1
/* Copyright (c) 2007 SNAP Innovation GmbH
1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
3
* BLOB Streaming for MySQL
3
* PrimeBase Media Stream for MySQL
5
5
* This program is free software; you can redistribute it and/or modify
6
6
* it under the terms of the GNU General Public License as published by
33
33
#include "CSStrUtil.h"
34
34
#include "CSHTTPStream.h"
36
#include "BSConnectionHandler.h"
37
#include "BSNetwork.h"
38
#include "BSOpenTable.h"
44
BSConnectionHandler::BSConnectionHandler(CSThreadList *list):
36
#include "ConnectionHandler_ms.h"
37
#include "Network_ms.h"
38
#include "OpenTable_ms.h"
40
#include "Engine_ms.h"
44
MSConnectionHandler::MSConnectionHandler(CSThreadList *list):
47
47
amWaitingToListen(false),
58
BSConnectionHandler::~BSConnectionHandler()
58
MSConnectionHandler::~MSConnectionHandler()
60
60
void *thd = myMySQLTHD;
64
BSEngine::closeConnection(myMySQLTHD);
64
MSEngine::closeConnection(myMySQLTHD);
67
bs_my_destroy_thread(thd);
67
ms_my_destroy_thread(thd);
71
void BSConnectionHandler::close()
71
void MSConnectionHandler::close()
77
BSConnectionHandler *BSConnectionHandler::newHandler(CSThreadList *list)
77
MSConnectionHandler *MSConnectionHandler::newHandler(CSThreadList *list)
79
return new BSConnectionHandler(list);
79
return new MSConnectionHandler(list);
82
82
/* Return false if not connection was openned, and the thread must quit. */
83
bool BSConnectionHandler::openStream()
83
bool MSConnectionHandler::openStream()
87
87
CSOutputStream *out;
90
if (!(sock = BSNetwork::openConnection(this)))
90
if (!(sock = MSNetwork::openConnection(this)))
93
93
in = sock->getInputStream();
104
int BSConnectionHandler::getHTTPStatus(int err)
104
int MSConnectionHandler::getHTTPStatus(int err)
109
case BS_OK: code = 200; break;
110
case BS_ERR_ENGINE: code = 500; break;
111
case BS_ERR_UNKNOWN_TABLE: code = 404; break;
112
case BS_ERR_UNKNOWN_DB: code = 404; break;
113
case BS_ERR_DATABASE_DELETED: code = 404; break;
114
case BS_ERR_NOT_FOUND: code = 404; break;
115
case BS_ERR_REMOVING_REPO: code - 404; break;
116
case BS_ERR_TABLE_LOCKED: code = 412; break; // Precondition Failed
117
case BS_ERR_INCORRECT_URL: code = 404; break;
118
case BS_ERR_AUTH_FAILED: code = 403; break; // Forbidden
109
case MS_OK: code = 200; break;
110
case MS_ERR_ENGINE: code = 500; break;
111
case MS_ERR_UNKNOWN_TABLE: code = 404; break;
112
case MS_ERR_UNKNOWN_DB: code = 404; break;
113
case MS_ERR_DATABASE_DELETED: code = 404; break;
114
case MS_ERR_NOT_FOUND: code = 404; break;
115
case MS_ERR_REMOVING_REPO: code - 404; break;
116
case MS_ERR_TABLE_LOCKED: code = 412; break; // Precondition Failed
117
case MS_ERR_INCORRECT_URL: code = 404; break;
118
case MS_ERR_AUTH_FAILED: code = 403; break; // Forbidden
119
119
default: code = 500; break;
124
void BSConnectionHandler::writeException(const char *qualifier)
124
void MSConnectionHandler::writeException(const char *qualifier)
148
148
iOutputStream->appendBody(myException.getStackTrace());
149
149
iOutputStream->appendBody(EXCEPTION_REPLY_STACK_TRACE_SUFFIX_TAG);
150
150
iOutputStream->appendBody("MySQL ");
151
iOutputStream->appendBody(bs_my_version());
152
iOutputStream->appendBody(", MyBS ");
153
iOutputStream->appendBody(bs_version());
151
iOutputStream->appendBody(ms_my_version());
152
iOutputStream->appendBody(", PBMS ");
153
iOutputStream->appendBody(ms_version());
154
154
iOutputStream->appendBody("<br>Copyright © 2007, SNAP Innovation GmbH</font></P></BODY></HTML>");
156
156
replyPending = false;
163
void BSConnectionHandler::writeException()
163
void MSConnectionHandler::writeException()
165
165
writeException(NULL);
168
void BSConnectionHandler::writeResult(const char *func, const char *file, int line, int err, char *engine, MyBSResultPtr result)
168
void MSConnectionHandler::writeResult(const char *func, const char *file, int line, int err, char *engine, PBMSResultPtr result)
171
171
char buffer[CS_EXC_MESSAGE_SIZE];
186
186
char engine_list[400];
188
cnt = BSEngine::getEngineList(400, engine_list);
188
cnt = MSEngine::getEngineList(400, engine_list);
190
190
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, "No streaming enabled engines");
191
191
else if (cnt == 1) {
192
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, "Streaming engine ");
192
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, "Stream engine ");
193
193
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, engine_list);
196
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, "Streaming engines ");
196
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, "Stream engines ");
197
197
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, engine_list);
307
307
* Request URI: /<database>/<table>/<column>/<column>=<value>&<column>=<value>&...
309
void BSConnectionHandler::handleGet()
309
void MSConnectionHandler::handleGet()
311
311
const char *bad_url_comment = "Incorrect URL: ";
315
315
self->myException.setErrorCode(0);
326
326
if (iColumn->length() == 0) {
329
if (bs_parse_blob_url(&blob, iTableURI->getCString(), false)) {
330
if (blob.bu_type == BS_URL_TYPE_BLOB || blob.bu_type == BS_URL_NEW_TYPE_BLOB) {
331
otab = BSTableList::getOpenTableByID(blob.bu_database, blob.bu_tab_id, false);
329
if (ms_parse_blob_url(&blob, iTableURI->getCString(), false)) {
330
if (blob.bu_type == MS_URL_TYPE_BLOB || blob.bu_type == MS_URL_NEW_TYPE_BLOB) {
331
otab = MSTableList::getOpenTableByID(blob.bu_database, blob.bu_tab_id, false);
333
333
otab->sendRepoBlob(blob.bu_blob_id, blob.bu_auth_code, iOutputStream);
334
334
backtopool_(otab);
337
BSRepoFile *repo_file;
337
MSRepoFile *repo_file;
339
if (!(otab = BSTableList::getOpenTableByStr(blob.bu_database, true))) {
339
if (!(otab = MSTableList::getOpenTableByStr(blob.bu_database, true))) {
340
340
char buffer[CS_EXC_MESSAGE_SIZE];
342
342
cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Unknown database: ");
343
343
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, blob.bu_database);
344
CSException::throwException(CS_CONTEXT, BS_ERR_UNKNOWN_DB, buffer);
344
CSException::throwException(CS_CONTEXT, MS_ERR_UNKNOWN_DB, buffer);
347
347
repo_file = otab->getDB()->getRepoFileFromPool(blob.bu_tab_id, false);
364
364
if (iCondition->length() == 0)
367
if (!mybs_field_ref_enabled())
368
CSException::throwException(CS_CONTEXT, BS_ERR_AUTH_FAILED, "BLOB field references not permitted. Use \"set global mybs_field_references=TRUE\" or use the command line option --mybs-field-references to enable BLOB field references.");
367
if (!pbms_field_ref_enabled())
368
CSException::throwException(CS_CONTEXT, MS_ERR_AUTH_FAILED, "BLOB field references not permitted. Use \"set global pbms_field_references=TRUE\" or use the command line option --mybs-field-references to enable BLOB field references.");
370
if (!(otab = BSTableList::lockTable(iTableURI)))
370
if (!(otab = MSTableList::lockTable(iTableURI)))
373
373
otab->sendEngineBlob(iColumn, iCondition, iOutputStream);
374
374
iOutputStream->flush();
377
BSTableList::unlockTable(otab, self->myException.getErrorCode() != 0);
377
MSTableList::unlockTable(otab, self->myException.getErrorCode() != 0);
387
387
cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, bad_url_comment);
388
388
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, iInputStream->getRequestURI()->getCString());
389
CSException::throwException(CS_CONTEXT, BS_ERR_INCORRECT_URL, buffer);
389
CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
393
void BSConnectionHandler::handlePut()
393
void MSConnectionHandler::handlePut()
398
398
self->myException.setErrorCode(0);
411
411
cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect URL: ");
412
412
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, iInputStream->getRequestURI()->getCString());
413
CSException::throwException(CS_CONTEXT, BS_ERR_INCORRECT_URL, buffer);
413
CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
416
if (!(otab = BSTableList::lockTable(iTableURI)))
416
if (!(otab = MSTableList::lockTable(iTableURI)))
419
419
csWord8 blob_len;
421
421
size_t handle_len;
423
423
blob_len = iInputStream->getContentLength();
460
460
* are waiting to listen!
462
462
threadStarted = true;
463
if (!BSNetwork::gWaitingToListen)
464
BSNetwork::startConnectionHandler();
463
if (!MSNetwork::gWaitingToListen)
464
MSNetwork::startConnectionHandler();
466
466
replyPending = true;
467
467
if (strcmp(method, "GET") == 0)
477
bool BSConnectionHandler::initialize()
477
bool MSConnectionHandler::initialize()
479
myMySQLTHD = bs_my_create_thread();
479
myMySQLTHD = ms_my_create_thread();
484
484
* Return false if no connection this thread should quit!
486
bool BSConnectionHandler::doWork()
486
bool MSConnectionHandler::doWork()
512
512
/* Free the MySQL thread: */
513
513
if ((thd = myMySQLTHD)) {
514
514
myMySQLTHD = NULL;
515
BSEngine::closeConnection(thd);
516
bs_my_destroy_thread(thd);
515
MSEngine::closeConnection(thd);
516
ms_my_destroy_thread(thd);
521
bool BSConnectionHandler::handleException()
521
bool MSConnectionHandler::handleException()
523
523
if (!myMustQuit) {
524
524
/* Start another handler if required: */
525
if (!BSNetwork::gWaitingToListen)
526
BSNetwork::startConnectionHandler();
525
if (!MSNetwork::gWaitingToListen)
526
MSNetwork::startConnectionHandler();
529
529
CSDaemon::handleException();