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);