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;
141 if (use_time_boundary && index.compare(0, to_index.size(), to_index) >= 0) {
142 CLS_LOG(20, "DEBUG: cls_timeindex_list: finishing on to_index=%s",
144 ret.truncated = false;
148 cls_timeindex_entry e;
150 if (parse_index(index, e.key_ts, e.key_ext) < 0) {
151 CLS_LOG(0, "ERROR: cls_timeindex_list: could not parse index=%s",
154 CLS_LOG(20, "DEBUG: cls_timeindex_list: index=%s, key_ext=%s, bl.len = %d",
155 index.c_str(), e.key_ext.c_str(), bl.length());
157 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);