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