1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
6 #include "objclass/objclass.h"
8 #include "cls/version/cls_version_ops.h"
10 #include "include/compat.h"
16 #define VERSION_ATTR "ceph.objclass.version"
18 static int set_version(cls_method_context_t hctx
, struct obj_version
*objv
)
24 CLS_LOG(20, "cls_version: set_version %s:%d", objv
->tag
.c_str(), (int)objv
->ver
);
26 int ret
= cls_cxx_setxattr(hctx
, VERSION_ATTR
, &bl
);
33 static int init_version(cls_method_context_t hctx
, struct obj_version
*objv
)
36 char buf
[TAG_LEN
+ 1];
38 int ret
= cls_gen_rand_base64(buf
, sizeof(buf
));
45 CLS_LOG(20, "cls_version: init_version %s:%d", objv
->tag
.c_str(), (int)objv
->ver
);
47 return set_version(hctx
, objv
);
50 /* implicit create should be true only if called from a write operation (set, inc), never from a read operation (read, check) */
51 static int read_version(cls_method_context_t hctx
, obj_version
*objv
, bool implicit_create
)
54 int ret
= cls_cxx_getxattr(hctx
, VERSION_ATTR
, &bl
);
55 if (ret
== -ENOENT
|| ret
== -ENODATA
) {
58 if (implicit_create
) {
59 return init_version(hctx
, objv
);
67 bufferlist::iterator iter
= bl
.begin();
68 ::decode(*objv
, iter
);
69 } catch (buffer::error
& err
) {
70 CLS_LOG(0, "ERROR: read_version(): failed to decode version entry\n");
77 static int cls_version_set(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
79 bufferlist::iterator in_iter
= in
->begin();
81 cls_version_set_op op
;
83 ::decode(op
, in_iter
);
84 } catch (buffer::error
& err
) {
85 CLS_LOG(1, "ERROR: cls_version_get(): failed to decode entry\n");
89 int ret
= set_version(hctx
, &op
.objv
);
96 static bool check_conds(list
<obj_version_cond
>& conds
, obj_version
& objv
)
101 for (list
<obj_version_cond
>::iterator iter
= conds
.begin(); iter
!= conds
.end(); ++iter
) {
102 obj_version_cond
& cond
= *iter
;
103 obj_version
& v
= cond
.ver
;
104 CLS_LOG(20, "cls_version: check_version %s:%d (cond=%d)", v
.tag
.c_str(), (int)v
.ver
, (int)cond
.cond
);
110 if (!objv
.compare(&v
))
114 if (!(objv
.ver
> v
.ver
))
118 if (!(objv
.ver
>= v
.ver
))
122 if (!(objv
.ver
< v
.ver
))
126 if (!(objv
.ver
<= v
.ver
))
129 case VER_COND_TAG_EQ
:
130 if (objv
.tag
.compare(v
.tag
) != 0)
133 case VER_COND_TAG_NE
:
134 if (objv
.tag
.compare(v
.tag
) == 0)
143 static int cls_version_inc(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
145 bufferlist::iterator in_iter
= in
->begin();
147 cls_version_inc_op op
;
149 ::decode(op
, in_iter
);
150 } catch (buffer::error
& err
) {
151 CLS_LOG(1, "ERROR: cls_version_get(): failed to decode entry\n");
156 int ret
= read_version(hctx
, &objv
, true);
160 if (!check_conds(op
.conds
, objv
)) {
165 ret
= set_version(hctx
, &objv
);
172 static int cls_version_check(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
174 bufferlist::iterator in_iter
= in
->begin();
176 cls_version_check_op op
;
178 ::decode(op
, in_iter
);
179 } catch (buffer::error
& err
) {
180 CLS_LOG(1, "ERROR: cls_version_get(): failed to decode entry\n");
185 int ret
= read_version(hctx
, &objv
, false);
188 CLS_LOG(20, "cls_version: read_version %s:%d", objv
.tag
.c_str(), (int)objv
.ver
);
190 if (!check_conds(op
.conds
, objv
)) {
191 CLS_LOG(20, "cls_version: failed condition check");
198 static int cls_version_read(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
202 cls_version_read_ret read_ret
;
203 int ret
= read_version(hctx
, &read_ret
.objv
, false);
207 ::encode(read_ret
, *out
);
214 CLS_LOG(1, "Loaded version class!");
216 cls_handle_t h_class
;
217 cls_method_handle_t h_version_set
;
218 cls_method_handle_t h_version_inc
;
219 cls_method_handle_t h_version_inc_conds
;
220 cls_method_handle_t h_version_read
;
221 cls_method_handle_t h_version_check_conds
;
223 cls_register("version", &h_class
);
226 cls_register_cxx_method(h_class
, "set", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_version_set
, &h_version_set
);
227 cls_register_cxx_method(h_class
, "inc", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_version_inc
, &h_version_inc
);
228 cls_register_cxx_method(h_class
, "inc_conds", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_version_inc
, &h_version_inc_conds
);
229 cls_register_cxx_method(h_class
, "read", CLS_METHOD_RD
, cls_version_read
, &h_version_read
);
230 cls_register_cxx_method(h_class
, "check_conds", CLS_METHOD_RD
, cls_version_check
, &h_version_check_conds
);