1
0
Fork 0

fixed logging restart, added more logging, cleanup

This commit is contained in:
Frank Celler 2012-02-07 15:01:30 +01:00
parent e530a34283
commit 0be5dec1bc
33 changed files with 1054 additions and 1001 deletions

View File

@ -36,6 +36,7 @@
#include "Basics/ProgramOptionsDescription.h"
#include "HttpServer/HttpHandlerFactory.h"
#include "HttpServer/PathHandler.h"
#include "Logger/Logger.h"
#include "Rest/HttpResponse.h"
using namespace std;
@ -43,25 +44,6 @@ using namespace triagens::basics;
using namespace triagens::rest;
using namespace triagens::admin;
// -----------------------------------------------------------------------------
// --SECTION-- static private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup RestServer
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief option for the directory containing the admin files
////////////////////////////////////////////////////////////////////////////////
string ApplicationAdminServer::optionAdminDirectory;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- static public methods
// -----------------------------------------------------------------------------
@ -100,8 +82,17 @@ ApplicationAdminServer::ApplicationAdminServer ()
: _allowLogViewer(false),
_allowAdminDirectory(false),
_allowFeConfiguration(false),
_allowVersion(false) {
_allowVersion(false),
_adminDirectory(),
_pathOptions(0),
_feConfiguration(),
_name(),
_version() {
_pathOptions = new PathHandler::Options();
#ifdef _PKGDATADIR_
_adminDirectory = string(_PKGDATADIR_) + "/html/admin";
#endif
}
////////////////////////////////////////////////////////////////////////////////
@ -202,8 +193,10 @@ void ApplicationAdminServer::addHandlers (HttpHandlerFactory* factory, string co
// .............................................................................
if (_allowAdminDirectory) {
if (! optionAdminDirectory.empty()) {
reinterpret_cast<PathHandler::Options*>(_pathOptions)->path = optionAdminDirectory;
if (! _adminDirectory.empty()) {
LOGGER_INFO << "using JavaScript front-end files stored at '" << _adminDirectory << "'";
reinterpret_cast<PathHandler::Options*>(_pathOptions)->path = _adminDirectory;
reinterpret_cast<PathHandler::Options*>(_pathOptions)->contentType = "text/plain";
reinterpret_cast<PathHandler::Options*>(_pathOptions)->allowSymbolicLink = false;
reinterpret_cast<PathHandler::Options*>(_pathOptions)->defaultFile = "index.html";
@ -237,7 +230,7 @@ void ApplicationAdminServer::addHandlers (HttpHandlerFactory* factory, string co
void ApplicationAdminServer::setupOptions (map<string, basics::ProgramOptionsDescription>& options) {
if (_allowAdminDirectory) {
options[ApplicationServer::OPTIONS_SERVER + ":help-admin"]
("server.admin-directory", &optionAdminDirectory, "directory containing the ADMIN front-end")
("server.admin-directory", &_adminDirectory, "directory containing the ADMIN front-end")
;
}

View File

@ -195,27 +195,6 @@ namespace triagens {
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- static private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup RestServer
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief option for the directory containing the admin files
////////////////////////////////////////////////////////////////////////////////
static string optionAdminDirectory;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------

View File

@ -344,7 +344,7 @@ namespace triagens {
seteuid(_loggingUid);
#endif
TRI_CloseLogging();
bool threaded = TRI_ShutdownLogging();
Logger::setApplicationName(logApplicationName);
Logger::setHostName(logHostName);
@ -368,6 +368,8 @@ namespace triagens {
TRI_SetPrefixLogging(logPrefix);
TRI_SetThreadIdentifierLogging(logThreadId);
TRI_InitialiseLogging(threaded);
TRI_CreateLogAppenderFile(logFile);
TRI_CreateLogAppenderSyslog(logPrefix, logSyslog);
@ -392,10 +394,11 @@ namespace triagens {
// do not use init files
if (StringUtils::tolower(initFile) == string("none")) {
LOGGER_INFO << "using no init file at all";
return true;
}
LOGGER_DEBUG << "using init file '" << initFile << "'";
LOGGER_INFO << "using init file '" << initFile << "'";
bool ok = options.parse(descriptionFile, initFile);
@ -407,6 +410,9 @@ namespace triagens {
return ok;
}
else {
LOGGER_DEBUG << "no init file has been specified";
}
// nothing has been specified on the command line regarding configuration file
if (! userConfigFile.empty()) {
@ -424,7 +430,7 @@ namespace triagens {
// check and see if file exists
if (FileUtils::exists(homeDir)) {
LOGGER_DEBUG << "using init file '" << homeDir << "'";
LOGGER_INFO << "using user init file '" << homeDir << "'";
bool ok = options.parse(descriptionFile, homeDir);
@ -436,14 +442,21 @@ namespace triagens {
return ok;
}
else {
LOGGER_INFO << "no user init file '" << homeDir << "' found";
}
}
else {
LOGGER_DEBUG << "no user init file, $HOME is empty";
}
}
#ifdef _SYSCONFDIR_
// try the configuration file in the system directory - if there is one
// note that the system directory is dependent upon how the user installed
// the application server.
// Please note that the system directory changes depending on
// where the user installed the application server.
if (! systemConfigFile.empty()) {
string sysDir = string(_SYSCONFDIR_);
@ -458,7 +471,7 @@ namespace triagens {
// check and see if file exists
if (FileUtils::exists(sysDir)) {
LOGGER_DEBUG << "using init file '" << sysDir << "'";
LOGGER_INFO << "using init file '" << sysDir << "'";
bool ok = options.parse(descriptionFile, sysDir);
@ -470,6 +483,12 @@ namespace triagens {
return ok;
}
else {
LOGGER_INFO << "no system init file '" << sysDir << "' found";
}
}
else {
LOGGER_DEBUG << "no system init file, not system directory is known";
}
}

View File

@ -548,6 +548,7 @@ static void OutputMessage (TRI_log_level_e level,
msg._message = copy ? TRI_DuplicateString2(message, length) : message;
msg._length = length;
// this will COPY the structure log_message_t into the vector
TRI_LockMutex(&LogMessageQueueLock);
TRI_PushBackVector(&LogMessageQueue, (void*) &msg);
TRI_UnlockMutex(&LogMessageQueueLock);
@ -1664,7 +1665,7 @@ void TRI_InitialiseLogging (bool threaded) {
// always close logging at the end
if (! ShutdownInitalised) {
atexit(TRI_ShutdownLogging);
atexit((void (*)(void)) TRI_ShutdownLogging);
ShutdownInitalised = true;
}
}
@ -1714,9 +1715,9 @@ void TRI_ReopenLogging () {
/// @brief shut downs the logging components
////////////////////////////////////////////////////////////////////////////////
void TRI_ShutdownLogging () {
bool TRI_ShutdownLogging () {
if (! Initialised) {
return;
return ThreadedLogging;
}
// logging is now inactive
@ -1749,6 +1750,8 @@ void TRI_ShutdownLogging () {
TRI_DestroyMutex(&BufferLock);
Initialised = false;
return ThreadedLogging;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -502,7 +502,7 @@ void TRI_ReopenLogging (void);
/// @brief shut downs the logging components
////////////////////////////////////////////////////////////////////////////////
void TRI_ShutdownLogging (void);
bool TRI_ShutdownLogging (void);
////////////////////////////////////////////////////////////////////////////////
/// @}

View File

@ -0,0 +1,5 @@
> ./avocado --server.http-port 12345 /tmp/vocbase
2012-02-05T13:23:52Z [455] INFO AvocadoDB (version 0.0.8 [exported]) is ready for business
2012-02-05T13:23:52Z [455] INFO HTTP client port: 12345
2012-02-05T13:23:52Z [455] INFO HTTP admin port: localhost:8530
2012-02-05T13:23:52Z [455] INFO Have Fun!

View File

@ -44,7 +44,7 @@ namespace triagens {
GeneralListenTask& operator= (GeneralListenTask const&);
public:
/*
////////////////////////////////////////////////////////////////////////////////
/// @brief listen to given address and port
////////////////////////////////////////////////////////////////////////////////
@ -60,6 +60,14 @@ namespace triagens {
GeneralListenTask (S* server, int port, bool reuseAddress)
: Task("GeneralListenTask"), ListenTask(port, reuseAddress), server(server) {
}
*/
////////////////////////////////////////////////////////////////////////////////
/// @brief listen to given port
////////////////////////////////////////////////////////////////////////////////
GeneralListenTask (S* server, struct addrinfo *aip, bool reuseAddress)
: Task("GeneralListenTask"), ListenTask(aip, reuseAddress), server(server) {
}
protected:

View File

@ -31,6 +31,14 @@
#include <Basics/Common.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <Basics/StringUtils.h>
#include <Basics/Exceptions.h>
#include <Logger/Logger.h>
#include <Basics/ReadLocker.h>
@ -193,16 +201,61 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
bool addPort (string const& address, int port, bool reuseAddress) {
ListenTask* task = new GeneralListenTask<S>(dynamic_cast<S*>(this), address, port, reuseAddress);
struct addrinfo *result, *aip;
struct addrinfo hints;
int error;
if (! task->isBound()) {
deleteTask(task);
return false;
memset(&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = 0;
string portString = basics::StringUtils::itoa(port);
if (address.empty()) {
error = getaddrinfo(NULL, portString.c_str(), &hints, &result);
}
else {
error = getaddrinfo(address.c_str(), portString.c_str(), &hints, &result);
}
_scheduler->registerTask(task);
if (error != 0) {
LOGGER_ERROR << "getaddrinfo for host: " << address.c_str() << " => " << gai_strerror(error);
return false;
}
bool gotTask = false;
// Try all returned addresses
for (aip = result; aip != NULL; aip = aip->ai_next) {
ListenTask* task = new GeneralListenTask<S > (dynamic_cast<S*> (this), aip, reuseAddress);
return true;
if (! task->isBound()) {
deleteTask(task);
}
else {
_scheduler->registerTask(task);
gotTask = true;
}
}
freeaddrinfo(result);
return gotTask;
// ListenTask* task = new GeneralListenTask<S > (dynamic_cast<S*> (this), address, port, reuseAddress);
//
// if (! task->isBound()) {
// deleteTask(task);
// return false;
// }
//
// _scheduler->registerTask(task);
//
// return true;
}
public:

View File

@ -1,7 +1,8 @@
ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS =
AM_CPPFLAGS =
AM_CXXFLAGS =
AM_CPPFLAGS = -D_SYSCONFDIR_='"${sysconfdir}"' -D_PKGDATADIR_='"${pkgdatadir}"'
AM_LDFLAGS =
BUILT_SOURCES = .setup-directories
LIBS =
@ -9,6 +10,15 @@ LIBS =
noinst_LIBRARIES = libavocadodb.a
bin_PROGRAMS = avocado
nobase_pkgdata_DATA = \
$(shell find @srcdir@/js/system -name "*.js" -print) \
$(shell find @srcdir@/html -name "*.css" -print) \
$(shell find @srcdir@/html -name "*.gif" -print) \
$(shell find @srcdir@/html -name "*.html" -print) \
$(shell find @srcdir@/html -name "*.ico" -print) \
$(shell find @srcdir@/html -name "*.js" -print) \
$(shell find @srcdir@/html -name "*.png" -print)
################################################################################
## avocado
################################################################################
@ -89,6 +99,9 @@ Doxygen/js/system/%.c: @srcdir@/js/system/%.js .setup-directories
Doxygen/js/modules/%.c: @srcdir@/js/system/%.js .setup-directories
python @top_srcdir@/Doxygen/Scripts/js2doxy.py $< > $@
Doxygen/js/bootstrap/%.c: @srcdir@/js/bootstrap/%.js .setup-directories
python @top_srcdir@/Doxygen/Scripts/js2doxy.py $< > $@
doxygen: Doxygen/avocado.doxy $(DOXYGEN)
doxygen Doxygen/avocado.doxy

View File

@ -3,6 +3,7 @@
################################################################################
libavocadodb_a_CPPFLAGS = \
$(AM_CPPFLAGS) \
@BOOST_CPPFLAGS@ \
@LIBEV_CPPFLAGS@ \
@MATH_CPPFLAGS@ \
@ -158,6 +159,8 @@ libavocadodb_a_SOURCES = \
VocBase/datafile.c \
VocBase/document-collection.c \
VocBase/fluent-query.c \
VocBase/select-result.c \
VocBase/join.c \
VocBase/query.c \
VocBase/headers.c \
VocBase/index.c \
@ -178,6 +181,7 @@ libavocadodb_a_SOURCES = \
QL/tokens.c
avocado_CPPFLAGS = \
$(AM_CPPFLAGS) \
@BOOST_CPPFLAGS@ \
@LIBEV_CPPFLAGS@ \
@MATH_CPPFLAGS@ \
@ -311,6 +315,9 @@ WIKI = \
Doxygen/xml/da/db6/InstallManual.md \
Doxygen/xml/dd/dd7/RefManual.md
Doxygen/xml/da/db6/InstallManual.md: Doxygen/xml/da/db6/InstallManual.xml
python @top_srcdir@/Doxygen/Scripts/xml2md.py $< > $@
Doxygen/xml/dd/dd7/RefManual.md: Doxygen/xml/dd/dd7/RefManual.xml
python @top_srcdir@/Doxygen/Scripts/xml2md.py $< > $@

View File

@ -49,7 +49,6 @@ ParseError::ParseError (const string& message, const size_t line, const size_t c
_message(message), _line(line), _column(column) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Destroy the instance
////////////////////////////////////////////////////////////////////////////////
@ -68,7 +67,6 @@ string ParseError::getDescription () const {
return errorMessage.str();
}
// -----------------------------------------------------------------------------
// --SECTION-- class ParserWrapper
// -----------------------------------------------------------------------------
@ -95,7 +93,6 @@ ParserWrapper::~ParserWrapper () {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Parse the query passed
////////////////////////////////////////////////////////////////////////////////
@ -141,16 +138,14 @@ bool ParserWrapper::parse () {
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get a parse error that may have occurred
////////////////////////////////////////////////////////////////////////////////
ParseError *ParserWrapper::getParseError () {
ParseError* ParserWrapper::getParseError () {
return _parseError;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the type of the query
////////////////////////////////////////////////////////////////////////////////
@ -163,44 +158,44 @@ QL_ast_query_type_e ParserWrapper::getQueryType () {
return _context->_query->_type;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Create a select clause
////////////////////////////////////////////////////////////////////////////////
TRI_qry_select_t *ParserWrapper::getSelect () {
TRI_qry_select_t* ParserWrapper::getSelect () {
TRI_qry_select_t* select = 0;
if (_isParsed) {
QLOptimizeExpression(_context->_query->_select._base);
QL_ast_query_select_type_e selectType = QLOptimizeGetSelectType(_context->_query);
if (!_isParsed) {
return 0;
}
if (selectType == QLQuerySelectTypeSimple) {
select = TRI_CreateQuerySelectDocument();
}
else if (selectType == QLQuerySelectTypeEvaluated) {
QL_javascript_conversion_t *selectJs = QLJavascripterInit();
if (selectJs != 0) {
TRI_AppendStringStringBuffer(selectJs->_buffer, "(function($) { return ");
QLJavascripterConvert(selectJs, _context->_query->_select._base);
TRI_AppendStringStringBuffer(selectJs->_buffer, " })");
select = TRI_CreateQuerySelectGeneral(selectJs->_buffer->_buffer);
// TODO: REMOVE ME
// std::cout << "SELECT: " << selectJs->_buffer->_buffer << "\n";
QLJavascripterFree(selectJs);
}
QLOptimizeExpression(_context->_query->_select._base);
QL_ast_query_select_type_e selectType = QLOptimizeGetSelectType(_context->_query);
if (selectType == QLQuerySelectTypeSimple) {
select = TRI_CreateQuerySelectDocument();
}
else if (selectType == QLQuerySelectTypeEvaluated) {
QL_javascript_conversion_t *selectJs = QLJavascripterInit();
if (selectJs != 0) {
TRI_AppendStringStringBuffer(selectJs->_buffer, "(function($) { return ");
QLJavascripterConvert(selectJs, _context->_query->_select._base);
TRI_AppendStringStringBuffer(selectJs->_buffer, " })");
select = TRI_CreateQuerySelectGeneral(selectJs->_buffer->_buffer);
// TODO: REMOVE ME
// std::cout << "SELECT: " << selectJs->_buffer->_buffer << "\n";
QLJavascripterFree(selectJs);
}
}
return select;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the alias of the primary collection
////////////////////////////////////////////////////////////////////////////////
char *ParserWrapper::getPrimaryAlias () {
char* ParserWrapper::getPrimaryAlias () {
if (_isParsed) {
return QLAstQueryGetPrimaryAlias(_context->_query);
}
@ -208,12 +203,11 @@ char *ParserWrapper::getPrimaryAlias () {
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the name of the primary collection
////////////////////////////////////////////////////////////////////////////////
char *ParserWrapper::getPrimaryName () {
char* ParserWrapper::getPrimaryName () {
if (_isParsed) {
return QLAstQueryGetPrimaryName(_context->_query);
}
@ -221,97 +215,175 @@ char *ParserWrapper::getPrimaryName () {
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Create joins
////////////////////////////////////////////////////////////////////////////////
TRI_select_join_t* ParserWrapper::getJoins () {
TRI_select_join_t* join = 0;
char *collectionName;
char *collectionAlias;
if (!_isParsed ) {
return NULL;
}
join = TRI_CreateSelectJoin();
if (!join) {
return NULL;
}
QL_ast_node_t *node = (QL_ast_node_t *) _context->_query->_from._base;
node = (QL_ast_node_t *) node->_next;
assert(node != 0);
// primary table
QL_ast_node_t *lhs = (QL_ast_node_t *) node->_lhs;
QL_ast_node_t *rhs = (QL_ast_node_t *) node->_rhs;
collectionName = lhs->_value._stringValue;
collectionAlias = rhs->_value._stringValue;
TRI_AddPartSelectJoin(join, JOIN_TYPE_PRIMARY, NULL, collectionName, collectionAlias);
while (node->_next) {
node = (QL_ast_node_t *) node->_next;
QL_ast_node_t *ref = (QL_ast_node_t *) node->_lhs;
QL_ast_node_t *condition = (QL_ast_node_t *) node->_rhs;
QLOptimizeExpression(condition);
QL_ast_query_where_type_e conditionType = QLOptimizeGetWhereType(condition);
TRI_qry_where_t* joinWhere = 0;
if (conditionType == QLQueryWhereTypeAlwaysTrue) {
// join condition is always true
joinWhere = TRI_CreateQueryWhereBoolean(true);
}
else if (conditionType == QLQueryWhereTypeAlwaysFalse) {
// join condition is always false
joinWhere = TRI_CreateQueryWhereBoolean(false);
}
else {
// where condition must be evaluated for each result
QL_javascript_conversion_t *conditionJs = QLJavascripterInit();
if (conditionJs != 0) {
TRI_AppendStringStringBuffer(conditionJs->_buffer, "(function($) { return (");
QLJavascripterConvert(conditionJs, condition);
TRI_AppendStringStringBuffer(conditionJs->_buffer, "); })");
joinWhere = TRI_CreateQueryWhereGeneral(conditionJs->_buffer->_buffer);
QLJavascripterFree(conditionJs);
}
}
collectionName = ((QL_ast_node_t *) (ref->_lhs))->_value._stringValue;
collectionAlias = ((QL_ast_node_t *) (ref->_rhs))->_value._stringValue;
if (node->_type == QLNodeJoinList) {
TRI_AddPartSelectJoin(join, JOIN_TYPE_LIST, joinWhere, collectionName, collectionAlias);
}
else if (node->_type == QLNodeJoinInner) {
TRI_AddPartSelectJoin(join, JOIN_TYPE_INNER, joinWhere, collectionName, collectionAlias);
}
else if (node->_type == QLNodeJoinLeft || node->_type == QLNodeJoinRight) {
TRI_AddPartSelectJoin(join, JOIN_TYPE_OUTER, joinWhere, collectionName, collectionAlias);
}
}
return join;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Create a where clause
////////////////////////////////////////////////////////////////////////////////
TRI_qry_where_t *ParserWrapper::getWhere () {
TRI_qry_where_t* ParserWrapper::getWhere () {
TRI_qry_where_t* where = 0;
if (_isParsed) {
QLOptimizeExpression(_context->_query->_where._base);
// TODO: REMOVE ME
// QL_formatter_t f;
// f.indentLevel = 0;
// QLFormatterDump(_context->_query->_where._base, &f, 0);
if (!_isParsed) {
return NULL;
}
_context->_query->_where._type = QLOptimizeGetWhereType(_context->_query);
QLOptimizeExpression(_context->_query->_where._base);
// TODO: REMOVE ME
// QL_formatter_t f;
// f.indentLevel = 0;
// QLFormatterDump(_context->_query->_where._base, &f, 0);
if (_context->_query->_where._type == QLQueryWhereTypeAlwaysTrue) {
// where condition is always true
where = TRI_CreateQueryWhereBoolean(true);
}
else if (_context->_query->_where._type == QLQueryWhereTypeAlwaysFalse) {
// where condition is always false
where = TRI_CreateQueryWhereBoolean(false);
}
else {
// where condition must be evaluated for each result
QL_javascript_conversion_t *whereJs = QLJavascripterInit();
if (whereJs != 0) {
TRI_AppendStringStringBuffer(whereJs->_buffer, "(function($) { return (");
QLJavascripterConvert(whereJs, _context->_query->_where._base);
TRI_AppendStringStringBuffer(whereJs->_buffer, "); })");
where = TRI_CreateQueryWhereGeneral(whereJs->_buffer->_buffer);
// TODO: REMOVE ME
// std::cout << "WHERE: " << whereJs->_buffer->_buffer << "\n";
QLJavascripterFree(whereJs);
}
_context->_query->_where._type = QLOptimizeGetWhereType(_context->_query->_where._base);
if (_context->_query->_where._type == QLQueryWhereTypeAlwaysTrue) {
// where condition is always true
where = TRI_CreateQueryWhereBoolean(true);
}
else if (_context->_query->_where._type == QLQueryWhereTypeAlwaysFalse) {
// where condition is always false
where = TRI_CreateQueryWhereBoolean(false);
}
else {
// where condition must be evaluated for each result
QL_javascript_conversion_t *whereJs = QLJavascripterInit();
if (whereJs != 0) {
TRI_AppendStringStringBuffer(whereJs->_buffer, "(function($) { return (");
QLJavascripterConvert(whereJs, _context->_query->_where._base);
TRI_AppendStringStringBuffer(whereJs->_buffer, "); })");
where = TRI_CreateQueryWhereGeneral(whereJs->_buffer->_buffer);
// TODO: REMOVE ME
// std::cout << "WHERE: " << whereJs->_buffer->_buffer << "\n";
QLJavascripterFree(whereJs);
}
}
return where;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Create an order clause
////////////////////////////////////////////////////////////////////////////////
TRI_qry_order_t *ParserWrapper::getOrder () {
TRI_qry_order_t* ParserWrapper::getOrder () {
TRI_qry_order_t* order = 0;
if (_isParsed ) {
if (_context->_query->_order._base) {
QLOptimizeOrder(_context->_query->_order._base);
QL_javascript_conversion_t *orderJs = QLJavascripterInit();
if (orderJs != 0) {
TRI_AppendStringStringBuffer(orderJs->_buffer, "(function($) { return (");
QLJavascripterConvertOrder(orderJs, (QL_ast_node_t *) _context->_query->_order._base->_next);
TRI_AppendStringStringBuffer(orderJs->_buffer, "); })");
order = TRI_CreateQueryOrderGeneral(orderJs->_buffer->_buffer);
// TODO: REMOVE ME
std::cout << "ORDER: " << orderJs->_buffer->_buffer << "\n";
QLJavascripterFree(orderJs);
}
if (!_isParsed ) {
return NULL;
}
if (_context->_query->_order._base) {
QLOptimizeOrder(_context->_query->_order._base);
QL_javascript_conversion_t *orderJs = QLJavascripterInit();
if (orderJs != 0) {
TRI_AppendStringStringBuffer(orderJs->_buffer, "(function($) { return (");
QLJavascripterConvertOrder(orderJs, (QL_ast_node_t *) _context->_query->_order._base->_next);
TRI_AppendStringStringBuffer(orderJs->_buffer, "); })");
order = TRI_CreateQueryOrderGeneral(orderJs->_buffer->_buffer);
// TODO: REMOVE ME
// std::cout << "ORDER: " << orderJs->_buffer->_buffer << "\n";
QLJavascripterFree(orderJs);
}
}
return order;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the skip value
////////////////////////////////////////////////////////////////////////////////
TRI_voc_size_t ParserWrapper::getSkip () {
TRI_voc_size_t skip = 0;
TRI_voc_size_t skip = 0;
if (_isParsed) {
if (_context->_query->_limit._isUsed) {
skip = (TRI_voc_size_t) _context->_query->_limit._offset;
}
else {
skip = TRI_QRY_NO_SKIP;
skip = TRI_QRY_NO_SKIP;
}
}
return skip;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the limit value
////////////////////////////////////////////////////////////////////////////////

View File

@ -42,6 +42,7 @@
#include "QL/javascripter.h"
#include "VocBase/query.h"
#include "VocBase/join.h"
using namespace std;
@ -70,14 +71,12 @@ namespace triagens {
ParseError(const string&, const size_t, const size_t);
////////////////////////////////////////////////////////////////////////////////
/// @brief Destroy the instance
////////////////////////////////////////////////////////////////////////////////
~ParseError();
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the parse error as a formatted string
////////////////////////////////////////////////////////////////////////////////
@ -92,14 +91,12 @@ namespace triagens {
string _message;
////////////////////////////////////////////////////////////////////////////////
/// @brief Line in which the error occurred
////////////////////////////////////////////////////////////////////////////////
size_t _line;
////////////////////////////////////////////////////////////////////////////////
/// @brief Column in which the error occurred
////////////////////////////////////////////////////////////////////////////////
@ -127,8 +124,7 @@ namespace triagens {
/// @brief Create a new instance
////////////////////////////////////////////////////////////////////////////////
ParserWrapper (const char *);
ParserWrapper (const char*);
////////////////////////////////////////////////////////////////////////////////
/// @brief Destroy the instance and free all associated memory
@ -136,60 +132,59 @@ namespace triagens {
~ParserWrapper ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Parse the query passed
////////////////////////////////////////////////////////////////////////////////
bool parse ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Get a parse error that may have occurred
////////////////////////////////////////////////////////////////////////////////
ParseError *getParseError ();
ParseError* getParseError ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the type of the query
////////////////////////////////////////////////////////////////////////////////
QL_ast_query_type_e getQueryType ();
QL_ast_query_type_e getQueryType ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Create a select clause
////////////////////////////////////////////////////////////////////////////////
TRI_qry_select_t *getSelect ();
TRI_qry_select_t* getSelect ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the alias of the primary collection
////////////////////////////////////////////////////////////////////////////////
char *getPrimaryAlias ();
char* getPrimaryAlias ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the name of the primary collection
////////////////////////////////////////////////////////////////////////////////
char *getPrimaryName ();
char* getPrimaryName ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Create joins
////////////////////////////////////////////////////////////////////////////////
TRI_select_join_t* getJoins ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Create a where clause
////////////////////////////////////////////////////////////////////////////////
TRI_qry_where_t *getWhere ();
TRI_qry_where_t* getWhere ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Create an order clause
////////////////////////////////////////////////////////////////////////////////
TRI_qry_order_t *getOrder ();
TRI_qry_order_t* getOrder ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the skip value
@ -197,31 +192,27 @@ namespace triagens {
TRI_voc_size_t getSkip ();
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the limit value
////////////////////////////////////////////////////////////////////////////////
TRI_voc_ssize_t getLimit ();
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief Query string
////////////////////////////////////////////////////////////////////////////////
const char *_query;
const char* _query;
////////////////////////////////////////////////////////////////////////////////
/// @brief Parser context. This is a struct that is used extensively by the
/// parser. It contains a pointer to the flex lexer, a pointer to the query's
/// AST root nodes and state information for memory management (GC)
////////////////////////////////////////////////////////////////////////////////
QL_parser_context_t *_context;
QL_parser_context_t* _context;
////////////////////////////////////////////////////////////////////////////////
/// @brief Pointer to a parse error
@ -230,8 +221,7 @@ namespace triagens {
/// error occurs. It will be freed automatically when the parser is destroyed.
////////////////////////////////////////////////////////////////////////////////
ParseError *_parseError;
ParseError* _parseError;
////////////////////////////////////////////////////////////////////////////////
/// @brief Flag if parsing has already taken place

View File

@ -413,7 +413,7 @@ bool QLAstNodeIsRelationalOperator (QL_ast_node_t *node) {
/// @brief return whether a node is a constant
////////////////////////////////////////////////////////////////////////////////
bool QLAstNodeIsBooleanizable (QL_ast_node_t *node) {
bool QLAstNodeIsBooleanizable (const QL_ast_node_t *node) {
switch (node->_type) {
case QLNodeValueBool:
// case QLNodeValueString: // TODO

View File

@ -242,7 +242,7 @@ bool QLAstNodeIsRelationalOperator (QL_ast_node_t *);
/// @brief return whether a node is convertable into a bool value
////////////////////////////////////////////////////////////////////////////////
bool QLAstNodeIsBooleanizable (QL_ast_node_t *);
bool QLAstNodeIsBooleanizable (const QL_ast_node_t *);
////////////////////////////////////////////////////////////////////////////////

View File

@ -91,7 +91,7 @@ void QLFormatterPrintBlockEnd (QL_formatter_t *formatter,const char *name) {
void QLFormatterPrintInt (QL_formatter_t *formatter,const char *name,uint64_t value) {
QLFormatterPrintIndentation(formatter);
printf("%s: %llu\n",name,value);
//printf("%s: %llu\n",name,value);
}

View File

@ -578,20 +578,18 @@ QL_ast_query_select_type_e QLOptimizeGetSelectType (const QL_ast_query_t *query)
////////////////////////////////////////////////////////////////////////////////
/// @brief get the type of a query's WHERE condition
/// @brief get the type of a query's WHERE/ON condition
////////////////////////////////////////////////////////////////////////////////
QL_ast_query_where_type_e QLOptimizeGetWhereType (const QL_ast_query_t *query) {
QL_ast_node_t *whereNode = query->_where._base;
if (whereNode == 0) {
QL_ast_query_where_type_e QLOptimizeGetWhereType (const QL_ast_node_t *node) {
if (node == 0) {
// query does not have a WHERE part
return QLQueryWhereTypeAlwaysTrue;
}
if (QLAstNodeIsBooleanizable(whereNode)) {
if (QLAstNodeIsBooleanizable(node)) {
// WHERE part is constant
if (QLOptimizeGetBool(whereNode)) {
if (QLOptimizeGetBool(node)) {
// WHERE is always true
return QLQueryWhereTypeAlwaysTrue;
}

View File

@ -130,10 +130,10 @@ QL_ast_query_select_type_e QLOptimizeGetSelectType (const QL_ast_query_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief get the type of a query's WHERE condition
/// @brief get the type of a query's WHERE/ON condition
////////////////////////////////////////////////////////////////////////////////
QL_ast_query_where_type_e QLOptimizeGetWhereType (const QL_ast_query_t*);
QL_ast_query_where_type_e QLOptimizeGetWhereType (const QL_ast_node_t*);
////////////////////////////////////////////////////////////////////////////////

View File

@ -53,7 +53,23 @@ namespace triagens {
bool AddressPort::split (string const& definition) {
size_t n = StringUtils::numEntries(definition, ":");
if (definition.empty()) {
return false;
}
if (definition[0] == '[') {
// ipv6 address
size_t find = definition.find("]:", 1);
if (find != string::npos && find + 2 < definition.size()) {
address = definition.substr(1, find-1);
port = StringUtils::uint32(definition.substr(find+2));
return true;
}
}
int n = StringUtils::numEntries(definition, ":");
if (n == 1) {
address = "";

View File

@ -42,6 +42,7 @@
#include "Dispatcher/ApplicationServerDispatcher.h"
#include "Dispatcher/DispatcherImpl.h"
#include "HttpServer/HttpHandlerFactory.h"
#include "HttpServer/RedirectHandler.h"
#include "Logger/Logger.h"
#include "Rest/Initialise.h"
#include "RestHandler/RestActionHandler.h"
@ -167,6 +168,10 @@ AvocadoServer::AvocadoServer (int argc, char** argv)
_databasePath("/var/lib/avocado"),
_vocbase(0) {
_workingDirectory = "/var/tmp";
#ifdef _PKGDATADIR_
_systemActionPath = string(_PKGDATADIR_) + "/js/system";
#endif
}
////////////////////////////////////////////////////////////////////////////////
@ -259,7 +264,7 @@ void AvocadoServer::buildApplicationServer () {
// .............................................................................
additional["JAVASCRIPT Options"]
("startup.directory", &_startupPath, "path to the directory containing the startup scripts")
("startup.directory", &_startupPath, "path to the directory containing alternate startup scripts")
("startup.modules-path", &_startupModules, "one or more directories separated by semicolon")
("action.directory", &_actionPath, "path to the action directory, defaults to <database.directory>/_ACTIONS")
;
@ -300,6 +305,7 @@ void AvocadoServer::buildApplicationServer () {
}
if (_startupPath.empty()) {
LOGGER_INFO << "using built-in JavaScript startup files";
StartupLoader.defineScript("bootstrap/modules.js", JS_bootstrap_modules);
StartupLoader.defineScript("bootstrap/print.js", JS_bootstrap_print);
StartupLoader.defineScript("server/actions.js", JS_server_actions);
@ -308,6 +314,7 @@ void AvocadoServer::buildApplicationServer () {
StartupLoader.defineScript("server/shell.js", JS_server_shell);
}
else {
LOGGER_INFO << "using JavaScript startup files at '" << _startupPath << "'";
StartupLoader.setDirectory(_startupPath);
}
@ -335,13 +342,20 @@ void AvocadoServer::buildApplicationServer () {
}
ActionLoader.setDirectory(path);
LOGGER_INFO << "using database action files at '" << path << "'";
}
else {
ActionLoader.setDirectory(_actionPath);
LOGGER_INFO << "using alternate action files at '" << _actionPath << "'";
}
if (! _systemActionPath.empty()) {
SystemActionLoader.setDirectory(_systemActionPath);
LOGGER_INFO << "using system action files at '" << _systemActionPath << "'";
}
else {
LOGGER_INFO << "system actions are disabled, empty system action path";
}
// .............................................................................
@ -463,6 +477,8 @@ int AvocadoServer::startupServer () {
adminFactory->addPrefixHandler(RestVocbaseBaseHandler::ACTION_PATH, RestHandlerCreator<RestActionHandler>::createData<TRI_vocbase_t*>, _vocbase);
adminFactory->addPrefixHandler(RestVocbaseBaseHandler::SYSTEM_ACTION_PATH, RestHandlerCreator<RestSystemActionHandler>::createData<TRI_vocbase_t*>, _vocbase);
adminFactory->addHandler("/", RedirectHandler::create, (void*) "/admin/index.html");
_adminHttpServer = _applicationHttpServer->buildServer(adminFactory, adminPorts);
}

View File

@ -29,7 +29,8 @@
/// @page CompilingTOC
///
/// <ol>
/// <li>@ref CompilingPrerequisites "Prerequisites"</li>
/// <li>@ref CompilingPrerequisites</li>
/// <li>@ref CompilingGeneral</li>
/// </ol>
////////////////////////////////////////////////////////////////////////////////
@ -40,20 +41,119 @@
/// @copydoc CompilingTOC
/// <hr>
///
/// @anchor CompilingPrerequisites
/// @section Prerequisites
/// The following sections describe how to compile and build the AvocadoDB from
/// scratch. The AvocadoDB will compile on most Linux and Mac OS X systems. It
/// assumes that you use the GNU C++ compiler to compile the source. The
/// AvocadoDB has been tested with the GNU C++ compiler, but should compile with
/// any Posix compliant compiler. Please let us know, whether you successfully
/// compiled it with another C++ compiler.
///
/// @section CompilingPrerequisites Basic System Requirements
///
/// In order to compile the AvocadoDB, you will need
/// Verify that your system contains
///
/// - a recent version of GCC / G++
/// - a recent version of FLEX
/// - a recent version of BISON
/// - the GNU C++ compiler "g++" and standard C++ libraries
/// - the GNU autotools (autoconf, automake)
/// - the GNU make
/// - the GNU scanner generator FLEX
/// - the GNU parser generator BISON
///
/// - the libev in version 3 or 4
/// - a recent version of the Google's V8 engine
/// - the readline library
/// - the ncurses library
/// - the boost header files
/// In addition you will need the following libraries
///
/// - libev in version 3 or 4
/// - Google's V8 engine
/// - the GNU readline library
/// - the GNU ncurses library in version 5 or 6
/// - boost header files, at least version 1.33
///
/// Some distributions, for example Centos 5, provide only very out-dated
/// versions of FLEX, BISON, and the V8 engine. In that case you need to compile
/// newer versions of the programs and/or libraries.
///
/// @section CompilingGeneral Compiling the AvocadoDB
///
/// @subsection DownloadSource Download the Source
///
/// Download the latest source using GIT:
///
/// @LIT{git clone git://github.com/triAGENS/AvocadoDB.git}
///
/// @subsection Prerequisites Prerequisites
///
/// Install or download the prerequisites
///
/// - boost development package (see www.boost.org), at least version 1.33
/// - Google's V8 engine (see code.google.com/p/v8)
/// - libev (see software.schmorp.de/pkg/libev.html)
///
/// Most linux systems already supply RPM or DEP for there packages. Please note
/// that you have to install the development packages.
///
/// @subsection Setup Setup
///
/// Switch into the AvocadoDB directory
///
/// @LIT{cd AvocadoDB}
///
/// The source tarball contains a pre-generated "configure" script. You can
/// regenerate this script by using the GNU auto tools. In order to do so,
/// execute
///
/// @LIT{make setup}
///
/// This will call aclocal, autoheader, automake, and autoconf in the correct
/// order.
///
/// @subsection Configure Configure
///
/// In order to configure the build environment execute
///
/// @LIT{./configure}
///
/// to setup the makefiles. This will check for the various system
/// characteristics and installed libraries. If the configure scripts fail to
/// find the boost library, check that C++ is installed and working and that the
/// boost-devel package was successfully installed.
///
/// @subsection Compile Compile
///
/// Compile the program by executing
///
/// @LIT{make}
///
/// This will compile the AvocadoDB and create a binary of the server in
///
/// @LIT{./avocadodb}
///
/// @subsection Test Test
///
/// Check the binary by starting it using the command line.
///
/// @LIT{./avocado --server.http-port 12345 /tmp/vocbase}
///
/// This will start up the AvocadoDB and listen for HTTP requests on port 12345
/// bound to any address. You should see the startup messages
///
/// @verbinclude startup1
///
/// Use your favorite browser to access the URL
///
/// @LIT{http://localhost:12345/version}
///
/// This should produce a JSON object like
///
/// @LIT{\{"server":"avocado"\,"version":"0.0.8 [exported]"\}}
///
/// as result.
///
/// @subsection Install Install
///
/// Install everything by executing
///
/// @LIT{make install}
///
/// You must be root to do this or at least have write permission to the
/// corresponding directories.
////////////////////////////////////////////////////////////////////////////////
// Local Variables:

View File

@ -35,11 +35,13 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <Basics/MutexLocker.h>
#include <Basics/StringUtils.h>
#include <BasicsC/socket-utils.h>
#include <Logger/Logger.h>
@ -81,6 +83,17 @@ namespace triagens {
bindSocket();
}
ListenTask::ListenTask (struct addrinfo *aip, bool reuseAddress)
: Task("ListenTask"),
readWatcher(0),
reuseAddress(reuseAddress),
address(""),
port(0),
listenSocket(0),
bound(false),
acceptFailures(0) {
bindSocket(aip);
}
ListenTask::~ListenTask () {
@ -99,16 +112,6 @@ namespace triagens {
bool ListenTask::rebind () {
MUTEX_LOCKER(changeLock);
if (bound) {
close(listenSocket);
}
return bindSocket();
}
// -----------------------------------------------------------------------------
// Task methods
// -----------------------------------------------------------------------------
@ -216,13 +219,30 @@ namespace triagens {
// handle connection
ConnectionInfo info;
/*
info.serverAddress = inet_ntoa(addr_out.sin_addr);
info.serverPort = port;
info.clientAddress = inet_ntoa(addr.sin_addr);
info.clientPort = addr.sin_port;
*/
// set client address and port
char host[NI_MAXHOST], serv[NI_MAXSERV];
if (getnameinfo((sockaddr*) &addr, len,
host, sizeof(host),
serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
info.clientAddress = string(host);
info.clientPort = addr.sin_port;
}
else {
info.clientAddress = inet_ntoa(addr.sin_addr);
info.clientPort = addr.sin_port;
}
info.serverAddress = address;
info.serverPort = port;
return handleConnected(connfd, info);
}
@ -235,12 +255,68 @@ namespace triagens {
bool ListenTask::bindSocket () {
bound = false;
listenSocket = -1;
struct addrinfo *result, *aip;
struct addrinfo hints;
int error;
// create a new socket
listenSocket = socket(AF_INET, SOCK_STREAM, 0);
memset(&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_ALL;
hints.ai_socktype = SOCK_STREAM;
if (listenSocket < 0) {
LOGGER_ERROR << "socket failed with " << errno << " (" << strerror(errno) << ")";
string portString = StringUtils::itoa(port);
if (address.empty()) {
LOGGER_ERROR << "get any address";
error = getaddrinfo(NULL, portString.c_str(), &hints, &result);
}
else {
error = getaddrinfo(address.c_str(), portString.c_str(), &hints, &result);
}
if (error != 0) {
LOGGER_ERROR << "getaddrinfo for host: " << address.c_str() << " => " << gai_strerror(error);
return false;
}
// Try all returned addresses until one works
for (aip = result; aip != NULL; aip = aip->ai_next) {
// try to bind the address info pointer
if (bindSocket(aip)) {
// OK
break;
}
}
freeaddrinfo(result);
return bound;
}
bool ListenTask::bindSocket (struct addrinfo *aip) {
bound = false;
listenSocket = -1;
// set address and port
char host[NI_MAXHOST], serv[NI_MAXSERV];
if (getnameinfo(aip->ai_addr, aip->ai_addrlen,
host, sizeof(host),
serv, sizeof(serv), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
address = string(host);
port = StringUtils::int32(string(serv));
LOGGER_TRACE << "bind to address '" << address << "' port '" << string(serv) << "'";
}
listenSocket = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
if (listenSocket == -1) {
return false;
}
@ -248,57 +324,19 @@ namespace triagens {
if (reuseAddress) {
int opt = 1;
if (setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&opt), sizeof(opt)) == -1) {
if (setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*> (&opt), sizeof (opt)) == -1) {
LOGGER_ERROR << "setsockopt failed with " << errno << " (" << strerror(errno) << ")";
return false;
}
LOGGER_TRACE << "reuse address flag set";
}
// bind to any address
sockaddr_in addr;
if (address.empty()) {
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
}
// bind to a given address
else {
size_t length;
char* a = TRI_GetHostByName(address.c_str(), &length);
if (a == 0) {
LOGGER_ERROR << "cannot resolve hostname: " << errno << " (" << strerror(errno) << ")";
return false;
}
if (sizeof(addr.sin_addr.s_addr) < length) {
LOGGER_ERROR << "IPv6 address are not allowed";
return false;
}
// bind socket to an address
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
memcpy(&(addr.sin_addr.s_addr), a, length);
addr.sin_port = htons(port);
TRI_Free(a);
}
int res = bind(listenSocket, (const sockaddr*) &addr, sizeof(addr));
int res = bind(listenSocket, aip->ai_addr, aip->ai_addrlen);
if (res < 0) {
close(listenSocket);
LOGGER_ERROR << "bind failed with " << errno << " (" << strerror(errno) << ")";
(void) close(listenSocket);
listenSocket = -1;
return false;
}
@ -316,7 +354,7 @@ namespace triagens {
// set socket to non-blocking
bool ok = TRI_SetNonBlockingSocket(listenSocket);
if (! ok) {
if (!ok) {
close(listenSocket);
LOGGER_ERROR << "cannot switch to non-blocking: " << errno << " (" << strerror(errno) << ")";
@ -327,7 +365,7 @@ namespace triagens {
// set close on exit
ok = TRI_SetCloseOnExecSocket(listenSocket);
if (! ok) {
if (!ok) {
close(listenSocket);
LOGGER_ERROR << "cannot set close-on-exit: " << errno << " (" << strerror(errno) << ")";
@ -339,5 +377,6 @@ namespace triagens {
return true;
}
}
}

View File

@ -29,6 +29,8 @@
#ifndef TRIAGENS_FYN_REST_LISTEN_TASK_H
#define TRIAGENS_FYN_REST_LISTEN_TASK_H 1
#include <netdb.h>
#include "Scheduler/Task.h"
#include <Basics/Mutex.h>
@ -54,17 +56,23 @@ namespace triagens {
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief listen to given address and port
/// @brief listen to given address and port (deprecated)
////////////////////////////////////////////////////////////////////////////////
ListenTask (string const& address, int port, bool reuseAddress);
////////////////////////////////////////////////////////////////////////////////
/// @brief listen to given port
/// @brief listen to given port (deprecated)
////////////////////////////////////////////////////////////////////////////////
ListenTask (int port, bool reuseAddress);
////////////////////////////////////////////////////////////////////////////////
/// @brief listen to given adress info pointer
////////////////////////////////////////////////////////////////////////////////
ListenTask (struct addrinfo *aip, bool reuseAddress);
public:
////////////////////////////////////////////////////////////////////////////////
@ -73,15 +81,6 @@ namespace triagens {
bool isBound () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief try to rebind to port
///
/// Note that this method can only be called before the task has been
/// registered.
////////////////////////////////////////////////////////////////////////////////
bool rebind ();
protected:
////////////////////////////////////////////////////////////////////////////////
@ -132,11 +131,12 @@ namespace triagens {
private:
bool bindSocket ();
bool bindSocket (struct addrinfo *aip);
private:
bool reuseAddress;
string const address;
int const port;
string address;
int port;
socket_t listenSocket;
bool bound;

View File

@ -41,6 +41,7 @@
#include "v8-shell.h"
#include "v8-utils.h"
#include "v8-vocbase.h"
#include "v8-conv.h"
using namespace v8;

View File

@ -1,400 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief cursors and result sets
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "cursor.h"
////////////////////////////////////////////////////////////////////////////////
/// @def TRI_RESULTSET_INIT_SIZE
///
/// initial data size (in bytes) in each result set
////////////////////////////////////////////////////////////////////////////////
#define TRI_RESULTSET_INIT_SIZE 256
////////////////////////////////////////////////////////////////////////////////
/// @def TRI_RESULTSET_GROWTH_FACTOR
///
/// percentual growth factor for data in result sets
/// if a new allocation has to be made, the result set will grow by at least
/// this factor. The intention of this is to reduce the number of malloc calls
////////////////////////////////////////////////////////////////////////////////
#define TRI_RESULTSET_GROWTH_FACTOR 0.1
// -----------------------------------------------------------------------------
// --SECTION-- result sets
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief prepare next element in a single result set
////////////////////////////////////////////////////////////////////////////////
TRI_resultset_data_t *NextSingleResultset(TRI_resultset_t *resultset) {
TRI_resultset_data_t *current;
assert(resultset->_type == RESULTSET_TYPE_SINGLE);
if (resultset->_position == 0) {
resultset->_current = resultset->_data;
}
current = resultset->_current;
resultset->_current += sizeof(TRI_doc_mptr_t *);
++resultset->_position;
assert(resultset->_position < resultset->_length);
return current;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief prepare next element in a multi result set
////////////////////////////////////////////////////////////////////////////////
TRI_resultset_data_t *NextMultiResultset(TRI_resultset_t *resultset) {
TRI_resultset_data_t *current;
TRI_resultset_element_multi_t *data;
TRI_voc_size_t n;
TRI_doc_mptr_t **documents;
assert(resultset->_type == RESULTSET_TYPE_MULTI);
if (resultset->_position == 0) {
resultset->_current = resultset->_data;
}
current = resultset->_current;
data = (TRI_resultset_element_multi_t *) resultset->_current;
n = data->_num;
documents = data->_documents;
resultset->_current += sizeof(TRI_voc_size_t) + n * sizeof(TRI_doc_mptr_t *);
++resultset->_position;
assert(resultset->_position < resultset->_length);
return current;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free common data structures in the result set
////////////////////////////////////////////////////////////////////////////////
static void FreeResultset(TRI_resultset_t *resultset) {
TRI_Free(resultset->_alias);
TRI_Free(resultset->_data);
// free result set itself
TRI_Free(resultset);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free special data structures for single result sets
////////////////////////////////////////////////////////////////////////////////
static void FreeSingleResultset(TRI_resultset_t *resultset) {
FreeResultset(resultset);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free special data structures for multi result sets
////////////////////////////////////////////////////////////////////////////////
static void FreeMultiResultset(TRI_resultset_t *resultset) {
FreeResultset(resultset);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief increase the data storage size of a result size
///
/// the data size will grow by at least TRI_RESULTSET_GROWTH_FACTOR
////////////////////////////////////////////////////////////////////////////////
static bool IncreaseStorageResultset(TRI_resultset_t *resultset, size_t size) {
TRI_resultset_data_t *data;
size_t newSize = resultset->_storageAllocated + size;
if (resultset->_data == 0) {
// if result set is broken after a failed realloc, we must exit early
return false;
}
// increase by at least TRI_RESULTSET_GROWTH_FACTOR
if (newSize < (size_t) (resultset->_storageAllocated * TRI_RESULTSET_GROWTH_FACTOR)) {
newSize = (size_t) resultset->_storageAllocated * TRI_RESULTSET_GROWTH_FACTOR;
}
// TODO: wrap realloc
data = (TRI_resultset_data_t *) realloc(resultset->_data, newSize);
if (data == 0) {
return false;
}
resultset->_data = data;
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a single document to a single result set
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddDocumentSingleResultset(TRI_resultset_t *resultset, const TRI_doc_mptr_t *document) {
size_t storageNeeded = sizeof(TRI_doc_mptr_t *);
assert(resultset->_type == RESULTSET_TYPE_SINGLE);
if (resultset->_storageUsed + storageNeeded < resultset->_storageAllocated) {
if (IncreaseStorageResultset(resultset, storageNeeded)) {
// could not get any more memory => error
return false;
}
}
memcpy(resultset->_data + resultset->_storageUsed, document, sizeof(TRI_doc_mptr_t *));
resultset->_storageUsed += storageNeeded;
++resultset->_length;
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add multiple documents to a multiple result set
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddDocumentsMultiResultset(TRI_resultset_t *resultset, const TRI_voc_size_t n,
const TRI_doc_mptr_t **documents) {
size_t storageNeeded = sizeof(TRI_voc_size_t) + n * sizeof(TRI_doc_mptr_t *);
assert(resultset->_type == RESULTSET_TYPE_MULTI);
if (resultset->_storageUsed + storageNeeded < resultset->_storageAllocated) {
if (IncreaseStorageResultset(resultset, storageNeeded)) {
// could not get any more memory => error
return false;
}
}
memcpy(resultset->_data + resultset->_storageUsed, &n, sizeof(TRI_voc_size_t));
resultset->_storageUsed += sizeof(TRI_voc_size_t);
memcpy(resultset->_data + resultset->_storageUsed, documents, n);
resultset->_storageUsed += n * sizeof(TRI_doc_mptr_t *);
++resultset->_length;
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new result set
////////////////////////////////////////////////////////////////////////////////
TRI_resultset_t *TRI_CreateResultset(const TRI_resultset_type_e type, const char *alias) {
TRI_resultset_t *resultset = (TRI_resultset_t *) TRI_Allocate(sizeof(TRI_resultset_t));
if (resultset == 0) {
return 0;
}
resultset->_alias = TRI_DuplicateString(alias);
if (resultset->_alias == 0) {
TRI_Free(resultset);
return 0;
}
// init storage
resultset->_data = (TRI_resultset_data_t *)
TRI_Allocate(TRI_RESULTSET_INIT_SIZE * sizeof(TRI_resultset_data_t *));
if (resultset->_data == 0) {
TRI_Free(resultset->_alias);
TRI_Free(resultset);
return 0;
}
resultset->_storageAllocated = TRI_RESULTSET_INIT_SIZE;
resultset->_storageUsed = 0;
resultset->_type = type;
resultset->_length = 0;
resultset->_position = 0;
// setup function pointers
if (type == RESULTSET_TYPE_SINGLE) {
resultset->next = NextSingleResultset;
resultset->free = FreeSingleResultset;
}
else if (type == RESULTSET_TYPE_MULTI) {
resultset->next = NextMultiResultset;
resultset->free = FreeMultiResultset;
}
else {
assert(false);
}
return resultset;
}
// -----------------------------------------------------------------------------
// --SECTION-- cursors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief free a cursor
////////////////////////////////////////////////////////////////////////////////
static void FreeCursor(TRI_cursor_t *cursor) {
size_t i = cursor->_resultsets._length;
// free individual result sets (backwards, to save memmove calls in vector implementation
if (i > 0) {
while (true) {
i--;
FreeResultset((TRI_resultset_t *) cursor->_resultsets._buffer[i]);
if (i == 0) {
break;
}
}
}
// free results vector
TRI_DestroyVectorPointer(&cursor->_currentData->_data);
TRI_Free(cursor->_currentData);
// free result sets vector
TRI_DestroyVectorPointer(&cursor->_resultsets);
// free cursor itself
TRI_Free(cursor);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns true if the cursor has more elements
////////////////////////////////////////////////////////////////////////////////
static inline bool HasNextCursor(const TRI_cursor_t *cursor) {
return (cursor->_position < cursor->_length);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns next element for the cursor
////////////////////////////////////////////////////////////////////////////////
TRI_resultset_row_t* NextCursor(TRI_cursor_t *cursor) {
size_t i;
TRI_resultset_data_t *data;
TRI_resultset_t *resultset;
if (!HasNextCursor(cursor)) {
return 0;
}
// iterate over all result sets in cursor
for (i = 0; i < cursor->_resultsets._length; i++) {
resultset = (TRI_resultset_t *) cursor->_resultsets._buffer[i];
// set data pointer for result set
data = resultset->next(resultset);
cursor->_currentData->_data._buffer[i] = data;
}
++cursor->_position;
return cursor->_currentData;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a result set to a cursor
////////////////////////////////////////////////////////////////////////////////
static void AddResultsetCursor(TRI_cursor_t *cursor, const TRI_resultset_t *resultset) {
TRI_PushBackVectorPointer(&cursor->_resultsets, (TRI_resultset_t *) resultset);
// start with 0 pointer
TRI_PushBackVectorPointer(&cursor->_currentData->_data, 0);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new cursor
////////////////////////////////////////////////////////////////////////////////
TRI_cursor_t *TRI_CreateCursor(TRI_rc_context_t *context, TRI_qry_select_t *select) {
TRI_cursor_t *cursor = (TRI_cursor_t *) TRI_Allocate(sizeof(TRI_cursor_t));
if (cursor == 0) {
return 0;
}
cursor->_currentData = (TRI_resultset_row_t *) TRI_Allocate(sizeof(TRI_resultset_row_t));
if (cursor->_currentData == 0) {
TRI_Free(cursor);
return 0;
}
// init row result sets vector
TRI_InitVectorPointer(&cursor->_currentData->_data);
// init result sets vector
TRI_InitVectorPointer(&cursor->_resultsets);
// store context
cursor->_context = context;
cursor->_select = select;
// setup function pointers
cursor->next = NextCursor;
cursor->hasNext = HasNextCursor;
cursor->free = FreeCursor;
cursor->addResultset = AddResultsetCursor;
// init positional data
cursor->_length = 0;
cursor->_position = 0;
return cursor;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -25,7 +25,7 @@
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "join.h"
#include "VocBase/join.h"
////////////////////////////////////////////////////////////////////////////////
@ -34,226 +34,82 @@
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief free join data feeder
/// @brief Free join part memory
////////////////////////////////////////////////////////////////////////////////
static void FreeFeeder(TRI_join_feeder_t *feeder) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief init join data feeder
////////////////////////////////////////////////////////////////////////////////
static void InitFeeder(TRI_join_feeder_t *feeder) {
TRI_sim_collection_t *collection;
TRI_doc_mptr_t *document;
collection = (TRI_sim_collection_t *) feeder->_collection;
if (collection->_primaryIndex._nrAlloc == 0) {
feeder->_start = 0;
feeder->_end = 0;
feeder->_current = 0;
return;
static void FreePart (TRI_join_part_t* part) {
if (part->_alias) {
TRI_Free(part->_alias);
}
feeder->_start = (void **) collection->_primaryIndex._table;
feeder->_end = (void **) (feeder->_start + collection->_primaryIndex._nrAlloc);
// collections contain documents in a hash table
// some of the entries are empty, and some contain deleted documents
// it is invalid to use every entry from the hash table but the invalid documents
// must be skipped.
// adjust starts to first valid document in collection
while (feeder->_start < feeder->_end) {
document = (TRI_doc_mptr_t*) *(feeder->_start);
if (document != 0 && !document->_deletion) {
break;
}
feeder->_start++;
if (part->_collectionName) {
TRI_Free(part->_collectionName);
}
while (feeder->_end > feeder->_start) {
document = (TRI_doc_mptr_t*) *(feeder->_end - 1);
if (document != 0 && !document->_deletion) {
break;
}
feeder->_end--;
}
feeder->rewind(feeder);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief rewind join data feeder
////////////////////////////////////////////////////////////////////////////////
static void RewindFeeder(TRI_join_feeder_t *feeder) {
feeder->_current = feeder->_start;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get current item from join data feeder and advance next pointer
////////////////////////////////////////////////////////////////////////////////
TRI_doc_mptr_t *CurrentFeeder(TRI_join_feeder_t *feeder) {
TRI_doc_mptr_t *document;
while (feeder->_current < feeder->_end) {
document = (TRI_doc_mptr_t*) *(feeder->_current);
feeder->_current++;
if (document && document->_deletion == 0) {
return document;
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get next item from join data feeder and advance next pointer
////////////////////////////////////////////////////////////////////////////////
TRI_doc_mptr_t *NextFeeder(TRI_join_feeder_t *feeder) {
TRI_doc_mptr_t *document;
while (feeder->_current < feeder->_end) {
feeder->_current++;
document = (TRI_doc_mptr_t*) *(feeder->_current);
if (document && document->_deletion == 0) {
return document;
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free a join part
////////////////////////////////////////////////////////////////////////////////
static void FreePartJoin(TRI_join_part_t *part) {
part->_feeder->free(part->_feeder);
TRI_Free(part->_feeder);
TRI_Free(part);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a join part to a join
/// @brief Free join memory
////////////////////////////////////////////////////////////////////////////////
void TRI_AddPartJoin(TRI_join_t *join, const TRI_join_type_e type, TRI_resultset_t *resultset, TRI_sim_collection_t *collection) {
TRI_join_part_t *part;
TRI_join_feeder_t *feeder;
part = (TRI_join_part_t *) TRI_Allocate(sizeof(TRI_join_part_t));
if (part == 0) {
return;
static void FreeSelectJoin (TRI_select_join_t* join) {
TRI_join_part_t* part;
size_t i;
for (i = 0; i < join->_parts._length; i++) {
part = (TRI_join_part_t*) join->_parts._buffer[i];
part->free(part);
}
feeder = (TRI_join_feeder_t *) TRI_Allocate(sizeof(TRI_join_feeder_t));
if (feeder == 0) {
TRI_Free(part);
return;
}
feeder->_collection = collection;
feeder->init = InitFeeder;
feeder->rewind = RewindFeeder;
feeder->current = CurrentFeeder;
feeder->next = NextFeeder;
feeder->free = FreeFeeder;
feeder->init(feeder);
part->_type = type;
part->_resultset = resultset;
part->_feeder = feeder;
part->free = FreePartJoin;
TRI_PushBackVectorPointer(&join->_parts, part);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief free join memory
////////////////////////////////////////////////////////////////////////////////
static void FreeJoin(TRI_join_t *join) {
TRI_join_part_t *part;
size_t n = join->_parts._length;
if (n > 0) {
while (true) {
n--;
part = join->_parts._buffer[n];
part->free(part);
if (n == 0) {
break;
}
}
}
TRI_DestroyVectorPointer(&join->_parts);
TRI_Free(join);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief initialize a join
/// @brief Add a part to a select join
////////////////////////////////////////////////////////////////////////////////
TRI_join_t *TRI_CreateJoin() {
TRI_join_t *join = (TRI_join_t*) TRI_Allocate(sizeof(TRI_join_t));
bool TRI_AddPartSelectJoin (TRI_select_join_t* join, const TRI_join_type_e type,
TRI_qry_where_t* condition, char* collectionName,
char* alias) {
TRI_join_part_t* part;
assert(join != 0);
part = (TRI_join_part_t*) TRI_Allocate(sizeof(TRI_join_part_t));
if (join == 0) {
return 0;
if (part == 0) {
return false;
}
part->_type = type;
part->_condition = condition;
part->_collection = 0;
part->_collectionName = TRI_DuplicateString(collectionName);
part->_alias = TRI_DuplicateString(alias);
part->free = FreePart;
TRI_InitVectorPointer(&join->_parts);
join->free = FreeJoin;
return join;
TRI_PushBackVectorPointer(&join->_parts, part);
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief execute joins
/// @brief Create a new join
////////////////////////////////////////////////////////////////////////////////
void TRI_ExecuteJoin(TRI_join_t *join) {
size_t numJoins;
size_t current;
TRI_join_feeder_t *feeder;
TRI_doc_mptr_t *document;
size_t numEval = 0;
TRI_select_join_t* TRI_CreateSelectJoin (void) {
TRI_select_join_t* join;
numJoins = join->_parts._length - 1;
current = numJoins;
// actual join loop - implemented as nested loop join
// it currently does not use indexes etc. so the performance is as worst as can be
feeder = ((TRI_join_part_t *) join->_parts._buffer[current])->_feeder;
JOIN_NEXT:
document = feeder->current(feeder);
if (document) {
numEval++;
goto JOIN_NEXT;
}
JOIN_REPEAT:
if (current == 0) {
goto JOIN_END;
join = (TRI_select_join_t*) TRI_Allocate(sizeof(TRI_select_join_t));
if (join == NULL) {
return NULL;
}
feeder->rewind(feeder);
--current;
feeder = ((TRI_join_part_t *) join->_parts._buffer[current])->_feeder;
document = feeder->next(feeder);
if (document) {
current = numJoins;
feeder = ((TRI_join_part_t *) join->_parts._buffer[current])->_feeder;
goto JOIN_NEXT;
}
goto JOIN_REPEAT;
assert(false);
TRI_InitVectorPointer(&join->_parts);
join->free = FreeSelectJoin;
JOIN_END:
printf("JOIN NUM EVAL: %lu\n",numEval);
return join;
}
////////////////////////////////////////////////////////////////////////////////
@ -266,4 +122,3 @@ JOIN_END:
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief joins
/// @brief %BRIEF%
///
/// @file
///
@ -25,11 +25,14 @@
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_STORAGE_DURHAM_JOIN
#define TRIAGENS_STORAGE_DURHAM_JOIN
#ifndef TRIAGENS_DURHAM_VOC_BASE_JOIN_H
#define TRIAGENS_DURHAM_VOC_BASE_JOIN_H 1
#include "simple-collection.h"
#include "cursor.h"
#include <BasicsC/common.h>
#include <BasicsC/vector.h>
#include <BasicsC/strings.h>
#include "VocBase/query.h"
#ifdef __cplusplus
extern "C" {
@ -46,71 +49,54 @@ extern "C" {
typedef enum {
JOIN_TYPE_PRIMARY,
JOIN_TYPE_LIST,
JOIN_TYPE_INNER,
JOIN_TYPE_OUTER
JOIN_TYPE_OUTER,
JOIN_TYPE_LIST
}
TRI_join_type_e;
////////////////////////////////////////////////////////////////////////////////
/// @brief input for join operator
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_join_feeder_s {
TRI_sim_collection_t *_collection;
void **_start;
void **_end;
void **_current;
void (*init) (struct TRI_join_feeder_s*);
void (*rewind) (struct TRI_join_feeder_s*);
TRI_doc_mptr_t *(*current) (struct TRI_join_feeder_s*);
TRI_doc_mptr_t *(*next) (struct TRI_join_feeder_s*);
void (*free) (struct TRI_join_feeder_s*);
}
TRI_join_feeder_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief join data structure
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_join_part_s {
TRI_join_feeder_t *_feeder; // data source
TRI_resultset_t *_resultset; // result output
TRI_join_type_e _type;
TRI_qry_where_t* _condition;
TRI_doc_collection_t* _collection;
char* _collectionName;
char* _alias;
// TRI_js_exec_context_t _context;
void (*free) (struct TRI_join_part_s*);
}
TRI_join_part_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief multi join container data structure
/// @brief join container data structure for select queries
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_join_s {
typedef struct TRI_select_join_s {
TRI_vector_pointer_t _parts;
void (*free) (struct TRI_join_s*);
void (*free) (struct TRI_select_join_s*);
}
TRI_join_t;
TRI_select_join_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief add a join part to a join
/// @brief Add a part to a select join
////////////////////////////////////////////////////////////////////////////////
void TRI_AddPartJoin(TRI_join_t *, const TRI_join_type_e, TRI_resultset_t *, TRI_sim_collection_t *);
bool TRI_AddPartSelectJoin(TRI_select_join_t*,
const TRI_join_type_e,
TRI_qry_where_t*,
char*,
char*);
////////////////////////////////////////////////////////////////////////////////
/// @brief initialize a join
/// @brief Create a new join
////////////////////////////////////////////////////////////////////////////////
TRI_join_t *TRI_CreateJoin(void);
////////////////////////////////////////////////////////////////////////////////
/// @brief execute joins
////////////////////////////////////////////////////////////////////////////////
void TRI_ExecuteJoin(TRI_join_t *);
TRI_select_join_t* TRI_CreateSelectJoin (void);
////////////////////////////////////////////////////////////////////////////////
/// @}

View File

@ -30,6 +30,7 @@
#include "BasicsC/logging.h"
#include "BasicsC/strings.h"
#include "VocBase/simple-collection.h"
#include "VocBase/select-result.h"
// -----------------------------------------------------------------------------
// --SECTION-- SELECT DOCUMENT
@ -1445,6 +1446,9 @@ TRI_rc_cursor_t* TRI_ExecuteQueryAql (TRI_query_t* query, TRI_rc_context_t* cont
cond_fptr condition;
order_fptr order;
bool applyPostSkipLimit;
TRI_select_result_t* _select;
TRI_vector_pointer_t* _dataparts;
TRI_select_datapart_t* _datapart;
skip = query->_skip;
limit = query->_limit;
@ -1524,6 +1528,18 @@ TRI_rc_cursor_t* TRI_ExecuteQueryAql (TRI_query_t* query, TRI_rc_context_t* cont
order = OrderDataGeneralQuery;
}
// stj
_dataparts = (TRI_vector_pointer_t*) TRI_Allocate(sizeof(TRI_vector_pointer_t));
TRI_InitVectorPointer(_dataparts);
_datapart = TRI_CreateDataPart("fux", query->_primary, RESULT_PART_SINGLE);
TRI_PushBackVectorPointer(_dataparts, _datapart);
_select = TRI_CreateSelectResult(_dataparts);
if (_select != NULL) {
_select->free(_select);
}
// .............................................................................
// construct a collection subset
// .............................................................................

286
VocBase/select-result.c Normal file
View File

@ -0,0 +1,286 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief selects and select result sets
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "VocBase/select-result.h"
#include "VocBase/query.h"
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup VocBase
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief Growth factor for select memory allocation
////////////////////////////////////////////////////////////////////////////////
#define TRI_SELECT_RESULT_GROWTH_FACTOR 1.5
////////////////////////////////////////////////////////////////////////////////
/// @brief Free memory allocated for dataparts
////////////////////////////////////////////////////////////////////////////////
static void FreeDataPart(TRI_select_datapart_t* datapart) {
if (datapart->_alias != NULL) {
TRI_Free(datapart->_alias);
}
TRI_Free(datapart);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Create a new select datapart instance
////////////////////////////////////////////////////////////////////////////////
TRI_select_datapart_t* TRI_CreateDataPart(const char* alias,
const TRI_doc_collection_t* collection,
const TRI_select_data_e type) {
TRI_select_datapart_t* datapart;
datapart = (TRI_select_datapart_t*) TRI_Allocate(sizeof(TRI_select_datapart_t));
if (datapart == NULL) {
return NULL;
}
datapart->_alias = TRI_DuplicateString(alias);
datapart->_collection = (TRI_doc_collection_t*) collection;
datapart->_type = type;
datapart->free = FreeDataPart;
return datapart;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Free memory allocated for select result
////////////////////////////////////////////////////////////////////////////////
static void FreeSelectResult (TRI_select_result_t* _select) {
TRI_select_datapart_t* datapart;
size_t i;
if (_select->_index._start != NULL) {
TRI_Free(_select->_index._start);
}
if (_select->_documents._start != NULL) {
TRI_Free(_select->_documents._start);
}
for (i = 0; i < _select->_dataParts->_length; i++) {
datapart = (TRI_select_datapart_t*) _select->_dataParts->_buffer[i];
datapart->free(datapart);
}
TRI_DestroyVectorPointer(_select->_dataParts);
TRI_Free(_select->_dataParts);
TRI_Free(_select);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Initialise a select result
////////////////////////////////////////////////////////////////////////////////
static void InitSelectResult (TRI_select_result_t* _select,
TRI_vector_pointer_t* dataparts) {
_select->_index._numAllocated = 0;
_select->_index._numUsed = 0;
_select->_index._start = 0;
_select->_documents._bytesAllocated = 0;
_select->_documents._bytesUsed = 0;
_select->_documents._start = 0;
_select->_documents._current = 0;
_select->_dataParts = dataparts;
_select->_numRows = 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Increase storage size for select result index
////////////////////////////////////////////////////////////////////////////////
static bool IncreaseIndexStorageSelectResult (TRI_select_result_t* _select,
const size_t numNeeded) {
void *start;
size_t newSize;
newSize = (size_t) _select->_index._numAllocated + numNeeded;
if (newSize <
(size_t) (_select->_index._numAllocated * TRI_SELECT_RESULT_GROWTH_FACTOR)) {
newSize = (size_t) (_select->_index._numAllocated * TRI_SELECT_RESULT_GROWTH_FACTOR);
}
start = realloc(_select->_index._start, newSize * sizeof(void *));
if (start == 0) {
return false;
}
_select->_index._numAllocated = newSize;
_select->_index._start = start;
_select->_index._current = (uint8_t *) start +
(_select->_index._numUsed * sizeof(void *));
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Increase storage size for select documents data
////////////////////////////////////////////////////////////////////////////////
static bool IncreaseDocumentsStorageSelectResult(TRI_select_result_t* _select,
size_t bytesNeeded) {
size_t newSize;
void* start;
newSize = (size_t) _select->_documents._bytesAllocated + bytesNeeded;
if (newSize < (size_t) (_select->_documents._bytesAllocated * 1.5)) {
newSize = (size_t) (_select->_documents._bytesAllocated * 1.5);
}
start = realloc(_select->_documents._start, newSize);
if (start == 0) {
return false;
}
if (start != _select->_documents._start && _select->_documents._start != 0) {
// FIXME: adjust entries in index
assert(false);
}
_select->_documents._bytesAllocated = newSize;
_select->_documents._start = start;
_select->_documents._current = (uint8_t *) start + _select->_documents._bytesUsed;
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Get the required storage size for a document result
////////////////////////////////////////////////////////////////////////////////
static size_t GetDocumentSizeSelectResult (const TRI_select_result_t* _select,
const TRI_vector_pointer_t* documents) {
TRI_vector_pointer_t* part;
size_t i, total;
total = 0;
for (i = 0; i < documents->_length; i++) {
total += sizeof(TRI_select_size_t);
part = (TRI_vector_pointer_t*) documents->_buffer[i];
total += sizeof(TRI_doc_mptr_t*) * part->_length;
}
return total;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Add a document to the result set
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddDocumentSelectResult (TRI_select_result_t* _select,
TRI_vector_pointer_t* documents) {
TRI_select_size_t* numPtr;
TRI_doc_mptr_t** dataPtr;
void* startPtr;
TRI_vector_pointer_t* part;
size_t numNeeded;
size_t bytesNeeded;
size_t i, j;
numNeeded = documents->_length;
if (_select->_index._numUsed + documents->_length > _select->_index._numAllocated) {
if (!IncreaseIndexStorageSelectResult(_select, numNeeded)) {
return false;
}
}
bytesNeeded = GetDocumentSizeSelectResult(_select, documents);
if (_select->_documents._bytesUsed + bytesNeeded > _select->_documents._bytesAllocated) {
if (!IncreaseDocumentsStorageSelectResult(_select, bytesNeeded)) {
return false;
}
}
// store pointer to document
startPtr = _select->_index._current;
dataPtr = (TRI_doc_mptr_t**) startPtr;
*dataPtr++ = startPtr;
_select->_index._current = (void*) dataPtr;
_select->_index._numUsed++;
// store document data
startPtr = _select->_documents._current;
numPtr = (TRI_select_size_t*) startPtr;
for (i = 0; i < documents->_length; i++) {
part = (TRI_vector_pointer_t*) documents->_buffer[i];
*numPtr++ = part->_length;
dataPtr = (TRI_doc_mptr_t**) numPtr;
for (j = 0; j < part->_length; j++) {
*dataPtr++ = (TRI_doc_mptr_t*) part->_buffer[j];
}
numPtr = (TRI_select_size_t*) dataPtr;
}
_select->_documents._bytesUsed += bytesNeeded;
_select->_documents._current = numPtr;
_select->_numRows++;
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Create a new select result
////////////////////////////////////////////////////////////////////////////////
TRI_select_result_t* TRI_CreateSelectResult (TRI_vector_pointer_t *dataparts) {
TRI_select_result_t* result;
result = (TRI_select_result_t*) TRI_Allocate(sizeof(TRI_select_result_t));
if (!result) {
return NULL;
}
InitSelectResult(result, dataparts);
result->free = FreeSelectResult;
return result;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
// End:

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief cursors and result sets
/// @brief select result
///
/// @file
///
@ -25,16 +25,14 @@
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_DURHAM_VOC_BASE_CURSOR
#define TRIAGENS_DURHAM_VOC_BASE_CURSOR
#include <stdlib.h>
#ifndef TRIAGENS_DURHAM_VOC_BASE_SELECT_RESULT_H
#define TRIAGENS_DURHAM_VOC_BASE_SELECT_RESULT_H 1
#include <BasicsC/common.h>
#include <BasicsC/vector.h>
#include <BasicsC/strings.h>
#include "VocBase/vocbase.h"
#include "VocBase/query.h"
#include "VocBase/document-collection.h"
#ifdef __cplusplus
extern "C" {
@ -46,133 +44,107 @@ extern "C" {
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief result set types
/// RESULTSET_TYPE_SINGLE means the result set will contain one element per
/// result row, RESULTSET_TYPE_MULTI means the result set will contain multiple
/// (0..n) elements per result row
/// @brief result part type (single document or multiple documents)
////////////////////////////////////////////////////////////////////////////////
typedef enum {
RESULTSET_TYPE_UNDEFINED = 0,
RESULTSET_TYPE_SINGLE,
RESULTSET_TYPE_MULTI
}
TRI_resultset_type_e;
////////////////////////////////////////////////////////////////////////////////
/// @brief typedef for result set data
////////////////////////////////////////////////////////////////////////////////
typedef char TRI_resultset_data_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief result set element (base type)
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_resultset_element_s {
void *_data;
TRI_resultset_type_e _type;
void (*free) (struct TRI_resultset_element_s*);
bool (*toJavaScript) (struct TRI_resultset_element_s*, TRI_rc_result_t*, void*);
RESULT_PART_SINGLE = 0,
RESULT_PART_MULTI = 1
}
TRI_resultset_element_t;
TRI_select_data_e;
////////////////////////////////////////////////////////////////////////////////
/// @brief single result set element
/// @brief typedef for number of rows in a select result
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_resultset_element_single_s {
TRI_doc_mptr_t *_document;
}
TRI_resultset_element_single_t;
typedef uint32_t TRI_select_size_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief multiple result set element
/// @brief select input type
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_select_feeder_s {
TRI_doc_collection_t* _collection;
typedef struct TRI_resultset_element_multi_s {
TRI_voc_size_t _num;
TRI_doc_mptr_t **_documents;
}
TRI_resultset_element_multi_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief result set type
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_resultset_s {
TRI_voc_size_t _length;
TRI_voc_size_t _position;
TRI_resultset_type_e _type;
char *_alias;
TRI_resultset_data_t *_data;
TRI_resultset_data_t *_current;
size_t _storageUsed;
size_t _storageAllocated;
void (*free) (struct TRI_resultset_s*);
TRI_resultset_data_t *(*next)(struct TRI_resultset_s*);
// bool (*toJavaScript) (struct TRI_resultset_s*, void*);
}
TRI_resultset_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief result set row type
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_resultset_row_s {
TRI_vector_pointer_t _data;
bool (*toJavaScript) (struct TRI_resultset_row_s*, void*);
void (*init) (struct TRI_select_feeder_s*);
void (*rewind) (struct TRI_select_feeder_s*);
TRI_doc_mptr_t* (*current) (struct TRI_select_feeder_s*);
TRI_doc_mptr_t* (*next) (struct TRI_select_feeder_s*);
}
TRI_resultset_row_t;
TRI_select_feeder_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief cursor type
/// @brief select data parts type
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_cursor_s {
TRI_rc_context_t* _context;
TRI_qry_select_t* _select;
typedef struct TRI_select_datapart_s {
char* _alias;
TRI_doc_collection_t* _collection;
TRI_select_data_e _type;
TRI_vector_pointer_t _resultsets;
TRI_voc_size_t _length;
TRI_voc_size_t _position;
TRI_resultset_row_t *_currentData;
void (*free) (struct TRI_cursor_s*);
TRI_resultset_row_t* (*next)(struct TRI_cursor_s*);
bool (*hasNext)(const struct TRI_cursor_s*);
void (*addResultset)(struct TRI_cursor_s*, const TRI_resultset_t*);
void (*free) (struct TRI_select_datapart_s*);
}
TRI_cursor_t;
TRI_select_datapart_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief add a single document to a single result set
/// @brief Create a new select datapart instance
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddDocumentSingleResultset(TRI_resultset_t *, const TRI_doc_mptr_t *);
////////////////////////////////////////////////////////////////////////////////
/// @brief add multiple documents (0..n) to a multiple result set
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddDocumentsMultiResultset(TRI_resultset_t *, const TRI_voc_size_t,
const TRI_doc_mptr_t **);
TRI_select_datapart_t* TRI_CreateDataPart(const char*,
const TRI_doc_collection_t*,
const TRI_select_data_e);
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new result set
/// @brief document index within a select result
////////////////////////////////////////////////////////////////////////////////
TRI_resultset_t *TRI_CreateResultset(const TRI_resultset_type_e, const char*);
typedef struct TRI_select_result_index_s {
TRI_select_size_t _numAllocated;
TRI_select_size_t _numUsed;
void *_start;
void *_current;
}
TRI_select_result_index_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief create a new cursor
/// @brief document storage within a select result
////////////////////////////////////////////////////////////////////////////////
TRI_cursor_t *TRI_CreateCursor(TRI_rc_context_t *, TRI_qry_select_t *);
typedef struct TRI_select_result_documents_s {
size_t _bytesAllocated;
size_t _bytesUsed;
void *_start;
void *_current;
}
TRI_select_result_documents_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief select result type
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_select_result_s {
TRI_select_size_t _numRows;
TRI_vector_pointer_t* _dataParts;
TRI_select_result_index_t _index;
TRI_select_result_documents_t _documents;
void (*free) (struct TRI_select_result_s*);
}
TRI_select_result_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief Add a document to the result set
////////////////////////////////////////////////////////////////////////////////
bool TRI_AddDocumentSelectResult (TRI_select_result_t*, TRI_vector_pointer_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief Create a new select result
////////////////////////////////////////////////////////////////////////////////
TRI_select_result_t* TRI_CreateSelectResult (TRI_vector_pointer_t*);
////////////////////////////////////////////////////////////////////////////////
/// @}

View File

@ -1 +1 @@
#define TRIAGENS_VERSION "0.0.8 [1311M]"
#define TRIAGENS_VERSION "0.0.8 [1316:1317M]"

View File

@ -13,7 +13,7 @@ if test -d ${DIR}/.svn; then
revision=`(cd $DIR && svnversion)`
else
if test ! -f "$INFO"; then
echo "WARNING: cannot open info file $INFO"
echo "INFO: cannot open info file $INFO, using exported"
revision="exported"
else
revision=`grep 'Revision:' $INFO | awk '{print $2}'`

View File

@ -120,6 +120,7 @@ case $target in
STATIC_LIBS=""
DYNAMIC_LIBS=""
LIBTOOL_LIBS=""
USE_DYLD="yes"
;;
*)

View File

@ -6,17 +6,20 @@ dnl ----------------------------------------------------------------------------
V8_CPPFLAGS=""
V8_LDFLAGS=""
V8_LIBS=""
AC_ARG_WITH(v8,
AS_HELP_STRING([--with-v8=DIR], [where the v8 library and includes are located]),
[V8_CPPFLAGS="-I$withval/include"
V8_LDFLAGS="-L$withval/lib"
V8_LIB_PATH="$withval/lib"
V8="$withval"]
)
AC_ARG_WITH(v8-lib,
AS_HELP_STRING([--with-v8-lib=DIR], [where the v8 library is located]),
[V8_LDFLAGS="-L$withval"]
[V8_LDFLAGS="-L$withval"
V8_LIB_PATH="$withval"]
)
TR_STATIC_ENABLE([v8])
@ -75,6 +78,8 @@ if test "$cross_compiling" = yes; then :
TRI_V8_VERSION="V8"
AC_MSG_WARN([cannot compute V8 version number when cross compiling])
else
if test "x`type -t ac_fn_cxx_try_run`" = "xfunction" 2> /dev/null; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <v8.h>
@ -85,8 +90,19 @@ int main (int, char**) {
}
_ACEOF
if test "x`type -t ac_fn_cxx_try_run`" = "xfunction" 2> /dev/null; then
if test "x$V8_LIB_PATH" != x; then
if test "$USE_DYLD" = yes; then
save_DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH"
DYLD_LIBRARY_PATH="$V8_LIB_PATH:$DYLD_LIBRARY_PATH"
else
save_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
DYLD_LIBRARY_PATH="$V8_LIB_PATH:$LD_LIBRARY_PATH"
fi
fi
AC_MSG_CHECKING([V8 version])
if ac_fn_cxx_try_run "$LINENO" >conftest.output; then
TRI_V8_VERSION=`cat conftest.output`
AC_MSG_RESULT([$TRI_V8_VERSION])
@ -94,12 +110,21 @@ _ACEOF
AC_MSG_RESULT([failed])
AC_MSG_ERROR([Please install the V8 library from Google])
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.beam conftest.$ac_ext conftest.output
if test "x$V8_LIB_PATH" != x; then
if test "$USE_DYLD" = yes; then
DYLD_LIBRARY_PATH="$save_DYLD_LIBRARY_PATH"
else
LD_LIBRARY_PATH="$save_LD_LIBRARY_PATH"
fi
fi
else
TRI_V8_VERSION="V8"
AC_MSG_WARN([cannot compute V8 version number, old autoconf version])
fi
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.beam conftest.$ac_ext conftest.output
dnl -----------------------------------------------------------------------------------------