1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 #ifndef MEMCACHED_EXTENSION_H
3 #define MEMCACHED_EXTENSION_H
4 
5 #ifndef __cplusplus
6 #include <stdbool.h>
7 #endif
8 
9 #include <stdint.h>
10 #include <memcached/engine_common.h>
11 #include <memcached/protocol_binary.h>
12 #include <memcached/types.h>
13 #include <memcached/server_api.h>
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19     /**
20      * \defgroup Extension Generic Extensions API
21      * \addtogroup Extension
22      * @{
23      *
24      * Definition of the generic extension API to memcached.
25      */
26 
27     /**
28      * Response codes for extension operations.
29      */
30     typedef enum {
31         /** The command executed successfully */
32         EXTENSION_SUCCESS     = 0x00,
33         /** A fatal error occurred, and the server should shut down as soon
34          * as possible */
35         EXTENSION_FATAL       = 0xfe,
36         /** Generic failure. */
37         EXTENSION_FAILED      = 0xff
38     } EXTENSION_ERROR_CODE;
39 
40     typedef enum {
41         /**
42          * A generic extention that don't provide a functionality to the
43          * memcached core, but lives in the memcached address space.
44          */
45         EXTENSION_DAEMON = 0x00,
46         /**
47          * A log consumer
48          */
49         EXTENSION_LOGGER,
50         /**
51          * Command extension for the ASCII protocol
52          */
53         EXTENSION_ASCII_PROTOCOL,
54         /**
55          * Command extension for the binary protocol
56          */
57         EXTENSION_BINARY_PROTOCOL
58     } extension_type_t;
59 
60     /**
61      * Deamon extensions should provide the following descriptor when
62      * they register themselves.
63      */
64     typedef struct extension_daemon_descriptor {
65         /**
66          * Get the name of the descriptor. The memory area returned by this
67          * function has to be valid until the descriptor is unregistered.
68          */
69         const char* (*get_name)(void);
70 
71         /**
72          * Deamon descriptors are stored in a linked list in the memcached
73          * core by using this pointer. Please do not modify this pointer
74          * by yourself until you have unregistered the descriptor.
75          * The <b>only</b> time it is safe for an extension to walk this
76          * list is during initialization of the modules.
77          */
78         struct extension_daemon_descriptor *next;
79     } EXTENSION_DAEMON_DESCRIPTOR;
80 
81     typedef enum {
82         EXTENSION_LOG_DETAIL,
83         EXTENSION_LOG_DEBUG,
84         EXTENSION_LOG_INFO,
85         EXTENSION_LOG_WARNING
86     } EXTENSION_LOG_LEVEL;
87 
88     /**
89      * Log extensions should provide the following rescriptor when
90      * they register themselves. Please note that if you register a log
91      * extension it will <u>replace</u> old one. If you want to be nice to
92      * the user you should allow your logger to be chained.
93      *
94      * Please note that the memcached server will <b>not</b> call the log
95      * function if the verbosity level is too low. This is a perfomance
96      * optimization from the core to avoid potential formatting of output
97      * that may be thrown away.
98      */
99     typedef struct {
100         /**
101          * Get the name of the descriptor. The memory area returned by this
102          * function has to be valid until the descriptor is unregistered.
103          */
104         const char* (*get_name)(void);
105 
106         /**
107          * Add an entry to the log.
108          * @param severity the severity for this log entry
109          * @param client_cookie the client we're serving (may be NULL if not
110          *                      known)
111          * @param fmt format string to add to the log
112          */
113         void (*log)(EXTENSION_LOG_LEVEL severity,
114                     const void* client_cookie,
115                     const char *fmt, ...);
116     } EXTENSION_LOGGER_DESCRIPTOR;
117 
118     typedef struct {
119         EXTENSION_LOGGER_DESCRIPTOR* (*get_logger)(void);
120         EXTENSION_LOG_LEVEL (*get_level)(void);
121         void (*set_level)(EXTENSION_LOG_LEVEL severity);
122     } SERVER_LOG_API;
123 
124     typedef struct {
125         char *value;
126         size_t length;
127     } token_t;
128 
129     /**
130      * ASCII protocol extensions must provide the following descriptor to
131      * extend the capabilities of the ascii protocol. The memcached core
132      * will probe each command in the order they are registered, so you should
133      * register the most likely command to be used first (or you could register
134      * only one descriptor and do a better dispatch routine inside your own
135      * implementation of accept / execute).
136      */
137     typedef struct extension_ascii_protocol_descriptor {
138         /**
139          * Get the name of the descriptor. The memory area returned by this
140          * function has to be valid until the descriptor is unregistered.
141          *
142          * @param cmd_cookie cookie registered with the command
143          */
144         const char* (*get_name)(const void *cmd_cookie);
145 
146         /**
147          * Called by the server to determine if the command in argc, argv should
148          * be process by this handler.
149          *
150          * If the command accepts out-of-band data (like add / append / prepend
151          * / replace / set), the command must set the datapointer and ndata
152          * to the number of bytes it want to read (remember to account for
153          * the trailing "\r\n" ;-))
154          *
155          * If you need extra data, you should copy all of the argc/argv info
156          * you may need to execute the command, because those parameters will
157          * be 0 and NULL when execute is invoked...
158          *
159          * @param cmd_cookie cookie registered with the command
160          * @param cookie identifying the client connection
161          * @param argc the number of arguments
162          * @param argv the argument vector
163          * @param ndata the number of bytes in out-of-band data (OUT)
164          * @param ptr where the core shall write the data (OUT)
165          * @param noreply is this a noreply command or not...
166          * @return true if the command should be handled by this command handler
167          */
168         bool (*accept)(const void *cmd_cookie,
169                        void *cookie,
170                        int argc,
171                        token_t *argv,
172                        size_t *ndata,
173                        char **ptr);
174 
175         /**
176          * execute the command.
177          *
178          * @param cmd_cookie cookie registered with the command
179          * @param cookie identifying the client connection
180          * @param argc the number of arguments
181          * @param argv the argument vector
182          * @param response_handler callback to add data to the return buffer
183          * @return Error code for the operation
184          */
185         ENGINE_ERROR_CODE (*execute)(const void *cmd_cookie,
186                                      const void *cookie,
187                                      int argc, token_t *argv,
188                                      ENGINE_ERROR_CODE (*response_handler)(const void *cookie,
189                                                                            int nbytes,
190                                                                            const char *dta));
191 
192         /**
193          * abort the command.
194          *
195          * @param cmd_cookie cookie registered with the command
196          * @param cookie identifying the client connection
197          */
198         void (*abort)(const void *cmd_cookie, const void *cookie);
199 
200         /**
201          * cookie for the command. This is the cookie passed to accept and
202          * execute, so that you can register the same functions for multiple
203          * commands (but tell them apart during invokations).
204          */
205         const void *cookie;
206 
207         /**
208          * Deamon descriptors are stored in a linked list in the memcached
209          * core by using this pointer. Please do not modify this pointer
210          * by yourself until you have unregistered the descriptor.
211          * The <b>only</b> time it is safe for an extension to walk this
212          * list is during initialization of the modules.
213          */
214         struct extension_ascii_protocol_descriptor *next;
215     } EXTENSION_ASCII_PROTOCOL_DESCRIPTOR;
216 
217 
218     typedef struct extension_binary_protocol_descriptor EXTENSION_BINARY_PROTOCOL_DESCRIPTOR;
219 
220     typedef ENGINE_ERROR_CODE (*BINARY_COMMAND_CALLBACK)(EXTENSION_BINARY_PROTOCOL_DESCRIPTOR *descriptor,
221                                                          ENGINE_HANDLE* handle,
222                                                          const void* cookie,
223                                                          protocol_binary_request_header *request,
224                                                          ADD_RESPONSE response);
225 
226     /**
227      * ASCII protocol extensions must provide the following descriptor to
228      * extend the capabilities of the ascii protocol. The memcached core
229      * will probe each command in the order they are registered, so you should
230      * register the most likely command to be used first (or you could register
231      * only one descriptor and do a better dispatch routine inside your own
232      * implementation of accept / execute).
233      */
234     struct extension_binary_protocol_descriptor {
235         /**
236          * Get the name of the descriptor. The memory area returned by this
237          * function has to be valid until the descriptor is unregistered.
238          */
239         const char* (*get_name)(void);
240 
241         void (*setup)(void (*add)(EXTENSION_BINARY_PROTOCOL_DESCRIPTOR *descriptor,
242                                   uint8_t cmd,
243                                   BINARY_COMMAND_CALLBACK new_handler));
244 
245         /**
246          * Deamon descriptors are stored in a linked list in the memcached
247          * core by using this pointer. Please do not modify this pointer
248          * by yourself until you have unregistered the descriptor.
249          * The <b>only</b> time it is safe for an extension to walk this
250          * list is during initialization of the modules.
251          */
252         struct extension_binary_protocol_descriptor *next;
253     };
254 
255     /**
256      * The signature for the "memcached_extensions_initialize" function
257      * exported from the loadable module.
258      *
259      * @param config configuration for this extension
260      * @param GET_SERVER_API pointer to a function to get a specific server
261      *                       API from. server_extension_api contains functions
262      *                       to register extensions.
263      * @return one of the error codes above.
264      */
265     typedef EXTENSION_ERROR_CODE (*MEMCACHED_EXTENSIONS_INITIALIZE)(const char *config, GET_SERVER_API get_server_api);
266 
267 
268     /**
269      * The API provided by the server to manipulate the list of server
270      * server extensions.
271      */
272     typedef struct {
273         /**
274          * Register an extension
275          *
276          * @param type The type of extension to register (ex: daemon, logger etc)
277          * @param extension The extension to register
278          * @return true if success, false otherwise
279          */
280         bool (*register_extension)(extension_type_t type, void *extension);
281 
282         /**
283          * Unregister an extension
284          *
285          * @param type The type of extension to unregister
286          * @param extension The extension to unregister
287          */
288         void (*unregister_extension)(extension_type_t type, void *extension);
289 
290         /**
291          * Get the registered extension for a certain type. This is useful
292          * if you would like to replace one of the handlers with your own
293          * extension to proxy functionality.
294          *
295          * @param type The type of extension to get
296          * @param extension Pointer to the registered event. Please note that
297          *        if the extension allows for multiple instances of the
298          *        extension there will be a "next" pointer inside the element
299          *        that can be used for object traversal.
300          */
301         void *(*get_extension)(extension_type_t type);
302     } SERVER_EXTENSION_API;
303 
304     /**
305      * @}
306      */
307 
308 #ifdef __cplusplus
309 }
310 #endif
311 
312 #endif
313