1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
10 #include "include/types.h"
11 #include "include/utime.h"
12 #include "objclass/objclass.h"
13 #include "cls/refcount/cls_refcount_ops.h"
14 #include "common/Clock.h"
16 #include "global/global_context.h"
17 #include "include/compat.h"
23 #define REFCOUNT_ATTR "refcount"
26 map
<string
, bool> refs
;
30 void encode(bufferlist
& bl
) const {
31 ENCODE_START(1, 1, bl
);
36 void decode(bufferlist::iterator
& bl
) {
42 WRITE_CLASS_ENCODER(obj_refcount
)
44 static string wildcard_tag
;
46 static int read_refcount(cls_method_context_t hctx
, bool implicit_ref
, obj_refcount
*objr
)
50 int ret
= cls_cxx_getxattr(hctx
, REFCOUNT_ATTR
, &bl
);
51 if (ret
== -ENODATA
) {
53 objr
->refs
[wildcard_tag
] = true;
61 bufferlist::iterator iter
= bl
.begin();
62 ::decode(*objr
, iter
);
63 } catch (buffer::error
& err
) {
64 CLS_LOG(0, "ERROR: read_refcount(): failed to decode refcount entry\n");
71 static int set_refcount(cls_method_context_t hctx
, map
<string
, bool>& refs
)
74 struct obj_refcount objr
;
80 int ret
= cls_cxx_setxattr(hctx
, REFCOUNT_ATTR
, &bl
);
87 static int cls_rc_refcount_get(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
89 bufferlist::iterator in_iter
= in
->begin();
91 cls_refcount_get_op op
;
93 ::decode(op
, in_iter
);
94 } catch (buffer::error
& err
) {
95 CLS_LOG(1, "ERROR: cls_rc_refcount_get(): failed to decode entry\n");
100 int ret
= read_refcount(hctx
, op
.implicit_ref
, &objr
);
104 CLS_LOG(10, "cls_rc_refcount_get() tag=%s\n", op
.tag
.c_str());
106 objr
.refs
[op
.tag
] = true;
108 ret
= set_refcount(hctx
, objr
.refs
);
115 static int cls_rc_refcount_put(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
117 bufferlist::iterator in_iter
= in
->begin();
119 cls_refcount_put_op op
;
121 ::decode(op
, in_iter
);
122 } catch (buffer::error
& err
) {
123 CLS_LOG(1, "ERROR: cls_rc_refcount_put(): failed to decode entry\n");
128 int ret
= read_refcount(hctx
, op
.implicit_ref
, &objr
);
132 if (objr
.refs
.empty()) {// shouldn't happen!
133 CLS_LOG(0, "ERROR: cls_rc_refcount_put() was called without any references!\n");
137 CLS_LOG(10, "cls_rc_refcount_put() tag=%s\n", op
.tag
.c_str());
140 map
<string
, bool>::iterator iter
= objr
.refs
.find(op
.tag
);
141 if (iter
!= objr
.refs
.end()) {
143 } else if (op
.implicit_ref
) {
144 iter
= objr
.refs
.find(wildcard_tag
);
145 if (iter
!= objr
.refs
.end()) {
153 objr
.refs
.erase(iter
);
155 if (objr
.refs
.empty()) {
156 return cls_cxx_remove(hctx
);
159 ret
= set_refcount(hctx
, objr
.refs
);
166 static int cls_rc_refcount_set(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
168 bufferlist::iterator in_iter
= in
->begin();
170 cls_refcount_set_op op
;
172 ::decode(op
, in_iter
);
173 } catch (buffer::error
& err
) {
174 CLS_LOG(1, "ERROR: cls_refcount_set(): failed to decode entry\n");
178 if (!op
.refs
.size()) {
179 return cls_cxx_remove(hctx
);
183 list
<string
>::iterator iter
;
184 for (iter
= op
.refs
.begin(); iter
!= op
.refs
.end(); ++iter
) {
185 objr
.refs
[*iter
] = true;
188 int ret
= set_refcount(hctx
, objr
.refs
);
195 static int cls_rc_refcount_read(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
197 bufferlist::iterator in_iter
= in
->begin();
199 cls_refcount_read_op op
;
201 ::decode(op
, in_iter
);
202 } catch (buffer::error
& err
) {
203 CLS_LOG(1, "ERROR: cls_rc_refcount_read(): failed to decode entry\n");
209 cls_refcount_read_ret read_ret
;
210 int ret
= read_refcount(hctx
, op
.implicit_ref
, &objr
);
214 map
<string
, bool>::iterator iter
;
215 for (iter
= objr
.refs
.begin(); iter
!= objr
.refs
.end(); ++iter
) {
216 read_ret
.refs
.push_back(iter
->first
);
219 ::encode(read_ret
, *out
);
226 CLS_LOG(1, "Loaded refcount class!");
228 cls_handle_t h_class
;
229 cls_method_handle_t h_refcount_get
;
230 cls_method_handle_t h_refcount_put
;
231 cls_method_handle_t h_refcount_set
;
232 cls_method_handle_t h_refcount_read
;
234 cls_register("refcount", &h_class
);
237 cls_register_cxx_method(h_class
, "get", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_rc_refcount_get
, &h_refcount_get
);
238 cls_register_cxx_method(h_class
, "put", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_rc_refcount_put
, &h_refcount_put
);
239 cls_register_cxx_method(h_class
, "set", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_rc_refcount_set
, &h_refcount_set
);
240 cls_register_cxx_method(h_class
, "read", CLS_METHOD_RD
, cls_rc_refcount_read
, &h_refcount_read
);