1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 #ifndef MEMCACHED_ENGINE_H
3 #define MEMCACHED_ENGINE_H
4 
5 #ifndef __cplusplus
6 #include <stdbool.h>
7 #endif
8 
9 #include <sys/types.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 
13 #include "memcached/types.h"
14 #include "memcached/protocol_binary.h"
15 #include "memcached/config_parser.h"
16 #include "memcached/server_api.h"
17 #include "memcached/callback.h"
18 #include "memcached/allocator_hooks.h"
19 #include "memcached/extension.h"
20 #include "memcached/vbucket.h"
21 #include "memcached/engine_common.h"
22 #include "memcached/dcp.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
27 
28 /*! \mainpage memcached public API
29  *
30  * \section intro_sec Introduction
31  *
32  * The memcached project provides an API for providing engines as well
33  * as data definitions for those implementing the protocol in C.  This
34  * documentation will explain both to you.
35  *
36  * \section docs_sec API Documentation
37  *
38  * Jump right into <a href="modules.html">the modules docs</a> to get started.
39  *
40  * \example default_engine.c
41  */
42 
43 /**
44  * \defgroup Engine Storage Engine API
45  * \defgroup Protex Protocol Extension API
46  * \defgroup Protocol Binary Protocol Structures
47  *
48  * \addtogroup Engine
49  * @{
50  *
51  * Most interesting here is to implement engine_interface_v1 for your
52  * engine.
53  */
54 
55 #define ENGINE_INTERFACE_VERSION 1
56 
57 
58     /**
59      * Abstract interface to an engine.
60      */
61 #ifdef WIN32
62 #undef interface
63 #endif
64     struct item_observer_cb_data {
65         const void *key; /* THis isn't going to work from a memory management perspective */
66         size_t nkey;
67     };
68 
69     /* This is typedefed in types.h */
70     struct server_handle_v1_t {
71         uint64_t interface; /**< The version number on the server structure */
72         SERVER_CORE_API *core;
73         SERVER_STAT_API *stat;
74         SERVER_EXTENSION_API *extension;
75         SERVER_CALLBACK_API *callback;
76         ENGINE_HANDLE *engine;
77         SERVER_LOG_API *log;
78         SERVER_COOKIE_API *cookie;
79         ALLOCATOR_HOOKS_API *alloc_hooks;
80     };
81 
82     typedef enum { TAP_MUTATION = 1,
83                    TAP_DELETION,
84                    TAP_FLUSH,
85                    TAP_OPAQUE,
86                    TAP_VBUCKET_SET,
87                    TAP_ACK,
88                    TAP_DISCONNECT,
89                    TAP_NOOP,
90                    TAP_PAUSE,
91                    TAP_CHECKPOINT_START,
92                    TAP_CHECKPOINT_END } tap_event_t;
93 
94     /**
95      * An iterator for the tap stream.
96      * The memcached core will keep on calling this function as long as a tap
97      * client is connected to the server. Each event returned by the iterator
98      * will be encoded in the binary protocol with the appropriate command opcode.
99      *
100      * If the engine needs to store extra information in the tap stream it should
101      * do so by returning the data through the engine_specific pointer. This data
102      * should be valid for the core to use (read only) until the next invocation
103      * of the iterator, of if the connection is closed.
104      *
105      * @param handle the engine handle
106      * @param cookie identification for the tap stream
107      * @param item item to send returned here (check tap_event_t)
108      * @param engine_specific engine specific data returned here
109      * @param nengine_specific number of bytes of engine specific data
110      * @param ttl ttl for this item (Tap stream hops)
111      * @param flags tap flags for this object
112      * @param seqno sequence number to send
113      * @param vbucket the virtual bucket id
114      * @return the tap event to send (or TAP_PAUSE if there isn't any events)
115      */
116     typedef tap_event_t (*TAP_ITERATOR)(ENGINE_HANDLE* handle,
117                                         const void *cookie,
118                                         item **item,
119                                         void **engine_specific,
120                                         uint16_t *nengine_specific,
121                                         uint8_t *ttl,
122                                         uint16_t *flags,
123                                         uint32_t *seqno,
124                                         uint16_t *vbucket);
125 
126     typedef ENGINE_ERROR_CODE (*engine_get_vb_map_cb)(const void *cookie,
127                                                       const void *map,
128                                                       size_t mapsize);
129 
130     /**
131      * The signature for the "create_instance" function exported from the module.
132      *
133      * This function should fill out an engine inteface structure according to
134      * the interface parameter (Note: it is possible to return a lower version
135      * number).
136      *
137      * @param interface The highest interface level the server supports
138      * @param get_server_api function to get the server API from
139      * @param Where to store the interface handle
140      * @return See description of ENGINE_ERROR_CODE
141      */
142     typedef ENGINE_ERROR_CODE (*CREATE_INSTANCE)(uint64_t interface,
143                                                  GET_SERVER_API get_server_api,
144                                                  ENGINE_HANDLE** handle);
145 
146     typedef enum {
147         ENGINE_FEATURE_CAS, /**< has compare-and-set operation */
148         ENGINE_FEATURE_PERSISTENT_STORAGE, /**< has persistent storage support*/
149         ENGINE_FEATURE_SECONDARY_ENGINE, /**< performs as pseudo engine */
150         ENGINE_FEATURE_ACCESS_CONTROL, /**< has access control feature */
151         ENGINE_FEATURE_MULTI_TENANCY,
152         ENGINE_FEATURE_LRU, /* Cache implements an LRU */
153         ENGINE_FEATURE_VBUCKET, /* Cache implements virtual buckets */
154         ENGINE_FEATURE_DATATYPE /**< uses datatype field */
155 
156 #define LAST_REGISTERED_ENGINE_FEATURE ENGINE_FEATURE_VBUCKET
157     } engine_feature_t;
158 
159     typedef struct {
160         /**
161          * The identifier of this feature. All values with the most significant bit cleared is reserved
162          * for "registered" features.
163          */
164         uint32_t feature;
165         /**
166          * A textual description of the feature. (null will print the registered name for the feature
167          * (or "Unknown feature"))
168          */
169         const char *description;
170     } feature_info;
171 
172     typedef struct {
173         /**
174          * Textual description of this engine
175          */
176         const char *description;
177         /**
178          * The number of features the server provides
179          */
180         uint32_t num_features;
181         /**
182          * An array containing all of the features the engine supports
183          */
184         feature_info features[1];
185     } engine_info;
186 
187     /**
188      * Definition of the first version of the engine interface
189      */
190     typedef struct engine_interface_v1 {
191         /**
192          * Engine info.
193          */
194         struct engine_interface interface;
195 
196         /**
197          * Get a description of this engine.
198          *
199          * @param handle the engine handle
200          * @return a stringz description of this engine
201          */
202         const engine_info* (*get_info)(ENGINE_HANDLE* handle);
203 
204         /**
205          * Initialize an engine instance.
206          * This is called *after* creation, but before the engine may be used.
207          *
208          * @param handle the engine handle
209          * @param config_str configuration this engine needs to initialize itself.
210          */
211         ENGINE_ERROR_CODE (*initialize)(ENGINE_HANDLE* handle,
212                                         const char* config_str);
213 
214         /**
215          * Tear down this engine.
216          *
217          * @param handle the engine handle
218          * @param force the flag indicating the force shutdown or not.
219          */
220         void (*destroy)(ENGINE_HANDLE* handle, const bool force);
221 
222         /*
223          * Item operations.
224          */
225 
226         /**
227          * Allocate an item.
228          *
229          * @param handle the engine handle
230          * @param cookie The cookie provided by the frontend
231          * @param output variable that will receive the item
232          * @param key the item's key
233          * @param nkey the length of the key
234          * @param nbytes the number of bytes that will make up the
235          *        value of this item.
236          * @param flags the item's flags
237          * @param exptime the maximum lifetime of this item
238          *
239          * @return ENGINE_SUCCESS if all goes well
240          */
241         ENGINE_ERROR_CODE (*allocate)(ENGINE_HANDLE* handle,
242                                       const void* cookie,
243                                       item **item,
244                                       const void* key,
245                                       const size_t nkey,
246                                       const size_t nbytes,
247                                       const int flags,
248                                       const rel_time_t exptime,
249                                       uint8_t datatype);
250 
251         /**
252          * Remove an item.
253          *
254          * @param handle the engine handle
255          * @param cookie The cookie provided by the frontend
256          * @param key the key identifying the item to be removed
257          * @param nkey the length of the key
258          * @param vbucket the virtual bucket id
259          *
260          * @return ENGINE_SUCCESS if all goes well
261          */
262         ENGINE_ERROR_CODE (*remove)(ENGINE_HANDLE* handle,
263                                     const void* cookie,
264                                     const void* key,
265                                     const size_t nkey,
266                                     uint64_t* cas,
267                                     uint16_t vbucket);
268 
269         /**
270          * Indicate that a caller who received an item no longer needs
271          * it.
272          *
273          * @param handle the engine handle
274          * @param cookie The cookie provided by the frontend
275          * @param item the item to be released
276          */
277         void (*release)(ENGINE_HANDLE* handle, const
278                         void *cookie,
279                         item* item);
280 
281         /**
282          * Retrieve an item.
283          *
284          * @param handle the engine handle
285          * @param cookie The cookie provided by the frontend
286          * @param item output variable that will receive the located item
287          * @param key the key to look up
288          * @param nkey the length of the key
289          * @param vbucket the virtual bucket id
290          *
291          * @return ENGINE_SUCCESS if all goes well
292          */
293         ENGINE_ERROR_CODE (*get)(ENGINE_HANDLE* handle,
294                                  const void* cookie,
295                                  item** item,
296                                  const void* key,
297                                  const int nkey,
298                                  uint16_t vbucket);
299 
300         /**
301          * Store an item.
302          *
303          * @param handle the engine handle
304          * @param cookie The cookie provided by the frontend
305          * @param item the item to store
306          * @param cas the CAS value for conditional sets
307          * @param operation the type of store operation to perform.
308          * @param vbucket the virtual bucket id
309          *
310          * @return ENGINE_SUCCESS if all goes well
311          */
312         ENGINE_ERROR_CODE (*store)(ENGINE_HANDLE* handle,
313                                    const void *cookie,
314                                    item* item,
315                                    uint64_t *cas,
316                                    ENGINE_STORE_OPERATION operation,
317                                    uint16_t vbucket);
318 
319         /**
320          * Perform an increment or decrement operation on an item.
321          *
322          * @param handle the engine handle
323          * @param cookie The cookie provided by the frontend
324          * @param key the key to look up
325          * @param nkey the length of the key
326          * @param increment if true, increment the value, else decrement
327          * @param create if true, create the item if it's missing
328          * @param delta the amount to increment or decrement.
329          * @param initial when creating, specifies the initial value
330          * @param exptime when creating, specifies the expiration time
331          * @param cas output CAS value
332          * @param result output arithmetic value
333          * @param vbucket the virtual bucket id
334          *
335          * @return ENGINE_SUCCESS if all goes well
336          */
337         ENGINE_ERROR_CODE (*arithmetic)(ENGINE_HANDLE* handle,
338                                         const void* cookie,
339                                         const void* key,
340                                         const int nkey,
341                                         const bool increment,
342                                         const bool create,
343                                         const uint64_t delta,
344                                         const uint64_t initial,
345                                         const rel_time_t exptime,
346                                         uint64_t *cas,
347                                         uint8_t datatype,
348                                         uint64_t *result,
349                                         uint16_t vbucket);
350 
351         /**
352          * Flush the cache.
353          *
354          * @param handle the engine handle
355          * @param cookie The cookie provided by the frontend
356          * @param when time at which the flush should take effect
357          *
358          * @return ENGINE_SUCCESS if all goes well
359          */
360         ENGINE_ERROR_CODE (*flush)(ENGINE_HANDLE* handle,
361                                    const void* cookie, time_t when);
362 
363         /*
364          * Statistics
365          */
366 
367         /**
368          * Get statistics from the engine.
369          *
370          * @param handle the engine handle
371          * @param cookie The cookie provided by the frontend
372          * @param stat_key optional argument to stats
373          * @param nkey the length of the stat_key
374          * @param add_stat callback to feed results to the output
375          *
376          * @return ENGINE_SUCCESS if all goes well
377          */
378         ENGINE_ERROR_CODE (*get_stats)(ENGINE_HANDLE* handle,
379                                        const void* cookie,
380                                        const char* stat_key,
381                                        int nkey,
382                                        ADD_STAT add_stat);
383 
384         /**
385          * Reset the stats.
386          *
387          * @param handle the engine handle
388          * @param cookie The cookie provided by the frontend
389          */
390         void (*reset_stats)(ENGINE_HANDLE* handle, const void *cookie);
391 
392         /**
393          * Get an array of per-thread stats. This allows the engine to
394          * keep separate stats per cookie. Your implementation of this
395          * callback <b>must</b> return a memory area returned from the
396          * server API's new_stats. If all of your connections belong
397          * to the same "stats pool" you should set this callback to
398          * NULL.
399          *
400          * @param handle the engine handle
401          * @param cookie the cookie representing the connection
402          * @return A pointer to a stats structure (or NULL if allocation
403          *         failed)
404          */
405         void *(*get_stats_struct)(ENGINE_HANDLE* handle,
406                                   const void* cookie);
407 
408         /**
409          * Aggregate stats among all per-connection stats. This allows
410          * the engine to call the aggregation callback for a number of
411          * stat structures. You would normally not use this if you
412          * didn't implement a special get_stats_struct().
413          *
414          *
415          * @param handle the engine handle
416          * @param cookie the cookie representing the connection
417          * @param callback the callback function you should call for all
418          *        of the stats structures you want to include in the
419          *        aggregatioin.
420          * @param dest This is the second parameter to the callback
421          *        function.
422          * @return ENGINE_SUCCESS unless you had a failure
423           */
424         ENGINE_ERROR_CODE (*aggregate_stats)(ENGINE_HANDLE* handle,
425                                              const void* cookie,
426                                              void (*callback)(void*, void*),
427                                              void*);
428 
429 
430         /**
431          * Any unknown command will be considered engine specific.
432          *
433          * @param handle the engine handle
434          * @param cookie The cookie provided by the frontend
435          * @param request pointer to request header to be filled in
436          * @param response function to transmit data
437          *
438          * @return ENGINE_SUCCESS if all goes well
439          */
440         ENGINE_ERROR_CODE (*unknown_command)(ENGINE_HANDLE* handle,
441                                              const void* cookie,
442                                              protocol_binary_request_header *request,
443                                              ADD_RESPONSE response);
444 
445         /* TAP operations */
446 
447         /**
448          * Callback for all incoming TAP messages. It is up to the engine
449          * to determine what to do with the event. The core will create and send
450          * a TAP_ACK message if the flag section contains TAP_FLAG_SEND_ACK with
451          * the status byte mapped from the return code.
452          *
453          * @param handle the engine handle
454          * @param cookie identification for the tap stream
455          * @param engine_specific pointer to engine specific data (received)
456          * @param nengine_specific number of bytes of engine specific data
457          * @param ttl ttl for this item (Tap stream hops)
458          * @param tap_flags tap flags for this object
459          * @param tap_event the tap event from over the wire
460          * @param tap_seqno sequence number for this item
461          * @param key the key in the message
462          * @param nkey the number of bytes in the key
463          * @param flags the flags for the item
464          * @param exptime the expiry time for the object
465          * @param cas the cas for the item
466          * @param data the data for the item
467          * @param ndata the number of bytes in the object
468          * @param vbucket the virtual bucket for the object
469          * @return ENGINE_SUCCESS for success
470          */
471         ENGINE_ERROR_CODE (*tap_notify)(ENGINE_HANDLE* handle,
472                                         const void *cookie,
473                                         void *engine_specific,
474                                         uint16_t nengine,
475                                         uint8_t ttl,
476                                         uint16_t tap_flags,
477                                         tap_event_t tap_event,
478                                         uint32_t tap_seqno,
479                                         const void *key,
480                                         size_t nkey,
481                                         uint32_t flags,
482                                         uint32_t exptime,
483                                         uint64_t cas,
484                                         uint8_t datatype,
485                                         const void *data,
486                                         size_t ndata,
487                                         uint16_t vbucket);
488 
489         /**
490          * Get (or create) a Tap iterator for this connection.
491          * @param handle the engine handle
492          * @param cookie The connection cookie
493          * @param client The "name" of the client
494          * @param nclient The number of bytes in the client name
495          * @param flags Tap connection flags
496          * @param userdata Specific userdata the engine may know how to use
497          * @param nuserdata The size of the userdata
498          * @return a tap iterator to iterate through the event stream
499          */
500         TAP_ITERATOR (*get_tap_iterator)(ENGINE_HANDLE* handle, const void* cookie,
501                                          const void* client, size_t nclient,
502                                          uint32_t flags,
503                                          const void* userdata, size_t nuserdata);
504 
505         /**
506          * Set the CAS id on an item.
507          */
508         void (*item_set_cas)(ENGINE_HANDLE *handle, const void *cookie,
509                              item *item, uint64_t cas);
510 
511         /**
512          * Get information about an item.
513          *
514          * The loader of the module may need the pointers to the actual data within
515          * an item. Instead of having to create multiple functions to get each
516          * individual item, this function will get all of them.
517          *
518          * @param handle the engine that owns the object
519          * @param cookie connection cookie for this item
520          * @param item the item to request information about
521          * @param item_info
522          * @return true if successful
523          */
524         bool (*get_item_info)(ENGINE_HANDLE *handle,
525                               const void *cookie,
526                               const item* item,
527                               item_info *item_info);
528 
529         /**
530          * Set information of an item.
531          *
532          * Set updated item information.
533          *
534          * @param handle the engine that owns the object
535          * @param cookie connection cookie for this item
536          * @param item the item who's information is to be updated
537          * @param item_info
538          * @return true if successful
539          */
540         bool (*set_item_info)(ENGINE_HANDLE *handle,
541                               const void *cookie,
542                               item* item,
543                               const item_info *itm_info);
544 
545         /**
546          * Get extra error information for an operation.
547          *
548          * @param handle the engine handle
549          * @param cookie The connection cookie
550          * @param buffer Where to store the info
551          * @param buffsz The size of the buffer
552          * @return the number of bytes written to the buffer
553          */
554         size_t (*errinfo)(ENGINE_HANDLE *handle, const void* cookie,
555                           char *buffer, size_t buffsz);
556 
557         /**
558          * Get the vbucket map stored in the engine
559          *
560          * @param handle the engine handle
561          * @param cookie The connection cookie
562          * @param callback a function the engine may call to "return" the
563          *                 buffer.
564          * @return ENGINE_SUCCESS for success
565          */
566         ENGINE_ERROR_CODE (*get_engine_vb_map)(ENGINE_HANDLE* handle,
567                                                const void * cookie,
568                                                engine_get_vb_map_cb callback);
569 
570         struct dcp_interface dcp;
571     } ENGINE_HANDLE_V1;
572 
573     /**
574      * @}
575      */
576 #ifdef __cplusplus
577 }
578 #endif
579 
580 #endif
581