1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2013 Couchbase, Inc
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 
18 #ifndef SRC_CALLBACKS_H_
19 #define SRC_CALLBACKS_H_ 1
20 
21 #include "config.h"
22 
23 #include <string>
24 
25 #include "locks.h"
26 
27 class Item;
28 
29 class SeqnoRange {
30 public:
SeqnoRange(uint64_t st, uint64_t en)31     SeqnoRange(uint64_t st, uint64_t en)
32         : start(st), end(en) {}
33 
getStartSeqno()34     uint64_t getStartSeqno() {
35         return start;
36     }
37 
getEndSeqno()38     uint64_t getEndSeqno() {
39         return end;
40     }
41 
42 private:
43     uint64_t start;
44     uint64_t end;
45 };
46 
47 class CacheLookup {
48 public:
CacheLookup(std::string k, int64_t s, uint16_t vb)49     CacheLookup(std::string k, int64_t s, uint16_t vb) :
50         key(k), bySeqno(s), vbid(vb) {}
51 
~CacheLookup()52     ~CacheLookup() {}
53 
getKey()54     std::string& getKey() { return key; }
55 
getBySeqno()56     int64_t getBySeqno() { return bySeqno; }
57 
getVBucketId()58     uint16_t getVBucketId() { return vbid; }
59 private:
60     std::string key;
61     int64_t bySeqno;
62     uint16_t vbid;
63 };
64 
65 /**
66  * Value for callback for GET operations.
67  */
68 class GetValue {
69 public:
GetValue()70     GetValue() : value(NULL), id(-1),
71                  status(ENGINE_KEY_ENOENT),
72                  partial(false), nru(0xff) { }
73 
GetValue(Item *v, ENGINE_ERROR_CODE s=ENGINE_SUCCESS, uint64_t i = -1, bool incomplete = false, uint8_t _nru = 0xff)74     explicit GetValue(Item *v, ENGINE_ERROR_CODE s=ENGINE_SUCCESS,
75                       uint64_t i = -1,
76                       bool incomplete = false, uint8_t _nru = 0xff) :
77         value(v), id(i), status(s), partial(incomplete), nru(_nru) { }
78 
79     /**
80      * The value retrieved for the key.
81      */
getValue()82     Item* getValue() { return value; }
83 
84     /**
85      * Engine code describing what happened.
86      */
getStatus() const87     ENGINE_ERROR_CODE getStatus() const { return status; }
88 
89     /**
90      * Set the status code
91      */
setStatus(ENGINE_ERROR_CODE s)92     void setStatus(ENGINE_ERROR_CODE s) { status = s; }
93 
94     /**
95      * Get the item's underlying ID (if applicable).
96      */
getId()97     uint64_t getId() { return id; }
98 
99     /**
100      * Set the item's underlying ID.
101      */
setId(uint64_t newId)102     void setId(uint64_t newId) { id = newId; }
103 
isPartial() const104     bool isPartial() const { return partial; }
105 
setPartial()106     void setPartial() { partial = true; }
107 
getNRUValue() const108     uint8_t getNRUValue() const { return nru; }
109 
setValue(Item *i)110     void setValue(Item *i) { value = i; }
111 
112 private:
113 
114     Item* value;
115     uint64_t id;
116     ENGINE_ERROR_CODE status;
117     bool partial;
118     uint8_t nru;
119 };
120 
121 /**
122  * Interface for callbacks from storage APIs.
123  */
124 template <typename RV>
125 class Callback {
126 public:
127 
Callback()128     Callback() : myStatus(0) {}
129 
~Callback()130     virtual ~Callback() {}
131 
132     /**
133      * Method called on callback.
134      */
135     virtual void callback(RV &value) = 0;
136 
setStatus(int status)137     virtual void setStatus(int status) {
138         myStatus = status;
139     }
140 
getStatus()141     virtual int getStatus() {
142         return myStatus;
143     }
144 
145 private:
146 
147     int myStatus;
148 };
149 
150 /**
151  * Threadsafe callback implementation that just captures the value.
152  */
153 template <typename T>
154 class RememberingCallback : public Callback<T> {
155 public:
156 
157     /**
158      * Construct a remembering callback.
159      */
RememberingCallback()160     RememberingCallback() : fired(false), so() { }
161 
162     /**
163      * Clean up (including lock resources).
164      */
~RememberingCallback()165     ~RememberingCallback() {
166     }
167 
168     /**
169      * The callback implementation -- just store a value.
170      */
callback(T &value)171     void callback(T &value) {
172         LockHolder lh(so);
173         val = value;
174         fired = true;
175         so.notify();
176     }
177 
178     /**
179      * Wait for a value to be available.
180      *
181      * This method will return immediately if a value is currently
182      * available, otherwise it will wait indefinitely for a value
183      * to arrive.
184      */
waitForValue()185     void waitForValue() {
186         LockHolder lh(so);
187         if (!fired) {
188             so.wait();
189         }
190         cb_assert(fired);
191     }
192 
193     /**
194      * The value that was captured from the callback.
195      */
196     T    val;
197     /**
198      * True if the callback has fired.
199      */
200     bool fired;
201 
202 private:
203     SyncObject so;
204 
205     DISALLOW_COPY_AND_ASSIGN(RememberingCallback);
206 };
207 
208 template <typename T>
209 class TimedRememberingCallback : public RememberingCallback<T> {
210 public:
TimedRememberingCallback()211     TimedRememberingCallback() :
212         RememberingCallback<T>(), start(gethrtime()), stop(0)
213     { }
214 
~TimedRememberingCallback()215     ~TimedRememberingCallback() {
216     }
217 
callback(T &value)218     void callback(T &value) {
219         stop = gethrtime();
220         RememberingCallback<T>::callback(value);
221     }
222 
getDelta() const223     hrtime_t getDelta() const {
224         return stop - start;
225     }
226 
227 private:
228     hrtime_t start;
229     hrtime_t stop;
230 
231     DISALLOW_COPY_AND_ASSIGN(TimedRememberingCallback);
232 };
233 
234 #endif  // SRC_CALLBACKS_H_
235