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