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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
* PBMS daemon global parameters.
30
#include <drizzled/common.h>
31
#include <drizzled/plugin.h>
32
#include <drizzled/session.h>
34
using namespace drizzled;
35
using namespace drizzled::plugin;
37
#define my_strdup(a,b) strdup(a)
39
#include "cslib/CSConfig.h"
41
#include "cslib/CSConfig.h"
42
#include "mysql_priv.h"
43
#include <mysql/plugin.h>
50
#include "cslib/CSDefs.h"
51
#include "cslib/CSObject.h"
52
#include "cslib/CSGlobal.h"
53
#include "cslib/CSThread.h"
54
#include "cslib/CSStrUtil.h"
55
#include "cslib/CSPath.h"
56
#include "cslib/CSLog.h"
59
#include "database_ms.h"
60
#include "parameters_ms.h"
63
#define PBMS_PORT 8080
67
static int my_port_number = PBMS_PORT;
69
static char *my_repository_threshold = NULL;
70
static char *my_temp_log_threshold = NULL;
71
static char *my_http_metadata_headers = NULL;
73
static u_long my_temp_blob_timeout = MS_DEFAULT_TEMP_LOG_WAIT;
74
static u_long my_garbage_threshold = MS_DEFAULT_GARBAGE_LEVEL;
75
static u_long my_max_keep_alive = MS_DEFAULT_KEEP_ALIVE;
77
static u_long my_backup_db_id = 1;
78
static uint32_t my_server_id = 1;
81
static set<string> my_black_list;
82
static bool my_events_enabled = true;
83
static CSMutex my_table_list_lock;
85
typedef enum {MATCH_ALL, MATCH_DBS, MATCH_SOME, MATCH_NONE, MATCH_UNKNOWN, MATCH_ERROR} TableMatchState;
86
static char *my_table_list = NULL;
87
static const char *dflt_my_table_list = "*";
89
static TableMatchState my_table_match = MATCH_UNKNOWN;
91
static int32_t my_before_insert_position= 1; // Call this event observer first.
92
static int32_t my_before_update_position= 1;
94
using namespace drizzled;
95
using namespace drizzled::plugin;
97
#define st_mysql_sys_var drizzled::drizzle_sys_var
100
struct st_mysql_sys_var
102
MYSQL_PLUGIN_VAR_HEADER;
107
#if MYSQL_VERSION_ID < 60000
109
#if MYSQL_VERSION_ID >= 50124
110
#define CONST_SAVE const
115
#if MYSQL_VERSION_ID >= 60005
116
#define CONST_SAVE const
126
uint32_t PBMSParameters::getPortNumber(){ return my_port_number;}
129
uint32_t PBMSParameters::getServerID(){ return my_server_id;}
132
uint64_t PBMSParameters::getRepoThreshold()
134
if (my_repository_threshold)
135
return((uint64_t) cs_byte_size_to_int8(my_repository_threshold));
137
return((uint64_t) cs_byte_size_to_int8(MS_REPO_THRESHOLD_DEF));
141
uint64_t PBMSParameters::getTempLogThreshold()
143
if (my_temp_log_threshold)
144
return((uint64_t) cs_byte_size_to_int8(my_temp_log_threshold));
146
return((uint64_t) cs_byte_size_to_int8(MS_TEMP_LOG_THRESHOLD_DEF));
150
uint32_t PBMSParameters::getTempBlobTimeout(){ return my_temp_blob_timeout;}
153
uint32_t PBMSParameters::getGarbageThreshold(){ return my_garbage_threshold;}
156
uint32_t PBMSParameters::getMaxKeepAlive(){ return my_max_keep_alive;}
159
const char * PBMSParameters::getDefaultMetaDataHeaders()
161
if (my_http_metadata_headers)
162
return my_http_metadata_headers;
164
return MS_HTTP_METADATA_HEADERS_DEF;
168
uint32_t PBMSParameters::getBackupDatabaseID() { return my_backup_db_id;}
171
void PBMSParameters::setBackupDatabaseID(uint32_t id) { my_backup_db_id = id;}
175
bool PBMSParameters::isPBMSEventsEnabled() { return my_events_enabled;}
178
#define NEXT_IN_TABLE_LIST(list) {\
179
while ((*list) && (*list != ',')) list++;\
183
static TableMatchState set_match_type(const char *list)
185
const char *ptr = list;
188
TableMatchState match_state;
197
while ((*ptr) && isspace(*ptr)) ptr++;
202
match_state = MATCH_UNKNOWN;
206
// Check database name
209
while ((*ptr) && (!isspace(*ptr)) && (*ptr != ',') && (*ptr != '.')) {ptr++;name_len++;}
210
while ((*ptr) && isspace(*ptr)) ptr++;
213
if ((name_len == 1) && (*name == '*'))
214
match_state = MATCH_ALL;
216
goto bad_list; // Missing table
219
if ((match_state > MATCH_DBS) && (name_len == 1) && (*name == '*'))
220
match_state = MATCH_DBS;
222
ptr++; // Skip the '.'
224
// Find the start of the table name.
225
while ((*ptr) && isspace(*ptr)) ptr++;
226
if ((!*ptr) || (*ptr == ',') || (*ptr == '.'))
227
goto bad_list; // Missing table
229
// Find the end of the table name.
230
while ((*ptr) && (!isspace(*ptr)) && (*ptr != ',') && (*ptr != '.')) ptr++;
233
// Locate the end of the element.
234
while ((*ptr) && isspace(*ptr)) ptr++;
236
if ((*ptr) && (*ptr != ','))
237
goto bad_list; // Bad table name
239
if (match_state > MATCH_SOME)
240
match_state = MATCH_SOME;
243
while ((*ptr) && isspace(*ptr)) ptr++;
250
snprintf(info, 120, "pbms_watch_tables format error near character position %d", (int) (ptr - list));
251
CSL.logLine(NULL, CSLog::Error, info);
252
CSL.logLine(NULL, CSLog::Error, list);
258
static const char* locate_db(const char *list, const char *db, int len)
263
while ((*list) && isspace(*list)) list++;
264
if ((*list == 0) || (*(list+1) == 0) || (*(list+2) == 0)) // We need at least 3 characters
270
else if (strncmp(list, db, len) == 0)
277
while ((*list) && isspace(*list)) list++;
278
if ((*list == 0) || (*(list+1) == 0) ) // We need at least 2 characters
283
while ((*list) && isspace(*list)) list++;
287
return list; // We have gound a table that could belong to this database;
291
NEXT_IN_TABLE_LIST(list);
298
// Parameter update functions are not called for parameters that are set on
299
// the command line. PBMSParameters::startUp() will perform any initialization required.
300
void PBMSParameters::startUp()
302
my_table_match = set_match_type(my_table_list);
306
bool PBMSParameters::isBlackListedDB(const char *db)
308
if (my_black_list.find(string(db)) == my_black_list.end())
315
void PBMSParameters::blackListedDB(const char *db)
317
my_black_list.insert(string(db));
321
bool PBMSParameters::try_LocateDB(CSThread *self, const char *db, bool *found)
323
volatile bool rtc = true;
325
lock_(&my_table_list_lock);
328
*found = (locate_db(my_table_list, db, strlen(db)) != NULL);
330
unlock_(&my_table_list_lock);
340
bool PBMSParameters::isBLOBDatabase(const char *db)
344
PBMSResultRec result;
347
if (isBlackListedDB(db))
350
if (my_table_match == MATCH_UNKNOWN)
351
my_table_match = set_match_type(my_table_list);
353
if (my_table_match == MATCH_NONE)
356
if (my_table_match <= MATCH_DBS)
359
if ((err = MSEngine::enterConnectionNoThd(&self, &result)) == 0) {
362
if (try_LocateDB(self, db, &found)) {
363
err = MSEngine::exceptionToResult(&self->myException, &result);
370
fprintf(stderr, "PBMSParameters::isBLOBDatabase(\"%s\") error (%d):'%s'\n",
371
db, result.mr_code, result.mr_message);
378
bool PBMSParameters::try_LocateTable(CSThread *self, const char *db, const char *table, bool *found)
380
volatile bool rtc = true;
383
int db_len, table_len, match_len;
385
lock_(&my_table_list_lock);
388
table_len = strlen(table);
392
ptr = locate_db(ptr, db, db_len);
397
else if (strncmp(ptr, table, table_len) == 0)
398
match_len = table_len;
402
if ((!*ptr) || (*ptr == ',') || isspace(*ptr)) {
408
NEXT_IN_TABLE_LIST(ptr);
412
unlock_(&my_table_list_lock);
422
bool PBMSParameters::isBLOBTable(const char *db, const char *table)
426
PBMSResultRec result;
429
if (isBlackListedDB(db))
432
if (my_table_match == MATCH_UNKNOWN)
433
my_table_match = set_match_type(my_table_list);
435
if (my_table_match == MATCH_NONE)
438
if (my_table_match <= MATCH_ALL)
441
if ((err = MSEngine::enterConnectionNoThd(&self, &result)) == 0) {
444
if (try_LocateTable(self, db, table, &found)) {
445
err = MSEngine::exceptionToResult(&self->myException, &result);
452
fprintf(stderr, "PBMSParameters::isBLOBTable(\"%s\", \"%s\") error (%d):'%s'\n",
453
db, table, result.mr_code, result.mr_message);
461
int32_t PBMSParameters::getBeforeUptateEventPosition() { return my_before_update_position;}
464
int32_t PBMSParameters::getBeforeInsertEventPosition() { return my_before_insert_position;}
468
static void pbms_temp_blob_timeout_func(THD *thd, struct st_mysql_sys_var *var, void *trg, CONST_SAVE void *save)
471
PBMSResultRec result;
476
*(u_long *)trg= *(u_long *) save;
478
if (MSEngine::enterConnectionNoThd(&self, &result))
481
MSDatabase::wakeTempLogThreads();
490
static MYSQL_SYSVAR_INT(port, my_port_number,
491
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
492
"The port for the server stream-based communications.",
493
NULL, NULL, PBMS_PORT, 0, 64*1024, 1);
495
static MYSQL_SYSVAR_STR(repository_threshold, my_repository_threshold,
496
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
497
"The maximum size of a BLOB repository file.",
498
NULL, NULL, MS_REPO_THRESHOLD_DEF);
500
static MYSQL_SYSVAR_STR(temp_log_threshold, my_temp_log_threshold,
501
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
502
"The maximum size of a temorary BLOB log file.",
503
NULL, NULL, MS_TEMP_LOG_THRESHOLD_DEF);
505
static MYSQL_SYSVAR_STR(http_metadata_headers, my_http_metadata_headers,
506
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
507
"A ':' delimited list of metadata header names to be used to initialize the pbms_metadata_header table when a database is created.",
508
NULL, NULL , MS_HTTP_METADATA_HEADERS_DEF);
510
static MYSQL_SYSVAR_ULONG(temp_blob_timeout, my_temp_blob_timeout,
512
"The timeout, in seconds, for temporary BLOBs. Uploaded blob data is removed after this time, unless committed to the database.",
513
NULL, pbms_temp_blob_timeout_func, MS_DEFAULT_TEMP_LOG_WAIT, 1, ~0L, 1);
515
static MYSQL_SYSVAR_ULONG(garbage_threshold, my_garbage_threshold,
517
"The percentage of garbage in a repository file before it is compacted.",
518
NULL, NULL, MS_DEFAULT_GARBAGE_LEVEL, 0, 100, 1);
521
static MYSQL_SYSVAR_ULONG(max_keep_alive, my_max_keep_alive,
523
"The timeout, in milli-seconds, before the HTTP server will close an inactive HTTP connection.",
524
NULL, NULL, MS_DEFAULT_KEEP_ALIVE, 1, UINT32_MAX, 1);
526
static MYSQL_SYSVAR_ULONG(next_backup_db_id, my_backup_db_id,
528
"The next backup ID to use when backing up a PBMS database.",
529
NULL, NULL, 1, 1, UINT32_MAX, 1);
535
static int check_table_list(THD *, struct st_mysql_sys_var *, void *save, drizzle_value *value)
539
const char *list = value->val_str(value, buffer, &len);
540
TableMatchState state;
542
state = set_match_type(list);
543
if (state == MATCH_ERROR)
546
char *new_list = strdup(list);
550
my_table_list_lock.lock();
551
if (my_table_list && (my_table_list != dflt_my_table_list)) free(my_table_list);
552
my_table_list = new_list;
554
my_table_match = state;
555
my_table_list_lock.unlock();
557
*static_cast<const char**>(save)= my_table_list;
563
static void set_table_list(THD *, struct st_mysql_sys_var *, void *var_ptr, CONST_SAVE void *)
565
// Everything was done in check_table_list()
566
*static_cast<const char**>(var_ptr)= my_table_list;
571
static MYSQL_SYSVAR_STR(watch_tables,
573
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_MEMALLOC,
574
N_("A comma delimited list of tables to watch of the format: <database>.<table>, ..."),
575
check_table_list, /* check func */
576
set_table_list, /* update func */
577
dflt_my_table_list /* default */);
579
static MYSQL_SYSVAR_BOOL(watch_enable,
582
N_("Enable PBMS daemon Insert/Update/Delete event scanning"),
583
NULL, /* check func */
584
NULL, /* update func */
587
static MYSQL_SYSVAR_INT(before_insert_position,
588
my_before_insert_position,
590
N_("Before insert row event observer call position"),
591
NULL, /* check func */
592
NULL, /* update func */
595
INT32_MAX -1, /* max */
598
static MYSQL_SYSVAR_INT(before_update_position,
599
my_before_update_position,
601
N_("Before update row event observer call position"),
602
NULL, /* check func */
603
NULL, /* update func */
606
INT32_MAX -1, /* max */
611
struct st_mysql_sys_var* pbms_system_variables[] = {
613
MYSQL_SYSVAR(repository_threshold),
614
MYSQL_SYSVAR(temp_log_threshold),
615
MYSQL_SYSVAR(temp_blob_timeout),
616
MYSQL_SYSVAR(garbage_threshold),
617
MYSQL_SYSVAR(http_metadata_headers),
618
MYSQL_SYSVAR(max_keep_alive),
619
MYSQL_SYSVAR(next_backup_db_id),
622
MYSQL_SYSVAR(watch_tables),
623
MYSQL_SYSVAR(watch_enable),
625
MYSQL_SYSVAR(before_insert_position),
626
MYSQL_SYSVAR(before_update_position),