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 cls_timeindex_list_ret ret
;
125 int rc
= cls_cxx_map_get_vals(hctx
, from_index
, TIMEINDEX_PREFIX
,
126 max_entries
, &keys
, &ret
.truncated
);
131 list
<cls_timeindex_entry
>& entries
= ret
.entries
;
132 map
<string
, bufferlist
>::iterator iter
= keys
.begin();
136 for (; iter
!= keys
.end(); ++iter
) {
137 const string
& index
= iter
->first
;
138 bufferlist
& bl
= iter
->second
;
140 if (use_time_boundary
&& index
.compare(0, to_index
.size(), to_index
) >= 0) {
141 CLS_LOG(20, "DEBUG: cls_timeindex_list: finishing on to_index=%s",
143 ret
.truncated
= false;
147 cls_timeindex_entry e
;
149 if (parse_index(index
, e
.key_ts
, e
.key_ext
) < 0) {
150 CLS_LOG(0, "ERROR: cls_timeindex_list: could not parse index=%s",
153 CLS_LOG(20, "DEBUG: cls_timeindex_list: index=%s, key_ext=%s, bl.len = %d",
154 index
.c_str(), e
.key_ext
.c_str(), bl
.length());
156 entries
.push_back(e
);
169 static int cls_timeindex_trim(cls_method_context_t hctx
,
170 bufferlist
* const in
,
171 bufferlist
* const out
)
173 bufferlist::iterator in_iter
= in
->begin();
175 cls_timeindex_trim_op op
;
177 ::decode(op
, in_iter
);
178 } catch (buffer::error
& err
) {
179 CLS_LOG(1, "ERROR: cls_timeindex_trim: failed to decode entry");
183 map
<string
, bufferlist
> keys
;
188 if (op
.from_marker
.empty()) {
189 get_index_time_prefix(op
.from_time
, from_index
);
191 from_index
= op
.from_marker
;
194 if (op
.to_marker
.empty()) {
195 get_index_time_prefix(op
.to_time
, to_index
);
197 to_index
= op
.to_marker
;
202 int rc
= cls_cxx_map_get_vals(hctx
, from_index
, TIMEINDEX_PREFIX
,
203 MAX_TRIM_ENTRIES
, &keys
, &more
);
208 map
<string
, bufferlist
>::iterator iter
= keys
.begin();
210 bool removed
= false;
211 for (; iter
!= keys
.end(); ++iter
) {
212 const string
& index
= iter
->first
;
214 CLS_LOG(20, "index=%s to_index=%s", index
.c_str(), to_index
.c_str());
216 if (index
.compare(0, to_index
.size(), to_index
) > 0) {
217 CLS_LOG(20, "DEBUG: cls_timeindex_trim: finishing on to_index=%s",
222 CLS_LOG(20, "removing key: index=%s", index
.c_str());
224 int rc
= cls_cxx_map_remove_key(hctx
, index
);
226 CLS_LOG(1, "ERROR: cls_cxx_map_remove_key failed rc=%d", rc
);
242 CLS_LOG(1, "Loaded timeindex class!");
244 cls_handle_t h_class
;
245 cls_method_handle_t h_timeindex_add
;
246 cls_method_handle_t h_timeindex_list
;
247 cls_method_handle_t h_timeindex_trim
;
249 cls_register("timeindex", &h_class
);
252 cls_register_cxx_method(h_class
, "add", CLS_METHOD_RD
| CLS_METHOD_WR
,
253 cls_timeindex_add
, &h_timeindex_add
);
254 cls_register_cxx_method(h_class
, "list", CLS_METHOD_RD
,
255 cls_timeindex_list
, &h_timeindex_list
);
256 cls_register_cxx_method(h_class
, "trim", CLS_METHOD_RD
| CLS_METHOD_WR
,
257 cls_timeindex_trim
, &h_timeindex_trim
);