MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
engine_loader.c
1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 #include "config.h"
3 #include <ctype.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <dlfcn.h>
7 #include "utilities/engine_loader.h"
8 #include <memcached/types.h>
9 
10 static const char * const feature_descriptions[] = {
11  "compare and swap",
12  "persistent storage",
13  "secondary engine",
14  "access control",
15  "multi tenancy",
16  "LRU"
17 };
18 
19 void *handle = NULL;
20 
21 bool load_engine(const char *soname,
22  SERVER_HANDLE_V1 *(*get_server_api)(void),
24  ENGINE_HANDLE **engine_handle)
25 {
26  ENGINE_HANDLE *engine = NULL;
27  /* Hack to remove the warning from C99 */
28  union my_hack {
29  CREATE_INSTANCE create;
30  void* voidptr;
31  } my_create = {.create = NULL };
32 
33  handle = dlopen(soname, RTLD_NOW | RTLD_LOCAL);
34  if (handle == NULL) {
35  const char *msg = dlerror();
36  logger->log(EXTENSION_LOG_WARNING, NULL,
37  "Failed to open library \"%s\": %s\n",
38  soname ? soname : "self",
39  msg ? msg : "unknown error");
40  return false;
41  }
42 
43  void *symbol = dlsym(handle, "create_instance");
44  if (symbol == NULL) {
45  logger->log(EXTENSION_LOG_WARNING, NULL,
46  "Could not find symbol \"create_instance\" in %s: %s\n",
47  soname ? soname : "self",
48  dlerror());
49  return false;
50  }
51  my_create.voidptr = symbol;
52 
53  /* request a instance with protocol version 1 */
54  ENGINE_ERROR_CODE error = (*my_create.create)(1, get_server_api, &engine);
55 
56  if (error != ENGINE_SUCCESS || engine == NULL) {
57  logger->log(EXTENSION_LOG_WARNING, NULL,
58  "Failed to create instance. Error code: %d\n", error);
59  dlclose(handle);
60  return false;
61  }
62  *engine_handle = engine;
63  return true;
64 }
65 
66 bool init_engine(ENGINE_HANDLE * engine,
67  const char *config_str,
69 {
70  ENGINE_HANDLE_V1 *engine_v1 = NULL;
71 
72  if (handle == NULL) {
73  logger->log(EXTENSION_LOG_WARNING, NULL,
74  "Failed to initialize engine, engine must fist be loaded.");
75  return false;
76  }
77 
78  if (engine->interface == 1) {
79  engine_v1 = (ENGINE_HANDLE_V1*)engine;
80 
81  // validate that the required engine interface is implemented:
82  if (engine_v1->get_info == NULL || engine_v1->initialize == NULL ||
83  engine_v1->destroy == NULL || engine_v1->allocate == NULL ||
84  engine_v1->remove == NULL || engine_v1->release == NULL ||
85  engine_v1->get == NULL || engine_v1->store == NULL ||
86  engine_v1->flush == NULL ||
87  engine_v1->get_stats == NULL || engine_v1->reset_stats == NULL ||
88  engine_v1->item_set_cas == NULL ||
89  engine_v1->get_item_info == NULL)
90  {
91  logger->log(EXTENSION_LOG_WARNING, NULL,
92  "Failed to initialize engine; it does not implement the engine interface.");
93  return false;
94  }
95 
96  ENGINE_ERROR_CODE error = engine_v1->initialize(engine,config_str);
97  if (error != ENGINE_SUCCESS) {
98  engine_v1->destroy(engine, false);
99  logger->log(EXTENSION_LOG_WARNING, NULL,
100  "Failed to initialize instance. Error code: %d\n",
101  error);
102  dlclose(handle);
103  return false;
104  }
105  } else {
106  logger->log(EXTENSION_LOG_WARNING, NULL,
107  "Unsupported interface level\n");
108  dlclose(handle);
109  return false;
110  }
111  return true;
112 }
113 
114 void log_engine_details(ENGINE_HANDLE * engine,
116 {
117  ENGINE_HANDLE_V1 *engine_v1 = (ENGINE_HANDLE_V1*)engine;
118  const engine_info *info;
119  info = engine_v1->get_info(engine);
120  if (info) {
121  char message[4096];
122  ssize_t nw = snprintf(message, sizeof(message), "Loaded engine: %s\n",
123  info->description ?
124  info->description : "Unknown");
125  if (nw == -1) {
126  return;
127  }
128  ssize_t offset = nw;
129  bool comma = false;
130 
131  if (info->num_features > 0) {
132  nw = snprintf(message + offset, sizeof(message) - offset,
133  "Supplying the following features: ");
134  if (nw == -1) {
135  return;
136  }
137  offset += nw;
138  for (int ii = 0; ii < info->num_features; ++ii) {
139  if (info->features[ii].description != NULL) {
140  nw = snprintf(message + offset, sizeof(message) - offset,
141  "%s%s", comma ? ", " : "",
142  info->features[ii].description);
143  } else {
144  if (info->features[ii].feature <= LAST_REGISTERED_ENGINE_FEATURE) {
145  nw = snprintf(message + offset, sizeof(message) - offset,
146  "%s%s", comma ? ", " : "",
147  feature_descriptions[info->features[ii].feature]);
148  } else {
149  nw = snprintf(message + offset, sizeof(message) - offset,
150  "%sUnknown feature: %d", comma ? ", " : "",
151  info->features[ii].feature);
152  }
153  }
154  comma = true;
155  if (nw == -1) {
156  return;
157  }
158  offset += nw;
159  }
160  }
161  logger->log(EXTENSION_LOG_INFO, NULL, "%s\n", message);
162  } else {
163  logger->log(EXTENSION_LOG_INFO, NULL,
164  "Loaded engine: Unknown\n");
165  }
166 }