]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
7c673cae FG |
3 | /* |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2015 CERN | |
7 | * | |
8 | * Author: Joaquim Rocha <joaquim.rocha@cern.ch> | |
9 | * | |
10 | * This library is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU Lesser General Public | |
12 | * License as published by the Free Software Foundation; either | |
13 | * version 2.1 of the License, or (at your option) any later version. | |
14 | * | |
15 | */ | |
16 | ||
17 | /** \file | |
18 | * | |
19 | * This is an OSD class that implements methods for object numeric options on | |
20 | * its omap values. | |
21 | * | |
22 | */ | |
23 | ||
24 | #include "objclass/objclass.h" | |
25 | #include <errno.h> | |
7c673cae FG |
26 | #include <string> |
27 | #include <sstream> | |
28 | #include <cstdio> | |
29 | #include <include/compat.h> | |
30 | ||
31 | #define DECIMAL_PRECISION 10 | |
32 | ||
9f95a23c TL |
33 | using ceph::bufferlist; |
34 | using std::string; | |
35 | using ceph::decode; | |
36 | using ceph::encode; | |
37 | ||
7c673cae FG |
38 | CLS_VER(1,0) |
39 | CLS_NAME(numops) | |
40 | ||
41 | static int add(cls_method_context_t hctx, bufferlist *in, bufferlist *out) | |
42 | { | |
43 | string key, diff_str; | |
44 | ||
11fdf7f2 | 45 | auto iter = in->cbegin(); |
7c673cae | 46 | try { |
11fdf7f2 TL |
47 | decode(key, iter); |
48 | decode(diff_str, iter); | |
f67539c2 | 49 | } catch (const ceph::buffer::error &err) { |
7c673cae FG |
50 | CLS_LOG(20, "add: invalid decode of input"); |
51 | return -EINVAL; | |
52 | } | |
53 | ||
54 | char *end_ptr = 0; | |
55 | double difference = strtod(diff_str.c_str(), &end_ptr); | |
56 | ||
57 | if (end_ptr && *end_ptr != '\0') { | |
58 | CLS_ERR("add: invalid input value: %s", diff_str.c_str()); | |
59 | return -EINVAL; | |
60 | } | |
61 | ||
62 | bufferlist bl; | |
63 | int ret = cls_cxx_map_get_val(hctx, key, &bl); | |
64 | ||
65 | double value; | |
66 | ||
67 | if (ret == -ENODATA || bl.length() == 0) { | |
68 | value = 0; | |
69 | } else if (ret < 0) { | |
70 | if (ret != -ENOENT) { | |
71 | CLS_ERR("add: error reading omap key %s: %d", key.c_str(), ret); | |
72 | } | |
73 | return ret; | |
74 | } else { | |
75 | std::string stored_value(bl.c_str(), bl.length()); | |
76 | end_ptr = 0; | |
77 | value = strtod(stored_value.c_str(), &end_ptr); | |
78 | ||
79 | if (end_ptr && *end_ptr != '\0') { | |
80 | CLS_ERR("add: invalid stored value: %s", stored_value.c_str()); | |
81 | return -EBADMSG; | |
82 | } | |
83 | } | |
84 | ||
85 | value += difference; | |
86 | ||
87 | std::stringstream stream; | |
88 | stream << std::setprecision(DECIMAL_PRECISION) << value; | |
89 | ||
90 | bufferlist new_value; | |
91 | new_value.append(stream.str()); | |
92 | ||
93 | return cls_cxx_map_set_val(hctx, key, &new_value); | |
94 | } | |
95 | ||
96 | static int mul(cls_method_context_t hctx, bufferlist *in, bufferlist *out) | |
97 | { | |
98 | string key, diff_str; | |
99 | ||
11fdf7f2 | 100 | auto iter = in->cbegin(); |
7c673cae | 101 | try { |
11fdf7f2 TL |
102 | decode(key, iter); |
103 | decode(diff_str, iter); | |
f67539c2 | 104 | } catch (const ceph::buffer::error &err) { |
11fdf7f2 | 105 | CLS_LOG(20, "mul: invalid decode of input"); |
7c673cae FG |
106 | return -EINVAL; |
107 | } | |
108 | ||
109 | char *end_ptr = 0; | |
110 | double difference = strtod(diff_str.c_str(), &end_ptr); | |
111 | ||
112 | if (end_ptr && *end_ptr != '\0') { | |
11fdf7f2 | 113 | CLS_ERR("mul: invalid input value: %s", diff_str.c_str()); |
7c673cae FG |
114 | return -EINVAL; |
115 | } | |
116 | ||
117 | bufferlist bl; | |
118 | int ret = cls_cxx_map_get_val(hctx, key, &bl); | |
119 | ||
120 | double value; | |
121 | ||
122 | if (ret == -ENODATA || bl.length() == 0) { | |
123 | value = 0; | |
124 | } else if (ret < 0) { | |
125 | if (ret != -ENOENT) { | |
11fdf7f2 | 126 | CLS_ERR("mul: error reading omap key %s: %d", key.c_str(), ret); |
7c673cae FG |
127 | } |
128 | return ret; | |
129 | } else { | |
130 | std::string stored_value(bl.c_str(), bl.length()); | |
131 | end_ptr = 0; | |
132 | value = strtod(stored_value.c_str(), &end_ptr); | |
133 | ||
134 | if (end_ptr && *end_ptr != '\0') { | |
11fdf7f2 | 135 | CLS_ERR("mul: invalid stored value: %s", stored_value.c_str()); |
7c673cae FG |
136 | return -EBADMSG; |
137 | } | |
138 | } | |
139 | ||
140 | value *= difference; | |
141 | ||
142 | std::stringstream stream; | |
143 | stream << std::setprecision(DECIMAL_PRECISION) << value; | |
144 | ||
145 | bufferlist new_value; | |
146 | new_value.append(stream.str()); | |
147 | ||
148 | return cls_cxx_map_set_val(hctx, key, &new_value); | |
149 | } | |
150 | ||
151 | CLS_INIT(numops) | |
152 | { | |
153 | CLS_LOG(20, "loading cls_numops"); | |
154 | ||
155 | cls_handle_t h_class; | |
156 | cls_method_handle_t h_add; | |
157 | cls_method_handle_t h_mul; | |
158 | ||
159 | cls_register("numops", &h_class); | |
160 | ||
161 | cls_register_cxx_method(h_class, "add", | |
162 | CLS_METHOD_RD | CLS_METHOD_WR, | |
163 | add, &h_add); | |
164 | ||
165 | cls_register_cxx_method(h_class, "mul", | |
166 | CLS_METHOD_RD | CLS_METHOD_WR, | |
167 | mul, &h_mul); | |
168 | } |