/*********************************************************************** Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA ***********************************************************************/ /**************************************************//** @file memcached_mysql.cc InnoDB Memcached Plugin Created 04/12/2011 Jimmy Yang *******************************************************/ #include "memcached_mysql.h" #include #include #include #include "sql_plugin.h" /** Configuration info passed to memcached, including the name of our Memcached InnoDB engine and memcached configure string to be loaded by memcached. */ struct mysql_memcached_context { pthread_t memcached_thread; memcached_context_t memcached_conf; }; /** Variables for configure options */ static char* mci_engine_library = NULL; static char* mci_eng_lib_path = NULL; static char* mci_memcached_option = NULL; static unsigned int mci_r_batch_size = 1048576; static unsigned int mci_w_batch_size = 32; static my_bool mci_enable_binlog = false; static MYSQL_SYSVAR_STR(engine_lib_name, mci_engine_library, PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC, "memcached engine library name", NULL, NULL, "innodb_engine.so"); static MYSQL_SYSVAR_STR(engine_lib_path, mci_eng_lib_path, PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC, "memcached engine library path", NULL, NULL, NULL); static MYSQL_SYSVAR_STR(option, mci_memcached_option, PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC, "memcached option string", NULL, NULL, NULL); static MYSQL_SYSVAR_UINT(r_batch_size, mci_r_batch_size, PLUGIN_VAR_READONLY, "read batch commit size", 0, 0, 1, 1, 1073741824, 0); static MYSQL_SYSVAR_UINT(w_batch_size, mci_w_batch_size, PLUGIN_VAR_READONLY, "write batch commit size", 0, 0, 1, 1, 1048576, 0); static MYSQL_SYSVAR_BOOL(enable_binlog, mci_enable_binlog, PLUGIN_VAR_READONLY, "whether to enable binlog", NULL, NULL, FALSE); static struct st_mysql_sys_var *daemon_memcached_sys_var[] = { MYSQL_SYSVAR(engine_lib_name), MYSQL_SYSVAR(engine_lib_path), MYSQL_SYSVAR(option), MYSQL_SYSVAR(r_batch_size), MYSQL_SYSVAR(w_batch_size), MYSQL_SYSVAR(enable_binlog), 0 }; static int daemon_memcached_plugin_deinit(void *p) { struct st_plugin_int* plugin = (struct st_plugin_int *)p; struct mysql_memcached_context* con = NULL; int loop_count = 0; /* If memcached plugin is still initializing, wait for a while.*/ while (!init_complete() && loop_count < 15 ) { sleep(1); loop_count++; } if (!init_complete()) { fprintf(stderr," InnoDB_Memcached: Memcached plugin is still" " initializing. Can't shut down it.\n"); return(0); } loop_count = 0; if (!shutdown_complete()) { shutdown_server(); } loop_count = 0; while (!shutdown_complete() && loop_count < 25) { sleep(2); loop_count++; } if(!shutdown_complete()) { fprintf(stderr," InnoDB_Memcached: Waited for 50 seconds" " for memcached thread to exit. Now force terminating" " the thread\n"); } con = (struct mysql_memcached_context*) (plugin->data); pthread_cancel(con->memcached_thread); if (con->memcached_conf.m_engine_library) { my_free(con->memcached_conf.m_engine_library); } my_free(con); return(0); } static int daemon_memcached_plugin_init(void *p) { struct mysql_memcached_context* con; pthread_attr_t attr; struct st_plugin_int* plugin = (struct st_plugin_int *)p; con = (mysql_memcached_context*) my_malloc(PSI_INSTRUMENT_ME, sizeof(*con), MYF(0)); if (mci_engine_library) { char* lib_path = (mci_eng_lib_path) ? mci_eng_lib_path : opt_plugin_dir; int lib_len = strlen(lib_path) + strlen(mci_engine_library) + strlen(FN_DIRSEP) + 1; con->memcached_conf.m_engine_library = (char*) my_malloc( PSI_INSTRUMENT_ME, lib_len, MYF(0)); strxmov(con->memcached_conf.m_engine_library, lib_path, FN_DIRSEP, mci_engine_library, NullS); } else { con->memcached_conf.m_engine_library = NULL; } con->memcached_conf.m_mem_option = mci_memcached_option; con->memcached_conf.m_innodb_api_cb = plugin->data; con->memcached_conf.m_r_batch_size = mci_r_batch_size; con->memcached_conf.m_w_batch_size = mci_w_batch_size; con->memcached_conf.m_enable_binlog = mci_enable_binlog; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); /* now create the thread */ if (pthread_create(&con->memcached_thread, &attr, daemon_memcached_main, (void *)&con->memcached_conf) != 0) { fprintf(stderr,"Could not create memcached daemon thread!\n"); exit(0); } plugin->data= (void *)con; return(0); } struct st_mysql_daemon daemon_memcached_plugin = {MYSQL_DAEMON_INTERFACE_VERSION}; mysql_declare_plugin(daemon_memcached) { MYSQL_DAEMON_PLUGIN, &daemon_memcached_plugin, "daemon_memcached", "Oracle Corporation", "Memcached Daemon", PLUGIN_LICENSE_GPL, daemon_memcached_plugin_init, /* Plugin Init */ daemon_memcached_plugin_deinit, /* Plugin Deinit */ 0x0100 /* 1.0 */, NULL, /* status variables */ daemon_memcached_sys_var, /* system variables */ NULL, /* config options */ 0 /* flags */ } mysql_declare_plugin_end;