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
;
19 set
<string
> retired_refs
;
23 void encode(bufferlist
& bl
) const {
24 ENCODE_START(2, 1, bl
);
26 ::encode(retired_refs
, bl
);
30 void decode(bufferlist::iterator
& bl
) {
34 ::decode(retired_refs
, bl
);
39 WRITE_CLASS_ENCODER(obj_refcount
)
41 static string wildcard_tag
;
43 static int read_refcount(cls_method_context_t hctx
, bool implicit_ref
, obj_refcount
*objr
)
47 int ret
= cls_cxx_getxattr(hctx
, REFCOUNT_ATTR
, &bl
);
48 if (ret
== -ENODATA
) {
50 objr
->refs
[wildcard_tag
] = true;
58 bufferlist::iterator iter
= bl
.begin();
59 ::decode(*objr
, iter
);
60 } catch (buffer::error
& err
) {
61 CLS_LOG(0, "ERROR: read_refcount(): failed to decode refcount entry\n");
68 static int set_refcount(cls_method_context_t hctx
, const struct obj_refcount
& objr
)
74 int ret
= cls_cxx_setxattr(hctx
, REFCOUNT_ATTR
, &bl
);
81 static int cls_rc_refcount_get(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
83 bufferlist::iterator in_iter
= in
->begin();
85 cls_refcount_get_op op
;
87 ::decode(op
, in_iter
);
88 } catch (buffer::error
& err
) {
89 CLS_LOG(1, "ERROR: cls_rc_refcount_get(): failed to decode entry\n");
94 int ret
= read_refcount(hctx
, op
.implicit_ref
, &objr
);
98 CLS_LOG(10, "cls_rc_refcount_get() tag=%s\n", op
.tag
.c_str());
100 objr
.refs
[op
.tag
] = true;
102 ret
= set_refcount(hctx
, objr
);
109 static int cls_rc_refcount_put(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
111 bufferlist::iterator in_iter
= in
->begin();
113 cls_refcount_put_op op
;
115 ::decode(op
, in_iter
);
116 } catch (buffer::error
& err
) {
117 CLS_LOG(1, "ERROR: cls_rc_refcount_put(): failed to decode entry\n");
122 int ret
= read_refcount(hctx
, op
.implicit_ref
, &objr
);
126 if (objr
.refs
.empty()) {// shouldn't happen!
127 CLS_LOG(0, "ERROR: cls_rc_refcount_put() was called without any references!\n");
131 CLS_LOG(10, "cls_rc_refcount_put() tag=%s\n", op
.tag
.c_str());
134 map
<string
, bool>::iterator iter
= objr
.refs
.find(op
.tag
);
135 if (iter
!= objr
.refs
.end()) {
137 } else if (op
.implicit_ref
) {
138 iter
= objr
.refs
.find(wildcard_tag
);
139 if (iter
!= objr
.refs
.end()) {
145 objr
.retired_refs
.find(op
.tag
) != objr
.retired_refs
.end())
148 objr
.retired_refs
.insert(op
.tag
);
149 objr
.refs
.erase(iter
);
151 if (objr
.refs
.empty()) {
152 return cls_cxx_remove(hctx
);
155 ret
= set_refcount(hctx
, objr
);
162 static int cls_rc_refcount_set(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
164 bufferlist::iterator in_iter
= in
->begin();
166 cls_refcount_set_op op
;
168 ::decode(op
, in_iter
);
169 } catch (buffer::error
& err
) {
170 CLS_LOG(1, "ERROR: cls_refcount_set(): failed to decode entry\n");
174 if (!op
.refs
.size()) {
175 return cls_cxx_remove(hctx
);
179 list
<string
>::iterator iter
;
180 for (iter
= op
.refs
.begin(); iter
!= op
.refs
.end(); ++iter
) {
181 objr
.refs
[*iter
] = true;
184 int ret
= set_refcount(hctx
, objr
);
191 static int cls_rc_refcount_read(cls_method_context_t hctx
, bufferlist
*in
, bufferlist
*out
)
193 bufferlist::iterator in_iter
= in
->begin();
195 cls_refcount_read_op op
;
197 ::decode(op
, in_iter
);
198 } catch (buffer::error
& err
) {
199 CLS_LOG(1, "ERROR: cls_rc_refcount_read(): failed to decode entry\n");
205 cls_refcount_read_ret read_ret
;
206 int ret
= read_refcount(hctx
, op
.implicit_ref
, &objr
);
210 map
<string
, bool>::iterator iter
;
211 for (iter
= objr
.refs
.begin(); iter
!= objr
.refs
.end(); ++iter
) {
212 read_ret
.refs
.push_back(iter
->first
);
215 ::encode(read_ret
, *out
);
222 CLS_LOG(1, "Loaded refcount class!");
224 cls_handle_t h_class
;
225 cls_method_handle_t h_refcount_get
;
226 cls_method_handle_t h_refcount_put
;
227 cls_method_handle_t h_refcount_set
;
228 cls_method_handle_t h_refcount_read
;
230 cls_register("refcount", &h_class
);
233 cls_register_cxx_method(h_class
, "get", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_rc_refcount_get
, &h_refcount_get
);
234 cls_register_cxx_method(h_class
, "put", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_rc_refcount_put
, &h_refcount_put
);
235 cls_register_cxx_method(h_class
, "set", CLS_METHOD_RD
| CLS_METHOD_WR
, cls_rc_refcount_set
, &h_refcount_set
);
236 cls_register_cxx_method(h_class
, "read", CLS_METHOD_RD
, cls_rc_refcount_read
, &h_refcount_read
);