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_timeindex_ops.h"
10 #include "include/compat.h"
15 static const size_t MAX_LIST_ENTRIES
= 1000;
16 static const size_t MAX_TRIM_ENTRIES
= 1000;
18 static const string TIMEINDEX_PREFIX
= "1_";
20 static void get_index_time_prefix(const utime_t
& ts
,
25 snprintf(buf
, sizeof(buf
), "%s%010ld.%06ld_", TIMEINDEX_PREFIX
.c_str(),
26 (long)ts
.sec(), (long)ts
.usec());
27 buf
[sizeof(buf
) - 1] = '\0';
32 static void get_index(cls_method_context_t hctx
,
33 const utime_t
& key_ts
,
34 const string
& key_ext
,
37 get_index_time_prefix(key_ts
, index
);
38 index
.append(key_ext
);
41 static int parse_index(const string
& index
,
48 int ret
= sscanf(index
.c_str(), "1_%d.%d_%255s", &sec
, &usec
, keyext
);
50 key_ts
= utime_t(sec
, usec
);
51 key_ext
= string(keyext
);
55 static int cls_timeindex_add(cls_method_context_t hctx
,
56 bufferlist
* const in
,
57 bufferlist
* const out
)
59 bufferlist::iterator in_iter
= in
->begin();
61 cls_timeindex_add_op op
;
63 ::decode(op
, in_iter
);
64 } catch (buffer::error
& err
) {
65 CLS_LOG(1, "ERROR: cls_timeindex_add_op(): failed to decode op");
69 for (list
<cls_timeindex_entry
>::iterator iter
= op
.entries
.begin();
70 iter
!= op
.entries
.end();
72 cls_timeindex_entry
& entry
= *iter
;
75 get_index(hctx
, entry
.key_ts
, entry
.key_ext
, index
);
77 CLS_LOG(20, "storing entry at %s", index
.c_str());
79 int ret
= cls_cxx_map_set_val(hctx
, index
, &entry
.value
);
88 static int cls_timeindex_list(cls_method_context_t hctx
,
89 bufferlist
* const in
,
90 bufferlist
* const out
)
92 bufferlist::iterator in_iter
= in
->begin();
94 cls_timeindex_list_op op
;
96 ::decode(op
, in_iter
);
97 } catch (buffer::error
& err
) {
98 CLS_LOG(1, "ERROR: cls_timeindex_list_op(): failed to decode op");
102 map
<string
, bufferlist
> keys
;
107 if (op
.marker
.empty()) {
108 get_index_time_prefix(op
.from_time
, from_index
);
110 from_index
= op
.marker
;
112 const bool use_time_boundary
= (op
.to_time
>= op
.from_time
);
114 if (use_time_boundary
) {
115 get_index_time_prefix(op
.to_time
, to_index
);
118 size_t max_entries
= op
.max_entries
;
119 if (max_entries
> MAX_LIST_ENTRIES
) {
120 max_entries
= MAX_LIST_ENTRIES
;
123 int rc
= cls_cxx_map_get_vals(hctx
, from_index
, TIMEINDEX_PREFIX
,
124 max_entries
+ 1, &keys
);
129 cls_timeindex_list_ret ret
;
131 list
<cls_timeindex_entry
>& entries
= ret
.entries
;
132 map
<string
, bufferlist
>::iterator iter
= keys
.begin();
137 for (size_t i
= 0; i
< max_entries
&& iter
!= keys
.end(); ++i
, ++iter
) {
138 const string
& index
= iter
->first
;
139 bufferlist
& bl
= iter
->second
;
142 if (use_time_boundary
&& index
.compare(0, to_index
.size(), to_index
) >= 0) {
143 CLS_LOG(20, "DEBUG: cls_timeindex_list: finishing on to_index=%s",
149 cls_timeindex_entry e
;
151 if (parse_index(index
, e
.key_ts
, e
.key_ext
) < 0) {
152 CLS_LOG(0, "ERROR: cls_timeindex_list: could not parse index=%s",
155 CLS_LOG(20, "DEBUG: cls_timeindex_list: index=%s, key_ext=%s, bl.len = %d",
156 index
.c_str(), e
.key_ext
.c_str(), bl
.length());
158 entries
.push_back(e
);
162 if (iter
== keys
.end()) {
167 ret
.truncated
= !done
;
175 static int cls_timeindex_trim(cls_method_context_t hctx
,
176 bufferlist
* const in
,
177 bufferlist
* const out
)
179 bufferlist::iterator in_iter
= in
->begin();
181 cls_timeindex_trim_op op
;
183 ::decode(op
, in_iter
);
184 } catch (buffer::error
& err
) {
185 CLS_LOG(1, "ERROR: cls_timeindex_trim: failed to decode entry");
189 map
<string
, bufferlist
> keys
;
194 if (op
.from_marker
.empty()) {
195 get_index_time_prefix(op
.from_time
, from_index
);
197 from_index
= op
.from_marker
;
200 if (op
.to_marker
.empty()) {
201 get_index_time_prefix(op
.to_time
, to_index
);
203 to_index
= op
.to_marker
;
206 int rc
= cls_cxx_map_get_vals(hctx
, from_index
, TIMEINDEX_PREFIX
,
207 MAX_TRIM_ENTRIES
, &keys
);
212 map
<string
, bufferlist
>::iterator iter
= keys
.begin();
214 bool removed
= false;
215 for (size_t i
= 0; i
< MAX_TRIM_ENTRIES
&& iter
!= keys
.end(); ++i
, ++iter
) {
216 const string
& index
= iter
->first
;
218 CLS_LOG(20, "index=%s to_index=%s", index
.c_str(), to_index
.c_str());
220 if (index
.compare(0, to_index
.size(), to_index
) > 0) {
221 CLS_LOG(20, "DEBUG: cls_timeindex_trim: finishing on to_index=%s",
226 CLS_LOG(20, "removing key: index=%s", index
.c_str());
228 int rc
= cls_cxx_map_remove_key(hctx
, index
);
230 CLS_LOG(1, "ERROR: cls_cxx_map_remove_key failed rc=%d", rc
);
246 CLS_LOG(1, "Loaded timeindex class!");
248 cls_handle_t h_class
;
249 cls_method_handle_t h_timeindex_add
;
250 cls_method_handle_t h_timeindex_list
;
251 cls_method_handle_t h_timeindex_trim
;
253 cls_register("timeindex", &h_class
);
256 cls_register_cxx_method(h_class
, "add", CLS_METHOD_RD
| CLS_METHOD_WR
,
257 cls_timeindex_add
, &h_timeindex_add
);
258 cls_register_cxx_method(h_class
, "list", CLS_METHOD_RD
,
259 cls_timeindex_list
, &h_timeindex_list
);
260 cls_register_cxx_method(h_class
, "trim", CLS_METHOD_RD
| CLS_METHOD_WR
,
261 cls_timeindex_trim
, &h_timeindex_trim
);