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"
7 #include "cls/refcount/cls_refcount_ops.h"
9 #include "include/compat.h"
15 #define REFCOUNT_ATTR "refcount"
18 map
<string
, bool> refs
;
22 void encode(bufferlist
& bl
) const {
23 ENCODE_START(1, 1, bl
);
28 void decode(bufferlist::iterator
& bl
) {
34 WRITE_CLASS_ENCODER(obj_refcount
)
36 static string wildcard_tag
;
38 static int read_refcount(cls_method_context_t hctx
, bool implicit_ref
, obj_refcount
*objr
)
42 int ret
= cls_cxx_getxattr(hctx
, REFCOUNT_ATTR
, &bl
);
43 if (ret
== -ENODATA
) {
45 objr
->refs
[wildcard_tag
] = true;
53 bufferlist::iterator iter
= bl
.begin();
54 ::decode(*objr
, iter
);
55 } catch (buffer::error
& err
) {
56 CLS_LOG(0, "ERROR: read_refcount(): failed to decode refcount entry\n");
63 static int set_refcount(cls_method_context_t hctx
, map
<string
, bool>& refs
)
66 struct obj_refcount objr
;
72 int ret
= cls_cxx_setxattr(hctx
, REFCOUNT_ATTR
, &bl
);
79 static int cls_rc_refcount_get(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
81 bufferlist::iterator in_iter
= in
->begin();
83 cls_refcount_get_op op
;
85 ::decode(op
, in_iter
);
86 } catch (buffer::error
& err
) {
87 CLS_LOG(1, "ERROR: cls_rc_refcount_get(): failed to decode entry\n");
92 int ret
= read_refcount(hctx
, op
.implicit_ref
, &objr
);
96 CLS_LOG(10, "cls_rc_refcount_get() tag=%s\n", op
.tag
.c_str());
98 objr
.refs
[op
.tag
] = true;
100 ret
= set_refcount(hctx
, objr
.refs
);
107 static int cls_rc_refcount_put(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
109 bufferlist::iterator in_iter
= in
->begin();
111 cls_refcount_put_op op
;
113 ::decode(op
, in_iter
);
114 } catch (buffer::error
& err
) {
115 CLS_LOG(1, "ERROR: cls_rc_refcount_put(): failed to decode entry\n");
120 int ret
= read_refcount(hctx
, op
.implicit_ref
, &objr
);
124 if (objr
.refs
.empty()) {// shouldn't happen!
125 CLS_LOG(0, "ERROR: cls_rc_refcount_put() was called without any references!\n");
129 CLS_LOG(10, "cls_rc_refcount_put() tag=%s\n", op
.tag
.c_str());
132 map
<string
, bool>::iterator iter
= objr
.refs
.find(op
.tag
);
133 if (iter
!= objr
.refs
.end()) {
135 } else if (op
.implicit_ref
) {
136 iter
= objr
.refs
.find(wildcard_tag
);
137 if (iter
!= objr
.refs
.end()) {
145 objr
.refs
.erase(iter
);
147 if (objr
.refs
.empty()) {
148 return cls_cxx_remove(hctx
);
151 ret
= set_refcount(hctx
, objr
.refs
);
158 static int cls_rc_refcount_set(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
160 bufferlist::iterator in_iter
= in
->begin();
162 cls_refcount_set_op op
;
164 ::decode(op
, in_iter
);
165 } catch (buffer::error
& err
) {
166 CLS_LOG(1, "ERROR: cls_refcount_set(): failed to decode entry\n");
170 if (!op
.refs
.size()) {
171 return cls_cxx_remove(hctx
);
175 list
<string
>::iterator iter
;
176 for (iter
= op
.refs
.begin(); iter
!= op
.refs
.end(); ++iter
) {
177 objr
.refs
[*iter
] = true;
180 int ret
= set_refcount(hctx
, objr
.refs
);
187 static int cls_rc_refcount_read(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
189 bufferlist::iterator in_iter
= in
->begin();
191 cls_refcount_read_op op
;
193 ::decode(op
, in_iter
);
194 } catch (buffer::error
& err
) {
195 CLS_LOG(1, "ERROR: cls_rc_refcount_read(): failed to decode entry\n");
201 cls_refcount_read_ret read_ret
;
202 int ret
= read_refcount(hctx
, op
.implicit_ref
, &objr
);
206 map
<string
, bool>::iterator iter
;
207 for (iter
= objr
.refs
.begin(); iter
!= objr
.refs
.end(); ++iter
) {
208 read_ret
.refs
.push_back(iter
->first
);
211 ::encode(read_ret
, *out
);
218 CLS_LOG(1, "Loaded refcount class!");
220 cls_handle_t h_class
;
221 cls_method_handle_t h_refcount_get
;
222 cls_method_handle_t h_refcount_put
;
223 cls_method_handle_t h_refcount_set
;
224 cls_method_handle_t h_refcount_read
;
226 cls_register("refcount", &h_class
);
229 cls_register_cxx_method(h_class
, "get", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_rc_refcount_get
, &h_refcount_get
);
230 cls_register_cxx_method(h_class
, "put", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_rc_refcount_put
, &h_refcount_put
);
231 cls_register_cxx_method(h_class
, "set", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_rc_refcount_set
, &h_refcount_set
);
232 cls_register_cxx_method(h_class
, "read", CLS_METHOD_RD
, cls_rc_refcount_read
, &h_refcount_read
);