1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 #ifndef BUCKET_ENGINE_INTERNAL_H
3 #define BUCKET_ENGINE_INTERNAL_H
4 #include "config.h"
5 #include <memcached/engine.h>
6 #include "genhash.h"
7 #include "topkeys.h"
8 #include "bucket_engine.h"
9 
10 typedef union proxied_engine {
11     ENGINE_HANDLE    *v0;
12     ENGINE_HANDLE_V1 *v1;
13 } proxied_engine_t;
14 
15 typedef enum {
16     STATE_NULL,
17     STATE_RUNNING,
18     STATE_STOPPING,
19     STATE_STOPPED
20 } bucket_state_t;
21 
22 typedef struct proxied_engine_handle {
23     const char          *name;
24     size_t               name_len;
25     proxied_engine_t     pe;
26     void                *stats;
27     topkeys_t          **topkeys;
28     TAP_ITERATOR         tap_iterator;
29     bool                 tap_iterator_disabled;
30     /* ON_DISCONNECT handling */
31     volatile bool        wants_disconnects;
32     /* Force shutdown flag */
33     bool                 force_shutdown;
34     EVENT_CALLBACK       cb;
35     const void          *cb_data;
36     /* count of connections + 1 for hashtable reference + number of
37      * reserved connections for this bucket + number of temporary
38      * references created by find_bucket & frieds.
39      *
40      * count of connections is count of engine_specific instances
41      * having peh equal to this engine_handle. There's only one
42      * exception which is connections for which on_disconnect callback
43      * was called but which are kept alive by reserved > 0. For those
44      * connections we drop refcount in on_disconnect but keep peh
45      * field so that bucket_engine_release_cookie can decrement peh
46      * refcount.
47      *
48      * Handle itself can be freed when this drops to zero. This can
49      * only happen when bucket is deleted (but can happen later
50      * because some connection can hold pointer longer) */
51     volatile int         refcount;
52     volatile int clients; /* # of clients currently calling functions in the engine */
53     const void *cookie;
54     void *dlhandle;
55     volatile bucket_state_t state;
56 } proxied_engine_handle_t;
57 
58 #define ES_CONNECTED_FLAG 0x1000
59 
60 /**
61  * bucket_engine needs to store data specific to a given connection.
62  * In order to do that it utilize the "engine-specific" field for a
63  * cookie. Due to the fact that the underlying engine needs to be able
64  * to use the field as well, we need a holder-structure to contain
65  * the bucket-specific data and the underlying engine-specific data.
66  */
67 typedef struct engine_specific {
68     /** The engine this cookie is connected to */
69     proxied_engine_handle_t *peh;
70     /** The userdata stored by the underlying engine */
71     void *engine_specific;
72     /** The number of times the underlying engine tried to reserve
73      * this connection */
74     /* 0x1000 is added while we think memcached connection is
75      * alive. We'll decrement it when processing ON_DISCONNECT
76      * callback. */
77     int reserved;
78 } engine_specific_t;
79 
80 
81 struct bucket_engine {
82     ENGINE_HANDLE_V1 engine;
83     SERVER_HANDLE_V1 *upstream_server;
84     bool initialized;
85     bool has_default;
86     bool auto_create;
87     char *default_engine_path;
88     char *admin_user;
89     char *default_bucket_name;
90     char *default_bucket_config;
91     proxied_engine_handle_t default_engine;
92     cb_mutex_t engines_mutex;
93     genhash_t *engines;
94     GET_SERVER_API get_server_api;
95     SERVER_HANDLE_V1 server;
96     SERVER_CALLBACK_API callback_api;
97     SERVER_EXTENSION_API extension_api;
98     SERVER_COOKIE_API cookie_api;
99 
100     struct {
101         bool in_progress; /* Is the global shutdown in progress */
102         int bucket_counter; /* Number of treads currently running shutdown */
103         cb_mutex_t mutex;
104         cb_cond_t cond;
105         /* this condition signals either in_progress being true or
106          * some bucket's refcount being 0.
107          *
108          * This means that under some conditions (lots of buckets
109          * recently deleted but still have connections assigned on
110          * them) we'll have a bit of thundering herd problem, where
111          * too many bucket deletion threads are woken up
112          * needlessly. But that can be improved much later when and if
113          * we actually find this to be a problem. */
114         cb_cond_t refcount_cond;
115     } shutdown;
116 
117     union {
118       engine_info engine_info;
119       char buffer[sizeof(engine_info) +
120                   (sizeof(feature_info) * LAST_REGISTERED_ENGINE_FEATURE)];
121     } info;
122 
123     int topkeys;
124 };
125 
126 #endif
127