1 /* timed api wrapper methods */
2 
3 #if defined(__APPLE__)
4 #include <mach/mach_time.h>
5 #endif
6 #if defined(WIN32)
7 #include <Windows.h>
8 #else
9 #include <sys/time.h>
10 #endif
11 #if !defined(WIN32) && !defined(_WIN32)
12 #include <unistd.h>
13 #endif
14 
15 #include <stdlib.h>
16 #include <string.h>
17 #include <stdint.h>
18 #include <time.h>
19 
20 #include "libforestdb/forestdb.h"
21 #include "config.h"
22 #include "timing.h"
23 
timed_fdb_commit(fdb_file_handle *fhandle, bool walflush)24 ts_nsec timed_fdb_commit(fdb_file_handle *fhandle, bool walflush){
25 
26   ts_nsec start, end;
27   fdb_status status;
28 
29   start = get_monotonic_ts();
30   if(walflush){
31     status = fdb_commit(fhandle, FDB_COMMIT_MANUAL_WAL_FLUSH);
32   } else {
33     status = fdb_commit(fhandle, FDB_COMMIT_NORMAL);
34   }
35 
36   end = get_monotonic_ts();
37 
38   if(status == FDB_RESULT_SUCCESS){
39     return ts_diff(start, end);
40   } else {
41     return ERR_NS;
42   }
43 }
44 
timed_fdb_compact(fdb_file_handle *fhandle)45 ts_nsec timed_fdb_compact(fdb_file_handle *fhandle){
46 
47   ts_nsec start, end;
48   fdb_status status;
49 
50   start = get_monotonic_ts();
51   status = fdb_compact(fhandle, NULL);
52 
53   end = get_monotonic_ts();
54 
55   if(status == FDB_RESULT_SUCCESS){
56     return ts_diff(start, end);
57   } else {
58     return ERR_NS;
59   }
60 }
61 
timed_fdb_set(fdb_kvs_handle *kv, fdb_doc *doc)62 ts_nsec timed_fdb_set(fdb_kvs_handle *kv, fdb_doc *doc){
63 
64   ts_nsec start, end;
65   fdb_status status;
66 
67   start = get_monotonic_ts();
68   status = fdb_set(kv, doc);
69   end = get_monotonic_ts();
70 
71   if(status == FDB_RESULT_SUCCESS){
72     return ts_diff(start, end);
73   } else {
74     return ERR_NS;
75   }
76 }
77 
timed_fdb_get(fdb_kvs_handle *kv, fdb_doc *doc)78 ts_nsec timed_fdb_get(fdb_kvs_handle *kv, fdb_doc *doc){
79 
80   ts_nsec start, end;
81   fdb_status status;
82 
83   start = get_monotonic_ts();
84   status = fdb_get(kv, doc);
85   end = get_monotonic_ts();
86 
87   if(status == FDB_RESULT_SUCCESS){
88     return ts_diff(start, end);
89   } else {
90     return ERR_NS;
91   }
92 }
93 
timed_fdb_delete(fdb_kvs_handle *kv, fdb_doc *doc)94 ts_nsec timed_fdb_delete(fdb_kvs_handle *kv, fdb_doc *doc){
95 
96   ts_nsec start, end;
97   fdb_status status;
98 
99   start = get_monotonic_ts();
100   status = fdb_del(kv, doc);
101   end = get_monotonic_ts();
102 
103   if(status == FDB_RESULT_SUCCESS){
104     return ts_diff(start, end);
105   } else {
106     return ERR_NS;
107   }
108 }
109 
timed_fdb_snapshot(fdb_kvs_handle *kv, fdb_kvs_handle **snap_kv)110 ts_nsec timed_fdb_snapshot(fdb_kvs_handle *kv, fdb_kvs_handle **snap_kv){
111 
112     ts_nsec start, end;
113     fdb_status status;
114 
115     start = get_monotonic_ts();
116     status = fdb_snapshot_open(kv, snap_kv, FDB_SNAPSHOT_INMEM);
117     end = get_monotonic_ts();
118 
119     if(status == FDB_RESULT_SUCCESS){
120       return ts_diff(start, end);
121     } else {
122       return ERR_NS;
123     }
124 
125 }
126 
timed_fdb_kvs_close(fdb_kvs_handle *kv)127 ts_nsec timed_fdb_kvs_close(fdb_kvs_handle *kv){
128 
129     ts_nsec start, end;
130     fdb_status status;
131 
132     start = get_monotonic_ts();
133     status = fdb_kvs_close(kv);
134     end = get_monotonic_ts();
135 
136     if(status == FDB_RESULT_SUCCESS){
137       return ts_diff(start, end);
138     } else {
139       return ERR_NS;
140     }
141 
142 }
143 
timed_fdb_close(fdb_file_handle *fhandle)144 ts_nsec timed_fdb_close(fdb_file_handle *fhandle){
145 
146     ts_nsec start, end;
147     fdb_status status;
148 
149     start = get_monotonic_ts();
150     status = fdb_close(fhandle);
151     end = get_monotonic_ts();
152 
153     if(status == FDB_RESULT_SUCCESS){
154       return ts_diff(start, end);
155     } else {
156       return ERR_NS;
157     }
158 
159 }
160 
timed_fdb_shutdown()161 ts_nsec timed_fdb_shutdown(){
162 
163     ts_nsec start, end;
164     fdb_status status;
165 
166     start = get_monotonic_ts();
167     status = fdb_shutdown();
168     end = get_monotonic_ts();
169 
170     if(status == FDB_RESULT_SUCCESS){
171       return ts_diff(start, end);
172     } else {
173       return ERR_NS;
174     }
175 
176 }
177 
timed_fdb_iterator_init(fdb_kvs_handle *kv, fdb_iterator **it)178 ts_nsec timed_fdb_iterator_init(fdb_kvs_handle *kv, fdb_iterator **it){
179 
180     ts_nsec start, end;
181     fdb_status status;
182 
183     start = get_monotonic_ts();
184     status = fdb_iterator_init(kv, it, NULL, 0, NULL, 0, FDB_ITR_NONE);
185     end = get_monotonic_ts();
186 
187     if(status == FDB_RESULT_SUCCESS){
188       return ts_diff(start, end);
189     } else {
190       return ERR_NS;
191     }
192 
193 
194 }
195 
timed_fdb_iterator_get(fdb_iterator *it, fdb_doc **doc)196 ts_nsec timed_fdb_iterator_get(fdb_iterator *it, fdb_doc **doc){
197 
198     ts_nsec start, end;
199     fdb_status status;
200 
201     start = get_monotonic_ts();
202     status = fdb_iterator_get(it, doc);
203     end = get_monotonic_ts();
204 
205     if(status == FDB_RESULT_SUCCESS){
206       return ts_diff(start, end);
207     } else {
208       return ERR_NS;
209     }
210 
211 }
212 
timed_fdb_iterator_next(fdb_iterator *it)213 ts_nsec timed_fdb_iterator_next(fdb_iterator *it){
214 
215     ts_nsec start, end;
216     fdb_status status;
217 
218     start = get_monotonic_ts();
219     status = fdb_iterator_next(it);
220     end = get_monotonic_ts();
221 
222     if(status == FDB_RESULT_SUCCESS){
223       return ts_diff(start, end);
224     } else {
225       return ERR_NS;
226     }
227 
228 }
229 
timed_fdb_iterator_close(fdb_iterator *it)230 ts_nsec timed_fdb_iterator_close(fdb_iterator *it){
231 
232     ts_nsec start, end;
233     fdb_status status;
234 
235     start = get_monotonic_ts();
236     status = fdb_iterator_close(it);
237     end = get_monotonic_ts();
238 
239     if(status == FDB_RESULT_SUCCESS){
240       return ts_diff(start, end);
241     } else {
242       return ERR_NS;
243     }
244 
245 }
246 
247 /*
248     return a monotonically increasing value with a seconds frequency.
249 */
get_monotonic_ts()250 ts_nsec get_monotonic_ts() {
251     ts_nsec ts = 0;
252 #if defined(WIN32)
253     /* GetTickCound64 gives us near 60years of ticks...*/
254     ts =  GetTickCount64() * 1000;  // TODO: this is not true high-res microseconds on windows
255 #elif defined(__APPLE__)
256     long time = mach_absolute_time();
257 
258     static mach_timebase_info_data_t timebase;
259     if (timebase.denom == 0) {
260       mach_timebase_info(&timebase);
261     }
262 
263     ts = (double)time * timebase.numer / timebase.denom;
264 #elif defined(__linux__) || defined(__sun) || defined(__FreeBSD__)
265     /* Linux and Solaris can use clock_gettime */
266     struct timespec tm;
267     if (clock_gettime(CLOCK_MONOTONIC, &tm) == -1) {
268         abort();
269     }
270     ts = tm.tv_nsec;
271 #else
272 #error "Don't know how to build get_monotonic_ts"
273 #endif
274 
275     return ts;
276 }
277 
ts_diff(ts_nsec start, ts_nsec end)278 ts_nsec ts_diff(ts_nsec start, ts_nsec end)
279 {
280     ts_nsec diff = 0;
281     if ((end-start)<0) {
282         diff  = 1000000000+end-start;
283     } else {
284         diff = end-start;
285     }
286     return diff/1000;
287 }
288