1
/* Copyright (c) 2010 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
* PBMS daemon global parameters.
30
#include <drizzled/common.h>
31
#include <drizzled/plugin.h>
32
#include <drizzled/session.h>
33
using namespace drizzled;
34
using namespace drizzled::plugin;
36
#define my_strdup(a,b) strdup(a)
38
#include "cslib/CSConfig.h"
40
#include "cslib/CSConfig.h"
41
#include "mysql_priv.h"
42
#include <mysql/plugin.h>
48
#include "cslib/CSDefs.h"
49
#include "cslib/CSObject.h"
50
#include "cslib/CSGlobal.h"
51
#include "cslib/CSThread.h"
52
#include "cslib/CSStrUtil.h"
53
#include "cslib/CSPath.h"
54
#include "cslib/CSLog.h"
57
#include "database_ms.h"
58
#include "parameters_ms.h"
61
#define PBMS_PORT 8080
65
static int my_port_number = PBMS_PORT;
67
static char *my_repository_threshold = NULL;
68
static char *my_temp_log_threshold = NULL;
69
static char *my_http_metadata_headers = NULL;
71
static u_long my_temp_blob_timeout = MS_DEFAULT_TEMP_LOG_WAIT;
72
static u_long my_garbage_threshold = MS_DEFAULT_GARBAGE_LEVEL;
73
static u_long my_max_keep_alive = MS_DEFAULT_KEEP_ALIVE;
75
static uint64_t my_backup_db_id = 1;
76
static uint32_t my_server_id = 1;
79
static set<string> my_black_list;
80
static bool my_events_enabled = true;
81
static CSMutex my_table_list_lock;
83
typedef enum {MATCH_ALL, MATCH_DBS, MATCH_SOME, MATCH_NONE, MATCH_UNKNOWN, MATCH_ERROR} TableMatchState;
84
static char *my_table_list = NULL;
85
static const char *dflt_my_table_list = "*";
87
static TableMatchState my_table_match = MATCH_UNKNOWN;
89
static int32_t my_before_insert_position= 1; // Call this event observer first.
90
static int32_t my_before_update_position= 1;
92
using namespace drizzled;
93
using namespace drizzled::plugin;
95
#define st_mysql_sys_var drizzled::drizzle_sys_var
98
struct st_mysql_sys_var
100
MYSQL_PLUGIN_VAR_HEADER;
105
#if MYSQL_VERSION_ID < 60000
107
#if MYSQL_VERSION_ID >= 50124
108
#define CONST_SAVE const
113
#if MYSQL_VERSION_ID >= 60005
114
#define CONST_SAVE const
124
uint32_t PBMSParameters::getPortNumber(){ return my_port_number;}
127
uint32_t PBMSParameters::getServerID(){ return my_server_id;}
130
uint64_t PBMSParameters::getRepoThreshold()
132
if (my_repository_threshold)
133
return((uint64_t) cs_byte_size_to_int8(my_repository_threshold));
135
return((uint64_t) cs_byte_size_to_int8(MS_REPO_THRESHOLD_DEF));
139
uint64_t PBMSParameters::getTempLogThreshold()
141
if (my_temp_log_threshold)
142
return((uint64_t) cs_byte_size_to_int8(my_temp_log_threshold));
144
return((uint64_t) cs_byte_size_to_int8(MS_TEMP_LOG_THRESHOLD_DEF));
148
uint32_t PBMSParameters::getTempBlobTimeout(){ return my_temp_blob_timeout;}
151
uint32_t PBMSParameters::getGarbageThreshold(){ return my_garbage_threshold;}
154
uint32_t PBMSParameters::getMaxKeepAlive(){ return my_max_keep_alive;}
157
const char * PBMSParameters::getDefaultMetaDataHeaders()
159
if (my_http_metadata_headers)
160
return my_http_metadata_headers;
162
return MS_HTTP_METADATA_HEADERS_DEF;
166
uint64_t PBMSParameters::getBackupDatabaseID() { return my_backup_db_id;}
169
void PBMSParameters::setBackupDatabaseID(uint64_t id) { my_backup_db_id = id;}
173
bool PBMSParameters::isPBMSEventsEnabled() { return my_events_enabled;}
176
#define NEXT_IN_TABLE_LIST(list) {\
177
while ((*list) && (*list != ',')) list++;\
181
static TableMatchState set_match_type(const char *list)
183
const char *ptr = list;
186
TableMatchState match_state;
195
while ((*ptr) && isspace(*ptr)) ptr++;
200
match_state = MATCH_UNKNOWN;
204
// Check database name
207
while ((*ptr) && (!isspace(*ptr)) && (*ptr != ',') && (*ptr != '.')) {ptr++;name_len++;}
208
while ((*ptr) && isspace(*ptr)) ptr++;
211
if ((name_len == 1) && (*name == '*'))
212
match_state = MATCH_ALL;
214
goto bad_list; // Missing table
217
if ((match_state > MATCH_DBS) && (name_len == 1) && (*name == '*'))
218
match_state = MATCH_DBS;
220
ptr++; // Skip the '.'
222
// Find the start of the table name.
223
while ((*ptr) && isspace(*ptr)) ptr++;
224
if ((!*ptr) || (*ptr == ',') || (*ptr == '.'))
225
goto bad_list; // Missing table
227
// Find the end of the table name.
228
while ((*ptr) && (!isspace(*ptr)) && (*ptr != ',') && (*ptr != '.')) ptr++;
231
// Locate the end of the element.
232
while ((*ptr) && isspace(*ptr)) ptr++;
234
if ((*ptr) && (*ptr != ','))
235
goto bad_list; // Bad table name
237
if (match_state > MATCH_SOME)
238
match_state = MATCH_SOME;
241
while ((*ptr) && isspace(*ptr)) ptr++;
248
snprintf(info, 120, "pbms_watch_tables format error near character position %d", (int) (ptr - list));
249
CSL.logLine(NULL, CSLog::Error, info);
250
CSL.logLine(NULL, CSLog::Error, list);
256
static const char* locate_db(const char *list, const char *db, int len)
261
while ((*list) && isspace(*list)) list++;
262
if ((*list == 0) || (*(list+1) == 0) || (*(list+2) == 0)) // We need at least 3 characters
268
else if (strncmp(list, db, len) == 0)
275
while ((*list) && isspace(*list)) list++;
276
if ((*list == 0) || (*(list+1) == 0) ) // We need at least 2 characters
281
while ((*list) && isspace(*list)) list++;
285
return list; // We have gound a table that could belong to this database;
289
NEXT_IN_TABLE_LIST(list);
296
// Parameter update functions are not called for parameters that are set on
297
// the command line. PBMSParameters::startUp() will perform any initialization required.
298
void PBMSParameters::startUp()
300
my_table_match = set_match_type(my_table_list);
304
bool PBMSParameters::isBlackListedDB(const char *db)
306
if (my_black_list.find(string(db)) == my_black_list.end())
313
void PBMSParameters::blackListedDB(const char *db)
315
my_black_list.insert(string(db));
319
bool PBMSParameters::isBLOBDatabase(const char *db)
323
PBMSResultRec result;
326
if (isBlackListedDB(db))
329
if (my_table_match == MATCH_UNKNOWN)
330
my_table_match = set_match_type(my_table_list);
332
if (my_table_match == MATCH_NONE)
335
if (my_table_match <= MATCH_DBS)
338
if ((err = MSEngine::enterConnectionNoThd(&self, &result)) == 0) {
342
lock_(&my_table_list_lock);
345
found = (locate_db(my_table_list, db, strlen(db)) != NULL);
347
unlock_(&my_table_list_lock);
351
err = MSEngine::exceptionToResult(&self->myException, &result);
359
fprintf(stderr, "PBMSParameters::isBLOBDatabase(\"%s\") error (%d):'%s'\n",
360
db, result.mr_code, result.mr_message);
367
bool PBMSParameters::isBLOBTable(const char *db, const char *table)
371
PBMSResultRec result;
374
int db_len, table_len, match_len;
376
if (isBlackListedDB(db))
379
if (my_table_match == MATCH_UNKNOWN)
380
my_table_match = set_match_type(my_table_list);
382
if (my_table_match == MATCH_NONE)
385
if (my_table_match <= MATCH_ALL)
388
if ((err = MSEngine::enterConnectionNoThd(&self, &result)) == 0) {
392
lock_(&my_table_list_lock);
395
table_len = strlen(table);
399
ptr = locate_db(ptr, db, db_len);
404
else if (strncmp(ptr, table, table_len) == 0)
405
match_len = table_len;
409
if ((!*ptr) || (*ptr == ',') || isspace(*ptr)) {
415
NEXT_IN_TABLE_LIST(ptr);
419
unlock_(&my_table_list_lock);
422
err = MSEngine::exceptionToResult(&self->myException, &result);
430
fprintf(stderr, "PBMSParameters::isBLOBTable(\"%s\", \"%s\") error (%d):'%s'\n",
431
db, table, result.mr_code, result.mr_message);
439
int32_t PBMSParameters::getBeforeUptateEventPosition() { return my_before_update_position;}
442
int32_t PBMSParameters::getBeforeInsertEventPosition() { return my_before_insert_position;}
446
static void pbms_temp_blob_timeout_func(THD *, struct st_mysql_sys_var *, void *, CONST_SAVE void *)
449
PBMSResultRec result;
451
if (MSEngine::enterConnectionNoThd(&self, &result))
454
MSDatabase::wakeTempLogThreads();
463
static MYSQL_SYSVAR_INT(port, my_port_number,
464
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
465
"The port for the server stream-based communications.",
466
NULL, NULL, PBMS_PORT, 0, 64*1024, 1);
468
static MYSQL_SYSVAR_STR(repository_threshold, my_repository_threshold,
469
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
470
"The maximum size of a BLOB repository file.",
471
NULL, NULL, MS_REPO_THRESHOLD_DEF);
473
static MYSQL_SYSVAR_STR(temp_log_threshold, my_temp_log_threshold,
474
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
475
"The maximum size of a temorary BLOB log file.",
476
NULL, NULL, MS_TEMP_LOG_THRESHOLD_DEF);
478
static MYSQL_SYSVAR_STR(http_metadata_headers, my_http_metadata_headers,
479
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
480
"A ':' delimited list of metadata header names to be used to initialize the pbms_metadata_header table when a database is created.",
481
NULL, NULL , MS_HTTP_METADATA_HEADERS_DEF);
483
static MYSQL_SYSVAR_ULONG(temp_blob_timeout, my_temp_blob_timeout,
485
"The timeout, in seconds, for temporary BLOBs. Uploaded blob data is removed after this time, unless committed to the database.",
486
NULL, pbms_temp_blob_timeout_func, MS_DEFAULT_TEMP_LOG_WAIT, 1, ~0L, 1);
488
static MYSQL_SYSVAR_ULONG(garbage_threshold, my_garbage_threshold,
490
"The percentage of garbage in a repository file before it is compacted.",
491
NULL, NULL, MS_DEFAULT_GARBAGE_LEVEL, 0, 100, 1);
494
static MYSQL_SYSVAR_ULONG(max_keep_alive, my_max_keep_alive,
496
"The timeout, in milli-seconds, before the HTTP server will close an inactive HTTP connection.",
497
NULL, NULL, MS_DEFAULT_KEEP_ALIVE, 1, UINT32_MAX, 1);
499
static MYSQL_SYSVAR_ULONGLONG(next_backup_db_id, my_backup_db_id,
501
"The next backup ID to use when backing up a PBMS database.",
502
NULL, NULL, 1, 1, UINT64_MAX, 1);
508
static int check_table_list(THD *, struct st_mysql_sys_var *, void *save, drizzle_value *value)
512
const char *list = value->val_str(value, buffer, &len);
513
TableMatchState state;
515
state = set_match_type(list);
516
if (state == MATCH_ERROR)
519
char *new_list = strdup(list);
523
my_table_list_lock.lock();
524
if (my_table_list && (my_table_list != dflt_my_table_list)) free(my_table_list);
525
my_table_list = new_list;
527
my_table_match = state;
528
my_table_list_lock.unlock();
530
*static_cast<const char**>(save)= my_table_list;
536
static void set_table_list(THD *, struct st_mysql_sys_var *, void *var_ptr, CONST_SAVE void *)
538
// Everything was done in check_table_list()
539
*static_cast<const char**>(var_ptr)= my_table_list;
544
static MYSQL_SYSVAR_STR(watch_tables,
546
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
547
N_("A comma delimited list of tables to watch of the format: <database>.<table>, ..."),
548
check_table_list, /* check func */
549
set_table_list, /* update func */
550
dflt_my_table_list /* default */);
552
static MYSQL_SYSVAR_BOOL(watch_enable,
555
N_("Enable PBMS daemon Insert/Update/Delete event scanning"),
556
NULL, /* check func */
557
NULL, /* update func */
560
static MYSQL_SYSVAR_INT(before_insert_position,
561
my_before_insert_position,
563
N_("Before insert row event observer call position"),
564
NULL, /* check func */
565
NULL, /* update func */
568
INT32_MAX -1, /* max */
571
static MYSQL_SYSVAR_INT(before_update_position,
572
my_before_update_position,
574
N_("Before update row event observer call position"),
575
NULL, /* check func */
576
NULL, /* update func */
579
INT32_MAX -1, /* max */
584
struct st_mysql_sys_var* pbms_system_variables[] = {
586
MYSQL_SYSVAR(repository_threshold),
587
MYSQL_SYSVAR(temp_log_threshold),
588
MYSQL_SYSVAR(temp_blob_timeout),
589
MYSQL_SYSVAR(garbage_threshold),
590
MYSQL_SYSVAR(http_metadata_headers),
591
MYSQL_SYSVAR(max_keep_alive),
592
MYSQL_SYSVAR(next_backup_db_id),
595
MYSQL_SYSVAR(watch_tables),
596
MYSQL_SYSVAR(watch_enable),
598
MYSQL_SYSVAR(before_insert_position),
599
MYSQL_SYSVAR(before_update_position),