From 9baae9c129fd727b09228b0bfcb1870d5483d040 Mon Sep 17 00:00:00 2001 From: Oreste Panaia Date: Wed, 9 Jan 2013 22:23:35 +0800 Subject: [PATCH 01/12] windows bug fixes --- arangod/Ahuacatl/ahuacatl-scope.c | 10 ++++++++-- lib/BasicsC/files.c | 14 +++++++++++++- lib/BasicsC/win-utils.c | 23 +++++++++++++++-------- lib/Scheduler/Scheduler.cpp | 6 +++--- 4 files changed, 39 insertions(+), 14 deletions(-) mode change 100644 => 100755 arangod/Ahuacatl/ahuacatl-scope.c mode change 100644 => 100755 lib/BasicsC/win-utils.c mode change 100644 => 100755 lib/Scheduler/Scheduler.cpp diff --git a/arangod/Ahuacatl/ahuacatl-scope.c b/arangod/Ahuacatl/ahuacatl-scope.c old mode 100644 new mode 100755 index d0cc2dcf86..d751b921ba --- a/arangod/Ahuacatl/ahuacatl-scope.c +++ b/arangod/Ahuacatl/ahuacatl-scope.c @@ -348,10 +348,13 @@ bool TRI_VariableExistsScopeAql (TRI_aql_context_t* const context, n = context->_currentScopes._length; assert(n > 0); + printf("oreste:%s:%d:[%d]\n",__FILE__,__LINE__,n); + while (n > 0) { TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AtVectorPointer(&context->_currentScopes, --n); assert(scope); + printf("oreste:%s:%d:[%s]\n",__FILE__,__LINE__,name); if (TRI_LookupByKeyAssociativePointer(&scope->_variables, (void*) name)) { // duplicate variable return true; @@ -375,7 +378,8 @@ bool TRI_AddVariableScopeAql (TRI_aql_context_t* const context, TRI_aql_node_t* const definingNode) { TRI_aql_variable_t* variable; TRI_aql_scope_t* scope; - + void* result; + assert(context); assert(name); @@ -389,8 +393,10 @@ bool TRI_AddVariableScopeAql (TRI_aql_context_t* const context, } scope = CurrentScope(context); - assert(! TRI_InsertKeyAssociativePointer(&scope->_variables, variable->_name, (void*) variable, false)); + result = TRI_InsertKeyAssociativePointer(&scope->_variables, variable->_name, (void*) variable, false); + assert(result != NULL); + return true; } diff --git a/lib/BasicsC/files.c b/lib/BasicsC/files.c index d2b1f92a3c..b221fab7e0 100755 --- a/lib/BasicsC/files.c +++ b/lib/BasicsC/files.c @@ -847,6 +847,14 @@ int TRI_VerifyLockFile (char const* filename) { } fd = TRI_OPEN(filename, O_RDONLY); + if (fd < 0) { + // this method if checking whether or not the database is locked is not suitable with the manner + // in which it is coded. + // windows assigns ownership of the file to the process for exclusive use + // the file exists, yet we can not open it, so being here we can only assume that the + // database is locked. + return TRI_ERROR_NO_ERROR; + } n = TRI_READ(fd, buffer, sizeof(buffer)); TRI_CLOSE(fd); @@ -992,7 +1000,11 @@ int TRI_DestroyLockFile (char const* filename) { fd = TRI_OPEN(filename, O_RDWR); - + + if (fd < 0) { + return false; + } + // .......................................................................... // TODO: Use windows LockFileEx to determine if file can be locked // .......................................................................... diff --git a/lib/BasicsC/win-utils.c b/lib/BasicsC/win-utils.c old mode 100644 new mode 100755 index e836c7a5ed..42eb30d520 --- a/lib/BasicsC/win-utils.c +++ b/lib/BasicsC/win-utils.c @@ -105,15 +105,22 @@ void TRI_usleep(unsigned long waitTime) { return; } + if (GetLastError() == ERROR_ALREADY_EXISTS) { + abort(); + } // Set timer to wait for indicated micro seconds. if (!SetWaitableTimer(hTimer, &wTime, 0, NULL, NULL, 0)) { // no much we can do at this low level return; } - // Wait for the timer - but don't wait for ever. - result = WaitForSingleObject(hTimer, ((waitTime/1000) + 1)); // wait for a 1 millisecond at least + // Wait for the timer + result = WaitForSingleObject(hTimer, INFINITE); + if (result != WAIT_OBJECT_0) { + abort(); + } + CloseHandle(hTimer); // todo: go through what the result is e.g. WAIT_OBJECT_0 return; } @@ -152,7 +159,7 @@ static void InvalidParameterHandler(const wchar_t* expression, // expression sen else { wprintf(L"win-utils.c:InvalidParameterHandler:FILE = NULL\n"); } - printf("oreste:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%:win-utils.c:InvalidParameterHandler:LINE = %ud\n",line); + printf("oreste:win-utils.c:InvalidParameterHandler:LINE = %ud\n",line); /* end oreste -debug */ //abort(); // TODO: use the wcstombs_s function to convert wchar to char - since all the above @@ -171,7 +178,8 @@ static void InvalidParameterHandler(const wchar_t* expression, // expression sen int finaliseWindows(const TRI_win_finalise_e finaliseWhat, const char* data) { - + int result = 0; + // ............................................................................ // The data is used to transport information from the calling function to here // it may be NULL (and will be in most cases) @@ -180,11 +188,10 @@ int finaliseWindows(const TRI_win_finalise_e finaliseWhat, const char* data) { switch (finaliseWhat) { case TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL: { - int errorCode; - errorCode = WSACleanup(); - if (errorCode != 0) { + result = WSACleanup(); // could this cause error on server termination? + if (result != 0) { // can not use LOG_ etc here since the logging may have terminated - printf("ERROR: Could not perform a valid Winsock2 cleanup. WSACleanup returned error %d.",errorCode); + printf("ERROR: Could not perform a valid Winsock2 cleanup. WSACleanup returned error %d.",result); return -1; } return 0; diff --git a/lib/Scheduler/Scheduler.cpp b/lib/Scheduler/Scheduler.cpp old mode 100644 new mode 100755 index bbca3ec0e2..bbecdab183 --- a/lib/Scheduler/Scheduler.cpp +++ b/lib/Scheduler/Scheduler.cpp @@ -272,7 +272,7 @@ void Scheduler::unregisterTask (Task* task) { map::iterator i = task2thread.find(task); if (i == task2thread.end()) { - LOGGER_WARNING << "unregisterTask called for a unknown task " << task << " (" << task->getName() << ")"; + LOGGER_WARNING << "unregisterTask called for an unknown task " << task << " (" << task->getName() << ")"; return; } @@ -306,7 +306,7 @@ void Scheduler::destroyTask (Task* task) { map::iterator i = task2thread.find(task); if (i == task2thread.end()) { - LOGGER_WARNING << "destroyTask called for a unknown task " << task << " (" << task->getName() << ")"; + LOGGER_WARNING << "destroyTask called for an unknown task " << task << " (" << task->getName() << ")"; return; } @@ -323,7 +323,7 @@ void Scheduler::destroyTask (Task* task) { task2thread.erase(i); } } - + thread->destroyTask(task); } From c01a5c6275a5c881aff5d387afd34ce52806e8c1 Mon Sep 17 00:00:00 2001 From: Oreste Panaia Date: Mon, 14 Jan 2013 20:16:09 +0800 Subject: [PATCH 02/12] arango shell and import --- arangod/Ahuacatl/ahuacatl-scope.c | 5 +- arangod/RestServer/arango.cpp | 1 - arangosh/ArangoShell/ArangoClient.cpp | 23 ++ arangosh/V8Client/ImportHelper.cpp | 14 +- arangosh/V8Client/ImportHelper.h | 8 +- arangosh/V8Client/V8ClientConnection.cpp | 2 + arangosh/V8Client/arangoimp.cpp | 40 ++- arangosh/V8Client/arangosh.cpp | 108 +++++++- lib/BasicsC/files.c | 9 +- lib/BasicsC/messages.h | 0 lib/BasicsC/operating-system.h | 4 + lib/BasicsC/win-utils.c | 2 - lib/BasicsC/win-utils.h | 261 +++++++++--------- lib/Rest/EndpointIp.cpp | 70 +++++ lib/SimpleHttpClient/ClientConnection.cpp | 8 +- lib/SimpleHttpClient/ClientConnection.h | 4 +- .../GeneralClientConnection.cpp | 4 +- .../GeneralClientConnection.h | 4 +- lib/SimpleHttpClient/SslClientConnection.cpp | 4 +- lib/SimpleHttpClient/SslClientConnection.h | 4 +- 20 files changed, 411 insertions(+), 164 deletions(-) mode change 100644 => 100755 arangod/RestServer/arango.cpp mode change 100644 => 100755 arangosh/ArangoShell/ArangoClient.cpp mode change 100644 => 100755 arangosh/V8Client/ImportHelper.cpp mode change 100644 => 100755 arangosh/V8Client/ImportHelper.h mode change 100644 => 100755 arangosh/V8Client/V8ClientConnection.cpp mode change 100644 => 100755 arangosh/V8Client/arangoimp.cpp mode change 100644 => 100755 arangosh/V8Client/arangosh.cpp mode change 100644 => 100755 lib/BasicsC/messages.h mode change 100644 => 100755 lib/BasicsC/operating-system.h mode change 100644 => 100755 lib/BasicsC/win-utils.h mode change 100644 => 100755 lib/SimpleHttpClient/ClientConnection.cpp mode change 100644 => 100755 lib/SimpleHttpClient/ClientConnection.h mode change 100644 => 100755 lib/SimpleHttpClient/GeneralClientConnection.cpp mode change 100644 => 100755 lib/SimpleHttpClient/GeneralClientConnection.h mode change 100644 => 100755 lib/SimpleHttpClient/SslClientConnection.cpp mode change 100644 => 100755 lib/SimpleHttpClient/SslClientConnection.h diff --git a/arangod/Ahuacatl/ahuacatl-scope.c b/arangod/Ahuacatl/ahuacatl-scope.c index d751b921ba..0eac469525 100755 --- a/arangod/Ahuacatl/ahuacatl-scope.c +++ b/arangod/Ahuacatl/ahuacatl-scope.c @@ -348,13 +348,10 @@ bool TRI_VariableExistsScopeAql (TRI_aql_context_t* const context, n = context->_currentScopes._length; assert(n > 0); - printf("oreste:%s:%d:[%d]\n",__FILE__,__LINE__,n); - while (n > 0) { TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AtVectorPointer(&context->_currentScopes, --n); assert(scope); - printf("oreste:%s:%d:[%s]\n",__FILE__,__LINE__,name); if (TRI_LookupByKeyAssociativePointer(&scope->_variables, (void*) name)) { // duplicate variable return true; @@ -395,7 +392,7 @@ bool TRI_AddVariableScopeAql (TRI_aql_context_t* const context, scope = CurrentScope(context); result = TRI_InsertKeyAssociativePointer(&scope->_variables, variable->_name, (void*) variable, false); - assert(result != NULL); + assert(result == NULL); return true; } diff --git a/arangod/RestServer/arango.cpp b/arangod/RestServer/arango.cpp old mode 100644 new mode 100755 index e494700be5..73702db7ac --- a/arangod/RestServer/arango.cpp +++ b/arangod/RestServer/arango.cpp @@ -89,7 +89,6 @@ int main (int argc, char* argv[]) { // ........................................................................... // TODO: need a terminate function for windows to be called and cleanup // any windows specific stuff. - // TODO: find the memory deallocation/allocation error // ........................................................................... res = finaliseWindows(TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL, 0); diff --git a/arangosh/ArangoShell/ArangoClient.cpp b/arangosh/ArangoShell/ArangoClient.cpp old mode 100644 new mode 100755 index 0f933a7dc2..2c3b0769d5 --- a/arangosh/ArangoShell/ArangoClient.cpp +++ b/arangosh/ArangoShell/ArangoClient.cpp @@ -490,6 +490,16 @@ void ArangoClient::parse (ProgramOptions& options, /// @brief starts pager //////////////////////////////////////////////////////////////////////////////// +#ifdef _WIN32 + +void ArangoClient::startPager () { + // not supported + if (!_usePager || _usePager) { + return; + } +} + +#else void ArangoClient::startPager () { if (! _usePager || _outputPager == "" || _outputPager == "stdout" || _outputPager == "-") { _pager = stdout; @@ -504,10 +514,21 @@ void ArangoClient::startPager () { _usePager = false; } } +#endif //////////////////////////////////////////////////////////////////////////////// /// @brief stops pager //////////////////////////////////////////////////////////////////////////////// +#ifdef _WIN32 + +void ArangoClient::stopPager () { + // not supported + if (!_usePager || _usePager) { + return; + } +} + +#else void ArangoClient::stopPager () { if (_pager != stdout) { @@ -516,6 +537,8 @@ void ArangoClient::stopPager () { } } +#endif + //////////////////////////////////////////////////////////////////////////////// /// @brief print to pager //////////////////////////////////////////////////////////////////////////////// diff --git a/arangosh/V8Client/ImportHelper.cpp b/arangosh/V8Client/ImportHelper.cpp old mode 100644 new mode 100755 index e5a2a30787..7a66dc6194 --- a/arangosh/V8Client/ImportHelper.cpp +++ b/arangosh/V8Client/ImportHelper.cpp @@ -59,7 +59,7 @@ namespace triagens { /// constructor and destructor //////////////////////////////////////////////////////////////////////////////// - ImportHelper::ImportHelper (httpclient::SimpleHttpClient* _client, size_t maxUploadSize) + ImportHelper::ImportHelper (httpclient::SimpleHttpClient* _client, uint64_t maxUploadSize) : _client(_client), _maxUploadSize(maxUploadSize), _lineBuffer(TRI_UNKNOWN_MEM_ZONE), @@ -107,7 +107,7 @@ namespace triagens { fd = STDIN_FILENO; } else { - fd = open(fileName.c_str(), O_RDONLY); + fd = TRI_OPEN(fileName.c_str(), O_RDONLY); } if (fd < 0) { @@ -155,7 +155,7 @@ namespace triagens { while (! _hasError) { v8::HandleScope scope; - ssize_t n = read(fd, buffer, sizeof(buffer)); + ssize_t n = TRI_READ(fd, buffer, sizeof(buffer)); if (n < 0) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, separator); @@ -180,7 +180,7 @@ namespace triagens { TRI_Free(TRI_UNKNOWN_MEM_ZONE, eol); if (fileName != "-") { - close(fd); + TRI_CLOSE(fd); } _outputBuffer.clear(); @@ -204,7 +204,7 @@ namespace triagens { fd = STDIN_FILENO; } else { - fd = open(fileName.c_str(), O_RDONLY); + fd = TRI_OPEN(fileName.c_str(), O_RDONLY); } if (fd < 0) { @@ -216,7 +216,7 @@ namespace triagens { bool isArray = false; while (! _hasError) { - ssize_t n = read(fd, buffer, sizeof(buffer)); + ssize_t n = TRI_READ(fd, buffer, sizeof(buffer)); if (n < 0) { _errorMessage = TRI_LAST_ERROR_STR; @@ -261,7 +261,7 @@ namespace triagens { _numberLines = _numberError + _numberOk; if (fileName != "-") { - close(fd); + TRI_CLOSE(fd); } _outputBuffer.clear(); diff --git a/arangosh/V8Client/ImportHelper.h b/arangosh/V8Client/ImportHelper.h old mode 100644 new mode 100755 index 19e34b07be..25180b7742 --- a/arangosh/V8Client/ImportHelper.h +++ b/arangosh/V8Client/ImportHelper.h @@ -52,6 +52,10 @@ #include "BasicsC/csv.h" #include "Basics/StringBuffer.h" +#ifdef _WIN32 +#include "BasicsC/win-utils.h" +#endif + namespace triagens { namespace httpclient { class SimpleHttpClient; @@ -87,7 +91,7 @@ namespace triagens { /// @brief constructor //////////////////////////////////////////////////////////////////////////////// - ImportHelper (httpclient::SimpleHttpClient* client, size_t maxUploadSize); + ImportHelper (httpclient::SimpleHttpClient* client, uint64_t maxUploadSize); //////////////////////////////////////////////////////////////////////////////// /// @brief destructor @@ -216,7 +220,7 @@ namespace triagens { private: httpclient::SimpleHttpClient* _client; - size_t _maxUploadSize; + uint64_t _maxUploadSize; string _separator; string _quote; diff --git a/arangosh/V8Client/V8ClientConnection.cpp b/arangosh/V8Client/V8ClientConnection.cpp old mode 100644 new mode 100755 index 0ed5e14ea1..539434c151 --- a/arangosh/V8Client/V8ClientConnection.cpp +++ b/arangosh/V8Client/V8ClientConnection.cpp @@ -81,7 +81,9 @@ V8ClientConnection::V8ClientConnection (Endpoint* endpoint, _client(0), _httpResult(0) { + _connection = GeneralClientConnection::factory(endpoint, requestTimeout, connectTimeout, numRetries); + if (_connection == 0) { throw "out of memory"; } diff --git a/arangosh/V8Client/arangoimp.cpp b/arangosh/V8Client/arangoimp.cpp old mode 100644 new mode 100755 index 56507d756f..cffbfed4cc --- a/arangosh/V8Client/arangoimp.cpp +++ b/arangosh/V8Client/arangoimp.cpp @@ -194,6 +194,33 @@ static void ParseProgramOptions (int argc, char* argv[]) { //////////////////////////////////////////////////////////////////////////////// int main (int argc, char* argv[]) { + + int ret = EXIT_SUCCESS; + +#ifdef _WIN32 + + // ........................................................................... + // Call this function to do various initialistions for windows only + // ........................................................................... + + // ........................................................................... + // Uncomment this to call this for extended debug information. + // If you familiar with valgrind ... then this is not like that, however + // you do get some similar functionality. + // ........................................................................... + //res = initialiseWindows(TRI_WIN_INITIAL_SET_DEBUG_FLAG, 0); + + ret = initialiseWindows(TRI_WIN_INITIAL_SET_INVALID_HANLE_HANDLER, 0); + if (ret != 0) { + _exit(1); + } + ret = initialiseWindows(TRI_WIN_INITIAL_WSASTARTUP_FUNCTION_CALL, 0); + if (ret != 0) { + _exit(1); + } + +#endif + TRIAGENS_C_INITIALISE(argc, argv); TRIAGENS_REST_INITIALISE(argc, argv); @@ -352,7 +379,18 @@ int main (int argc, char* argv[]) { TRIAGENS_REST_SHUTDOWN; - return EXIT_SUCCESS; +#ifdef _WIN32 + + // ........................................................................... + // TODO: need a terminate function for windows to be called and cleanup + // any windows specific stuff. + // ........................................................................... + + ret = finaliseWindows(TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL, 0); + +#endif + + return ret; } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangosh/V8Client/arangosh.cpp b/arangosh/V8Client/arangosh.cpp old mode 100644 new mode 100755 index b7eb852793..91797c7469 --- a/arangosh/V8Client/arangosh.cpp +++ b/arangosh/V8Client/arangosh.cpp @@ -1092,11 +1092,37 @@ static void AddColors (v8::Handle context) { //////////////////////////////////////////////////////////////////////////////// int main (int argc, char* argv[]) { + + int ret = EXIT_SUCCESS; + +#ifdef _WIN32 + + // ........................................................................... + // Call this function to do various initialistions for windows only + // ........................................................................... + + // ........................................................................... + // Uncomment this to call this for extended debug information. + // If you familiar with valgrind ... then this is not like that, however + // you do get some similar functionality. + // ........................................................................... + //res = initialiseWindows(TRI_WIN_INITIAL_SET_DEBUG_FLAG, 0); + + ret = initialiseWindows(TRI_WIN_INITIAL_SET_INVALID_HANLE_HANDLER, 0); + if (ret != 0) { + _exit(1); + } + ret = initialiseWindows(TRI_WIN_INITIAL_WSASTARTUP_FUNCTION_CALL, 0); + if (ret != 0) { + _exit(1); + } + +#endif + TRIAGENS_C_INITIALISE(argc, argv); TRIAGENS_REST_INITIALISE(argc, argv); TRI_InitialiseLogging(false); - int ret = EXIT_SUCCESS; BaseClient.setEndpointString(Endpoint::getDefaultEndpoint()); @@ -1119,6 +1145,7 @@ int main (int argc, char* argv[]) { } if (useServer) { + BaseClient.createEndpoint(); if (BaseClient.endpointServer() == 0) { @@ -1126,6 +1153,7 @@ int main (int argc, char* argv[]) { exit(EXIT_FAILURE); } + ClientConnection = CreateConnection(); } @@ -1232,7 +1260,72 @@ int main (int argc, char* argv[]) { // ............................................................................. // http://www.network-science.de/ascii/ Font: ogre + if (! BaseClient.quiet()) { + + cout << endl; + +#ifdef _WIN32 + + // ............................................................................. + // Quick hack for windows + // ............................................................................. + + + if (BaseClient.colors()) { + + int greenColour = FOREGROUND_GREEN | FOREGROUND_INTENSITY; + int redColour = FOREGROUND_RED | FOREGROUND_INTENSITY; + int defaultColour = 0; + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + bool ok; + + ok = GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbiInfo); + if (ok) { + defaultColour = csbiInfo.wAttributes; + } + + SetConsoleOutputCP(65001); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), greenColour); + printf(" "); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), redColour); + printf(" _ "); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColour); + printf("\n"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), greenColour); + printf(" __ _ _ __ __ _ _ __ __ _ ___ "); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), redColour); + printf(" ___| |__ "); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColour); + printf("\n"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), greenColour); + printf(" / _` | '__/ _` | '_ \\ / _` |/ _ \\"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), redColour); + printf("/ __| '_ \\ "); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColour); + printf("\n"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), greenColour); + printf("| (_| | | | (_| | | | | (_| | (_) "); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), redColour); + printf("\\__ \\ | | |"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColour); + printf("\n"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), greenColour); + printf(" \\__,_|_| \\__,_|_| |_|\\__, |\\___/"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), redColour); + printf("|___/_| |_|"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColour); + printf("\n"); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), greenColour); + printf(" |___/ "); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), redColour); + printf(" "); + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColour); + printf("\n"); + + } + +#else char const* g = ArangoClient::COLOR_GREEN; char const* r = ArangoClient::COLOR_RED; char const* z = ArangoClient::COLOR_RESET; @@ -1251,6 +1344,7 @@ int main (int argc, char* argv[]) { printf("%s| (_| | | | (_| | | | | (_| | (_) %s\\__ \\ | | |%s\n", g, r, z); printf("%s \\__,_|_| \\__,_|_| |_|\\__, |\\___/%s|___/_| |_|%s\n", g, r, z); printf("%s |___/ %s %s\n", g, r, z); +#endif cout << endl << "Welcome to arangosh " << TRIAGENS_VERSION << ". Copyright (c) 2012 triAGENS GmbH" << endl; @@ -1334,6 +1428,7 @@ int main (int argc, char* argv[]) { BaseClient.openLog(); + // ............................................................................. // run normal shell // ............................................................................. @@ -1385,6 +1480,17 @@ int main (int argc, char* argv[]) { TRIAGENS_REST_SHUTDOWN; +#ifdef _WIN32 + + // ........................................................................... + // TODO: need a terminate function for windows to be called and cleanup + // any windows specific stuff. + // ........................................................................... + + ret = finaliseWindows(TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL, 0); + +#endif + return ret; } diff --git a/lib/BasicsC/files.c b/lib/BasicsC/files.c index 48189b2ef6..8f29d42915 100755 --- a/lib/BasicsC/files.c +++ b/lib/BasicsC/files.c @@ -102,7 +102,7 @@ static TRI_read_write_lock_t FileNamesLock; static ssize_t LookupElementVectorString (TRI_vector_string_t * vector, char const * element) { int idx = -1; - size_t i; + int i; TRI_ReadLockReadWriteLock(&FileNamesLock); @@ -270,6 +270,12 @@ bool TRI_IsDirectory (char const* path) { /// @brief checks if path is a symbolic link //////////////////////////////////////////////////////////////////////////////// +#ifdef _WIN32 +bool TRI_IsSymbolicLink (char const* path) { + // todo : check if a file is a symbolic link - without opening the file + return false; +} +#else bool TRI_IsSymbolicLink (char const* path) { struct stat stbuf; int res; @@ -278,6 +284,7 @@ bool TRI_IsSymbolicLink (char const* path) { return (res == 0) && ((stbuf.st_mode & S_IFMT) == S_IFLNK); } +#endif //////////////////////////////////////////////////////////////////////////////// /// @brief checks if file exists diff --git a/lib/BasicsC/messages.h b/lib/BasicsC/messages.h old mode 100644 new mode 100755 diff --git a/lib/BasicsC/operating-system.h b/lib/BasicsC/operating-system.h old mode 100644 new mode 100755 index 8114e23e9d..c4eabe49c0 --- a/lib/BasicsC/operating-system.h +++ b/lib/BasicsC/operating-system.h @@ -529,6 +529,10 @@ typedef unsigned char bool; typedef SOCKET socket_t; +#define STDIN_FILENO 0; +#define STDOUT_FILENO 1; +#define STDERR_FILENO 2; + #endif //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/BasicsC/win-utils.c b/lib/BasicsC/win-utils.c index 42eb30d520..f881c657b2 100755 --- a/lib/BasicsC/win-utils.c +++ b/lib/BasicsC/win-utils.c @@ -259,8 +259,6 @@ int initialiseWindows(const TRI_win_initialise_e initialiseWhat, const char* dat return -1; - - } diff --git a/lib/BasicsC/win-utils.h b/lib/BasicsC/win-utils.h old mode 100644 new mode 100755 index 88c07edce8..d7010ae185 --- a/lib/BasicsC/win-utils.h +++ b/lib/BasicsC/win-utils.h @@ -1,133 +1,132 @@ -//////////////////////////////////////////////////////////////////////////////// -/// @brief windows utilties -/// -/// @file -/// -/// DISCLAIMER -/// -/// Copyright 2004-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 Dr. O -/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany -//////////////////////////////////////////////////////////////////////////////// - -#ifndef TRIAGENS_BASICS_C_WIN_UTILS_H -#define TRIAGENS_BASICS_C_WIN_UTILS_H 1 - +//////////////////////////////////////////////////////////////////////////////// +/// @brief windows utilties +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2004-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 Dr. O +/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef TRIAGENS_BASICS_C_WIN_UTILS_H +#define TRIAGENS_BASICS_C_WIN_UTILS_H 1 + #include - -/* Constants rounded for 21 decimals. -#define M_E 2.71828182845904523536 -#define M_LOG2E 1.44269504088896340736 -#define M_LOG10E 0.434294481903251827651 -#define M_LN2 0.693147180559945309417 -#define M_LN10 2.30258509299404568402 -#define M_PI 3.14159265358979323846 -#define M_PI_2 1.57079632679489661923 -#define M_PI_4 0.785398163397448309616 -#define M_1_PI 0.318309886183790671538 -#define M_2_PI 0.636619772367581343076 -#define M_1_SQRTPI 0.564189583547756286948 -#define M_2_SQRTPI 1.12837916709551257390 -#define M_SQRT2 1.41421356237309504880 -#define M_SQRT_2 0.707106781186547524401 -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup Windows_Utilties -/// @{ -//////////////////////////////////////////////////////////////////////////////// - -// ............................................................................. -// Called before anything else starts - initialises whatever is required to be -// initalised. -// ............................................................................. -typedef enum { - TRI_WIN_FINAL_SET_INVALID_HANLE_HANDLER, - TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL -} -TRI_win_finalise_e; - -typedef enum { - TRI_WIN_INITIAL_SET_DEBUG_FLAG, - TRI_WIN_INITIAL_SET_INVALID_HANLE_HANDLER, - TRI_WIN_INITIAL_WSASTARTUP_FUNCTION_CALL -} -TRI_win_initialise_e; - -int finaliseWindows (const TRI_win_finalise_e, const char*); -int initialiseWindows (const TRI_win_initialise_e, const char*); - -// ............................................................................. -// windows equivalent of ftruncate (the truncation of an open file) is -// _chsize -// ............................................................................. - -int ftruncate (int, long); - - -// ............................................................................. -// windows does not have a function called getpagesize -- create one here -// ............................................................................. - -int getpagesize (void); - - - + +/* Constants rounded for 21 decimals. +#define M_E 2.71828182845904523536 +#define M_LOG2E 1.44269504088896340736 +#define M_LOG10E 0.434294481903251827651 +#define M_LN2 0.693147180559945309417 +#define M_LN10 2.30258509299404568402 +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 +#define M_PI_4 0.785398163397448309616 +#define M_1_PI 0.318309886183790671538 +#define M_2_PI 0.636619772367581343076 +#define M_1_SQRTPI 0.564189583547756286948 +#define M_2_SQRTPI 1.12837916709551257390 +#define M_SQRT2 1.41421356237309504880 +#define M_SQRT_2 0.707106781186547524401 +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////////////// +/// @addtogroup Windows_Utilties +/// @{ +//////////////////////////////////////////////////////////////////////////////// + +// ............................................................................. +// Called before anything else starts - initialises whatever is required to be +// initalised. +// ............................................................................. +typedef enum { + TRI_WIN_FINAL_SET_INVALID_HANLE_HANDLER, + TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL +} +TRI_win_finalise_e; + +typedef enum { + TRI_WIN_INITIAL_SET_DEBUG_FLAG, + TRI_WIN_INITIAL_SET_INVALID_HANLE_HANDLER, + TRI_WIN_INITIAL_WSASTARTUP_FUNCTION_CALL +} +TRI_win_initialise_e; + +int finaliseWindows (const TRI_win_finalise_e, const char*); +int initialiseWindows (const TRI_win_initialise_e, const char*); + +// ............................................................................. +// windows equivalent of ftruncate (the truncation of an open file) is +// _chsize +// ............................................................................. + +int ftruncate (int, long); + + +// ............................................................................. +// windows does not have a function called getpagesize -- create one here +// ............................................................................. + +int getpagesize (void); + + int TRI_WIN_closesocket (SOCKET); - -// ............................................................................. -// This function uses the CreateFile windows method rather than _open which -// then will allow the application to rename files on the fly. -// ............................................................................. - -int TRI_createFile (const char* filename, int openFlags, int modeFlags); - -int TRI_openFile (const char* filename, int openFlags); - -// ............................................................................. -// the sleep function in windows is for milliseconds, on linux it is for seconds -// this provides a translation -// ............................................................................. - -void TRI_sleep(unsigned long); - - -// ............................................................................. -// there is no usleep (micro sleep) in windows, so we create one here -// ............................................................................. - -void TRI_usleep(unsigned long); - -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -} -#endif - -#endif - -// Local Variables: -// mode: outline-minor -// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" -// End: + +// ............................................................................. +// This function uses the CreateFile windows method rather than _open which +// then will allow the application to rename files on the fly. +// ............................................................................. + +int TRI_createFile (const char* filename, int openFlags, int modeFlags); + +int TRI_openFile (const char* filename, int openFlags); + +// ............................................................................. +// the sleep function in windows is for milliseconds, on linux it is for seconds +// this provides a translation +// ............................................................................. + +void TRI_sleep(unsigned long); + + +// ............................................................................. +// there is no usleep (micro sleep) in windows, so we create one here +// ............................................................................. + +void TRI_usleep(unsigned long); + +//////////////////////////////////////////////////////////////////////////////// +/// @} +//////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)" +// End: diff --git a/lib/Rest/EndpointIp.cpp b/lib/Rest/EndpointIp.cpp index 51d577aea4..1f91a9c49c 100755 --- a/lib/Rest/EndpointIp.cpp +++ b/lib/Rest/EndpointIp.cpp @@ -210,6 +210,75 @@ socket_t EndpointIp::connectSocket (const struct addrinfo* aip, double connectTi /// @brief connect the endpoint //////////////////////////////////////////////////////////////////////////////// +#ifdef _WIN32 + +socket_t EndpointIp::connect (double connectTimeout, double requestTimeout) { + struct addrinfo* result = 0; + struct addrinfo* aip; + struct addrinfo hints; + int error; + + LOGGER_DEBUG << "connecting to ip endpoint " << _specification; + + assert(_socket == 0); + assert(!_connected); + + memset(&hints, 0, sizeof (struct addrinfo)); + hints.ai_family = getDomain(); // Allow IPv4 or IPv6 + hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV | AI_ALL; + hints.ai_socktype = SOCK_STREAM; + + string portString = StringUtils::itoa(_port); + + error = getaddrinfo(_host.c_str(), portString.c_str(), &hints, &result); + + if (error != 0) { + int lastError = WSAGetLastError(); + + if (error == WSANOTINITIALISED) { + // can not call WSAGetLastError - since the socket layer hasn't been initialised yet! + lastError = error; + } + else { + lastError = WSAGetLastError(); + } + + switch (lastError) { + case WSANOTINITIALISED: { + LOGGER_ERROR << "getaddrinfo for host: " << _host.c_str() << " => WSAStartup was not called or not called successfully."; + break; + } + default: { + LOGGER_ERROR << "getaddrinfo for host: " << _host.c_str() << " => " << gai_strerror(error); + break; + } + } + + if (result != 0) { + freeaddrinfo(result); + } + + return 0; + } + + socket_t listenSocket = 0; + + // Try all returned addresses until one works + for (aip = result; aip != NULL; aip = aip->ai_next) { + // try to bind the address info pointer + listenSocket = connectSocket(aip, connectTimeout, requestTimeout); + if (listenSocket != 0) { + // OK + break; + } + } + + freeaddrinfo(result); + + return listenSocket; +} + +#else socket_t EndpointIp::connect (double connectTimeout, double requestTimeout) { struct addrinfo* result = 0; struct addrinfo* aip; @@ -256,6 +325,7 @@ socket_t EndpointIp::connect (double connectTimeout, double requestTimeout) { return listenSocket; } +#endif //////////////////////////////////////////////////////////////////////////////// /// @brief destroys an IPv4 socket endpoint diff --git a/lib/SimpleHttpClient/ClientConnection.cpp b/lib/SimpleHttpClient/ClientConnection.cpp old mode 100644 new mode 100755 index e8134da7b0..a312b74aef --- a/lib/SimpleHttpClient/ClientConnection.cpp +++ b/lib/SimpleHttpClient/ClientConnection.cpp @@ -186,7 +186,7 @@ bool ClientConnection::prepare (const double timeout, const bool isWrite) const /// @brief write data to the connection //////////////////////////////////////////////////////////////////////////////// -bool ClientConnection::write (void* buffer, size_t length, size_t* bytesWritten) { +bool ClientConnection::writeClientConnection (void* buffer, size_t length, size_t* bytesWritten) { if (!checkSocket()) { return false; } @@ -196,7 +196,7 @@ bool ClientConnection::write (void* buffer, size_t length, size_t* bytesWritten) int status = ::send(_socket, buffer, length, 0); #elif defined(_WIN32) // MSG_NOSIGNAL not supported on windows platform - int status = ::send(_socket, (const char*)(buffer), (int)(length), 0); + int status = TRI_WRITE_SOCKET(_socket, (const char*)(buffer), (int)(length), 0); #else int status = ::send(_socket, buffer, length, MSG_NOSIGNAL); #endif @@ -211,7 +211,7 @@ bool ClientConnection::write (void* buffer, size_t length, size_t* bytesWritten) /// @brief read data from the connection //////////////////////////////////////////////////////////////////////////////// -bool ClientConnection::read (StringBuffer& stringBuffer) { +bool ClientConnection::readClientConnection (StringBuffer& stringBuffer) { if (!checkSocket()) { return false; } @@ -221,7 +221,7 @@ bool ClientConnection::read (StringBuffer& stringBuffer) { do { char buffer[READBUFFER_SIZE]; - int lenRead = ::read(_socket, buffer, READBUFFER_SIZE - 1); + int lenRead = TRI_READ_SOCKET(_socket, buffer, READBUFFER_SIZE - 1,0); if (lenRead <= 0) { // error: stop reading diff --git a/lib/SimpleHttpClient/ClientConnection.h b/lib/SimpleHttpClient/ClientConnection.h old mode 100644 new mode 100755 index 9b3646a38f..87e7103e0a --- a/lib/SimpleHttpClient/ClientConnection.h +++ b/lib/SimpleHttpClient/ClientConnection.h @@ -130,13 +130,13 @@ namespace triagens { /// @brief write data to the connection //////////////////////////////////////////////////////////////////////////////// - bool write (void*, size_t, size_t*); + bool writeClientConnection (void*, size_t, size_t*); //////////////////////////////////////////////////////////////////////////////// /// @brief read data from the connection //////////////////////////////////////////////////////////////////////////////// - bool read (triagens::basics::StringBuffer&); + bool readClientConnection (triagens::basics::StringBuffer&); //////////////////////////////////////////////////////////////////////////////// /// @brief return whether the connection is readable diff --git a/lib/SimpleHttpClient/GeneralClientConnection.cpp b/lib/SimpleHttpClient/GeneralClientConnection.cpp old mode 100644 new mode 100755 index 0d4a5db0c1..36a661a18d --- a/lib/SimpleHttpClient/GeneralClientConnection.cpp +++ b/lib/SimpleHttpClient/GeneralClientConnection.cpp @@ -142,7 +142,7 @@ bool GeneralClientConnection::handleWrite (const double timeout, void* buffer, s *bytesWritten = 0; if (prepare(timeout, true)) { - return write(buffer, length, bytesWritten); + return writeClientConnection(buffer, length, bytesWritten); } return false; @@ -154,7 +154,7 @@ bool GeneralClientConnection::handleWrite (const double timeout, void* buffer, s bool GeneralClientConnection::handleRead (double timeout, StringBuffer& buffer) { if (prepare(timeout, false)) { - return read(buffer); + return readClientConnection(buffer); } return false; diff --git a/lib/SimpleHttpClient/GeneralClientConnection.h b/lib/SimpleHttpClient/GeneralClientConnection.h old mode 100644 new mode 100755 index 96bc245bc1..1c62bd3036 --- a/lib/SimpleHttpClient/GeneralClientConnection.h +++ b/lib/SimpleHttpClient/GeneralClientConnection.h @@ -212,13 +212,13 @@ namespace triagens { /// @brief write data to the connection //////////////////////////////////////////////////////////////////////////////// - virtual bool write (void*, size_t, size_t*) = 0; + virtual bool writeClientConnection (void*, size_t, size_t*) = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief read data from the connection //////////////////////////////////////////////////////////////////////////////// - virtual bool read (triagens::basics::StringBuffer&) = 0; + virtual bool readClientConnection (triagens::basics::StringBuffer&) = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief return whether the connection is readable diff --git a/lib/SimpleHttpClient/SslClientConnection.cpp b/lib/SimpleHttpClient/SslClientConnection.cpp old mode 100644 new mode 100755 index 9c8f628cc6..85d2e13ebe --- a/lib/SimpleHttpClient/SslClientConnection.cpp +++ b/lib/SimpleHttpClient/SslClientConnection.cpp @@ -200,7 +200,7 @@ bool SslClientConnection::prepare (const double timeout, const bool isWrite) con /// @brief write data to the connection //////////////////////////////////////////////////////////////////////////////// -bool SslClientConnection::write (void* buffer, size_t length, size_t* bytesWritten) { +bool SslClientConnection::writeClientConnection (void* buffer, size_t length, size_t* bytesWritten) { *bytesWritten = 0; if (_ssl == 0) { @@ -234,7 +234,7 @@ bool SslClientConnection::write (void* buffer, size_t length, size_t* bytesWritt /// @brief read data from the connection //////////////////////////////////////////////////////////////////////////////// -bool SslClientConnection::read (StringBuffer& stringBuffer) { +bool SslClientConnection::readClientConnection (StringBuffer& stringBuffer) { if (_ssl == 0) { return false; } diff --git a/lib/SimpleHttpClient/SslClientConnection.h b/lib/SimpleHttpClient/SslClientConnection.h old mode 100644 new mode 100755 index 30bc8b3522..d72f93a687 --- a/lib/SimpleHttpClient/SslClientConnection.h +++ b/lib/SimpleHttpClient/SslClientConnection.h @@ -115,13 +115,13 @@ namespace triagens { /// @brief write data to the connection //////////////////////////////////////////////////////////////////////////////// - bool write (void*, size_t, size_t*); + bool writeClientConnection (void*, size_t, size_t*); //////////////////////////////////////////////////////////////////////////////// /// @brief read data from the connection //////////////////////////////////////////////////////////////////////////////// - bool read (triagens::basics::StringBuffer&); + bool readClientConnection (triagens::basics::StringBuffer&); //////////////////////////////////////////////////////////////////////////////// /// @brief return whether the connection is readable From 3fbf03074134a5b07fabd0d3e4977d689fe20123 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 15 Jan 2013 09:17:19 +0100 Subject: [PATCH 04/12] fixed Doxygen error --- Documentation/UserManual/FirstStepsArangoDB.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/UserManual/FirstStepsArangoDB.md b/Documentation/UserManual/FirstStepsArangoDB.md index f30adbe721..70018fb413 100644 --- a/Documentation/UserManual/FirstStepsArangoDB.md +++ b/Documentation/UserManual/FirstStepsArangoDB.md @@ -364,7 +364,7 @@ While the `byExample` works very well for simple queries where you and `or` conditions. Therefore, ArangoDB also supports a full-blown query language. - arangosh> db._query('FOR user IN example FILTER user.name == "Musterfrau" return user').toArray() + arangosh> db._query('FOR user IN example FILTER user.name == "Musterfrau" RETURN user').toArray() [ { _id : "4538791/6308263", @@ -376,7 +376,7 @@ query language. Search for all persons over 30. - arangosh> db._query('FOR user IN example FILTER user.age > 30" return user').toArray() + arangosh> db._query('FOR user IN example FILTER user.age > 30 RETURN user').toArray() [ { _id : "4538791/6308263", From 6686a075ca3336665992e1b5ed3cf0b0e75d819a Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 15 Jan 2013 14:46:18 +0100 Subject: [PATCH 05/12] pretty printing fix --- js/common/bootstrap/module-internal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/common/bootstrap/module-internal.js b/js/common/bootstrap/module-internal.js index 1689359085..80050dff1b 100644 --- a/js/common/bootstrap/module-internal.js +++ b/js/common/bootstrap/module-internal.js @@ -405,7 +405,7 @@ } else { var i; - var sep = ""; + var sep = " "; internal.output(internal.colors.COLOR_PUNCTUATION); internal.output("["); From c1ec3c49ed2a9b99138da4ce6d19d7f2bff06922 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 15 Jan 2013 14:53:06 +0100 Subject: [PATCH 06/12] shut up prettifiers on demand --- js/common/bootstrap/module-internal.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/js/common/bootstrap/module-internal.js b/js/common/bootstrap/module-internal.js index 80050dff1b..884f35d5cd 100644 --- a/js/common/bootstrap/module-internal.js +++ b/js/common/bootstrap/module-internal.js @@ -571,42 +571,42 @@ /// @brief start pretty printing //////////////////////////////////////////////////////////////////////////////// - internal.startPrettyPrint = function () { - if (! internal.PRETTY_PRINT) { - internal.PRETTY_PRINT = true; + internal.startPrettyPrint = function (silent) { + if (! internal.PRETTY_PRINT && ! silent) { internal.print("using pretty printing"); } + internal.PRETTY_PRINT = true; }; //////////////////////////////////////////////////////////////////////////////// /// @brief stop pretty printing //////////////////////////////////////////////////////////////////////////////// - internal.stopPrettyPrint = function () { - if (internal.PRETTY_PRINT) { - internal.PRETTY_PRINT = false; + internal.stopPrettyPrint = function (silent) { + if (internal.PRETTY_PRINT && ! silent) { internal.print("disabled pretty printing"); } + internal.PRETTY_PRINT = false; }; //////////////////////////////////////////////////////////////////////////////// /// @brief start color printing //////////////////////////////////////////////////////////////////////////////// - internal.startColorPrint = function () { - internal.colors = internal.COLORS; - if (! internal.COLOR_OUTPUT) { - internal.COLOR_OUTPUT = true; + internal.startColorPrint = function (silent) { + if (! internal.COLOR_OUTPUT && ! silent) { internal.print("starting color printing"); } + internal.colors = internal.COLORS; + internal.COLOR_OUTPUT = true; }; //////////////////////////////////////////////////////////////////////////////// /// @brief stop color printing //////////////////////////////////////////////////////////////////////////////// - internal.stopColorPrint = function () { - if (internal.COLOR_OUTPUT) { + internal.stopColorPrint = function (silent) { + if (internal.COLOR_OUTPUT && ! silent) { internal.print("disabled color printing"); } internal.COLOR_OUTPUT = false; From 40318ad926eaea909bbcf1e356e4e0bbfc46fca1 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 15 Jan 2013 15:00:17 +0100 Subject: [PATCH 07/12] pretty dumper --- js/common/bootstrap/module-internal.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/js/common/bootstrap/module-internal.js b/js/common/bootstrap/module-internal.js index 884f35d5cd..7e6d644bbd 100644 --- a/js/common/bootstrap/module-internal.js +++ b/js/common/bootstrap/module-internal.js @@ -613,6 +613,29 @@ internal.colors = internal.NOCOLORS; }; +//////////////////////////////////////////////////////////////////////////////// +/// @brief debug print function +//////////////////////////////////////////////////////////////////////////////// + + internal.dump = function () { + var oldPretty = internal.PRETTY_PRINT; + var oldColor = internal.COLOR_OUTPUT; + + internal.startPrettyPrint(true); + internal.startColorPrint(true); + + for (var i = 0; i < arguments.length; ++i) { + internal.print(arguments[i]); + } + + if (! oldPretty) { + internal.stopPrettyPrint(true); + } + if (! oldColor) { + internal.stopColorPrint(true); + } + }; + //////////////////////////////////////////////////////////////////////////////// /// @brief encode password using SHA256 //////////////////////////////////////////////////////////////////////////////// From bedc46f6468aafba65ab39780436d730ac6f7ecf Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 15 Jan 2013 15:09:31 +0100 Subject: [PATCH 08/12] issue #355 --- Documentation/latex/header.tex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/latex/header.tex b/Documentation/latex/header.tex index d34e13a837..24d2585ba9 100644 --- a/Documentation/latex/header.tex +++ b/Documentation/latex/header.tex @@ -17,6 +17,8 @@ \usepackage{doxygen} \usepackage{listings} \usepackage{ifthen} +\usepackage{alltt} +\usepackage{upquote} \lstset{language=C++,inputencoding=utf8,basicstyle=\footnotesize,breaklines=true,breakatwhitespace=true,tabsize=8,numbers=left } \makeindex \setcounter{tocdepth}{3} From 4712e1637e7fe2e7140dc2736cd8fb20c7c59e43 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 15 Jan 2013 15:11:16 +0100 Subject: [PATCH 09/12] optionally do not check element equality when inserting into the associative multi index this might speed up insertion a lot if we know that the same element cannot be in the index already --- lib/BasicsC/associative-multi.c | 14 +++++++++++--- lib/BasicsC/associative-multi.h | 5 ++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/BasicsC/associative-multi.c b/lib/BasicsC/associative-multi.c index a93d3aadb5..c74d1e8746 100644 --- a/lib/BasicsC/associative-multi.c +++ b/lib/BasicsC/associative-multi.c @@ -46,7 +46,7 @@ /// @brief initial number of elements of a container //////////////////////////////////////////////////////////////////////////////// -#define INITIAL_SIZE (10) +#define INITIAL_SIZE (64) //////////////////////////////////////////////////////////////////////////////// /// @} @@ -772,7 +772,10 @@ void* TRI_LookupByElementMultiPointer (TRI_multi_pointer_t* array, void const* e /// @brief adds an key/element to the array //////////////////////////////////////////////////////////////////////////////// -void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t* array, void* element, bool overwrite) { +void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t* array, + void* element, + const bool overwrite, + const bool checkEquality) { uint64_t hash; uint64_t i; void* old; @@ -792,7 +795,12 @@ void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t* array, void* element, #endif // search the table - while (array->_table[i] != NULL && ! array->isEqualElementElement(array, element, array->_table[i])) { + + // if the checkEquality flag is not set, we do not check for element equality + // we use this flag to speed up initial insertion into the index, i.e. when the + // index is built for a collection and we know for sure no duplicate elements + // will be inserted + while (array->_table[i] != NULL && (checkEquality && ! array->isEqualElementElement(array, element, array->_table[i]))) { i = (i + 1) % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS array->_nrProbesA++; diff --git a/lib/BasicsC/associative-multi.h b/lib/BasicsC/associative-multi.h index d9ef0ae7c7..502a14edc9 100644 --- a/lib/BasicsC/associative-multi.h +++ b/lib/BasicsC/associative-multi.h @@ -297,7 +297,10 @@ void* TRI_LookupByElementMultiPointer (TRI_multi_pointer_t*, void const* element /// @brief adds an key/element to the array //////////////////////////////////////////////////////////////////////////////// -void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t*, void* element, bool overwrite); +void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t*, + void*, + const bool, + const bool); //////////////////////////////////////////////////////////////////////////////// /// @brief removes an element from the array From 2e5f65a2ad16d2a75935abfec73db56802eaef86 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 15 Jan 2013 15:13:34 +0100 Subject: [PATCH 10/12] speed up insertion into edges index --- arangod/VocBase/index.c | 54 ++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 31 deletions(-) diff --git a/arangod/VocBase/index.c b/arangod/VocBase/index.c index e2a98334b0..dd50c081c6 100644 --- a/arangod/VocBase/index.c +++ b/arangod/VocBase/index.c @@ -542,6 +542,7 @@ static bool IsEqualElementEdge (TRI_multi_pointer_t* array, //////////////////////////////////////////////////////////////////////////////// static int InsertEdge (TRI_index_t* idx, TRI_doc_mptr_t const* doc) { + TRI_edge_header_t* entries; TRI_edge_header_t* entryIn; TRI_edge_header_t* entryOut; TRI_doc_edge_key_marker_t const* edge; @@ -557,40 +558,33 @@ static int InsertEdge (TRI_index_t* idx, TRI_doc_mptr_t const* doc) { // allocate all edge headers and return early if memory allocation fails - // IN - entryIn = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_edge_header_t), false); - if (entryIn == NULL) { - return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); - } - - // OUT - entryOut = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_edge_header_t), false); - if (entryOut == NULL) { - TRI_Free(TRI_UNKNOWN_MEM_ZONE, entryIn); - + // use one allocation with 2 slots + // the IN entry will be in the first slot, and we only need to free this one later + // using one allocation with 2 slots saves a lot of mallocs, and speeds up the + // index insertion for a large edge collection + entries = TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, 2 * sizeof(TRI_edge_header_t), false); + if (entries == NULL) { return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); } // we have allocated all necessary memory by here - // IN - assert(entryIn); + // first slot: IN + entryIn = entries; entryIn->_mptr = doc; entryIn->_flags = TRI_FlagsEdge(TRI_EDGE_IN, isReflexive, isBidirectional); entryIn->_cid = edge->_toCid; entryIn->_key = ((char*) edge) + edge->_offsetToKey; - - TRI_InsertElementMultiPointer(edgesIndex, entryIn, true); + TRI_InsertElementMultiPointer(edgesIndex, entryIn, true, true); - // OUT - assert(entryOut); + // second slot: OUT + entryOut = entries + 1; entryOut->_mptr = doc; entryOut->_flags = TRI_FlagsEdge(TRI_EDGE_OUT, isReflexive, isBidirectional); entryOut->_cid = edge->_fromCid; entryOut->_key = ((char*) edge) + edge->_offsetFromKey; + TRI_InsertElementMultiPointer(edgesIndex, entryOut, true, true); - TRI_InsertElementMultiPointer(edgesIndex, entryOut, true); - return TRI_ERROR_NO_ERROR; } @@ -616,22 +610,20 @@ static int RemoveEdge (TRI_index_t* idx, TRI_doc_mptr_t const* doc) { entry._mptr = doc; + // OUT + // we do not need to free the OUT element + entry._flags = TRI_LookupFlagsEdge(TRI_EDGE_OUT); + entry._cid = edge->_fromCid; + entry._key = ((char*) edge) + edge->_offsetFromKey; + TRI_RemoveElementMultiPointer(edgesIndex, &entry); + // IN entry._flags = TRI_LookupFlagsEdge(TRI_EDGE_IN); entry._cid = edge->_toCid; entry._key = ((char*) edge) + edge->_offsetToKey; old = TRI_RemoveElementMultiPointer(edgesIndex, &entry); - if (old != NULL) { - TRI_Free(TRI_UNKNOWN_MEM_ZONE, old); - } - - // OUT - entry._flags = TRI_LookupFlagsEdge(TRI_EDGE_OUT); - entry._cid = edge->_fromCid; - entry._key = ((char*) edge) + edge->_offsetFromKey; - old = TRI_RemoveElementMultiPointer(edgesIndex, &entry); - + // the pointer to the IN element is also the memory pointer we need to free if (old != NULL) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, old); } @@ -731,8 +723,8 @@ void TRI_DestroyEdgeIndex (TRI_index_t* idx) { n = edgesIndex->_edges._nrAlloc; for (i = 0; i < n; ++i) { - void* element = edgesIndex->_edges._table[i]; - if (element) { + TRI_edge_header_t* element = edgesIndex->_edges._table[i]; + if (element != NULL && (element->_flags & TRI_EDGE_BIT_DIRECTION_IN) != 0) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, element); } } From 3d59723f99b25fa29c29cebeb0b406b7852a383c Mon Sep 17 00:00:00 2001 From: Lucas Dohmen Date: Tue, 15 Jan 2013 15:45:47 +0100 Subject: [PATCH 11/12] Tiny additions to Frank * Missing templates will result in an error * The middleware calls next * All JSLint warnings except one fixed --- js/common/modules/org/arangodb/frank.js | 46 +++++++++++++++---------- js/common/tests/shell-frank.js | 33 ++++++++++++++++-- 2 files changed, 59 insertions(+), 20 deletions(-) diff --git a/js/common/modules/org/arangodb/frank.js b/js/common/modules/org/arangodb/frank.js index dbd776d351..292e654e56 100644 --- a/js/common/modules/org/arangodb/frank.js +++ b/js/common/modules/org/arangodb/frank.js @@ -1,12 +1,15 @@ +/*jslint indent: 2, nomen: true, maxlen: 100, sloppy: true, plusplus: true */ +/*global _, require, db, exports */ + var Frank, - baseMiddleware, + BaseMiddleware, _ = require("underscore"), internal = {}; internal.createUrlObject = function (url, constraint, method) { var urlObject = {}; - if(!_.isString(url)) { + if (!_.isString(url)) { throw "URL has to be a String"; } @@ -37,28 +40,29 @@ Frank = function (options) { } if (_.isString(templateCollection)) { - this.routingInfo.templateCollection = db._collection(templateCollection) || db._create(templateCollection); + this.routingInfo.templateCollection = db._collection(templateCollection) || + db._create(templateCollection); } }; _.extend(Frank.prototype, { handleRequest: function (method, route, argument1, argument2) { - var newRoute = {}, options, handler; + var newRoute = {}, options, handler; - if (_.isUndefined(argument2)) { - handler = argument1; - options = {}; - } else { - options = argument1; - handler = argument2; - } + if (_.isUndefined(argument2)) { + handler = argument1; + options = {}; + } else { + options = argument1; + handler = argument2; + } - newRoute.url = internal.createUrlObject(route, options.constraint, method); - newRoute.handler = handler; + newRoute.url = internal.createUrlObject(route, options.constraint, method); + newRoute.handler = handler; - this.routingInfo.routes.push(newRoute); + this.routingInfo.routes.push(newRoute); }, - + head: function (route, argument1, argument2) { this.handleRequest("head", route, argument1, argument2); }, @@ -74,14 +78,14 @@ _.extend(Frank.prototype, { put: function (route, argument1, argument2) { this.handleRequest("put", route, argument1, argument2); }, - + patch: function (route, argument1, argument2) { this.handleRequest("patch", route, argument1, argument2); }, delete: function (route, argument1, argument2) { this.handleRequest("delete", route, argument1, argument2); - }, + } }); @@ -125,7 +129,11 @@ BaseMiddleware = function (templateCollection) { throw "No template collection has been provided when creating a new Frank"; } - template = templateCollection.firstExample({path: "simple/path"}); + template = templateCollection.firstExample({path: templatePath }); + + if (_.isNull(template)) { + throw "Template '" + templatePath + "' does not exist"; + } if (template.templateLanguage !== "underscore") { throw "Unknown template language '" + template.templateLanguage + "'"; @@ -137,6 +145,8 @@ BaseMiddleware = function (templateCollection) { }; response = _.extend(response, responseFunctions); + + next(); }; return middleware; diff --git a/js/common/tests/shell-frank.js b/js/common/tests/shell-frank.js index c654219196..0ca85cc9ec 100644 --- a/js/common/tests/shell-frank.js +++ b/js/common/tests/shell-frank.js @@ -77,7 +77,7 @@ function SetRoutesFrankSpec () { assertEqual(routes.length, 1); assertEqual(routes[0].url.constraint, constraint); }, - + testSetMethodToHead: function () { var myFunc = function () {}, routes = app.routingInfo.routes; @@ -243,6 +243,18 @@ function BaseMiddlewareWithoutTemplateSpec () { } assertEqual(error, "No template collection has been provided when creating a new Frank"); + }, + + testMiddlewareCallsTheAction: function () { + var actionWasCalled = false; + + next = function () { + actionWasCalled = true; + }; + + baseMiddleware(request, response, options, next); + + assertTrue(actionWasCalled); } }; } @@ -303,11 +315,28 @@ function BaseMiddlewareWithTemplateSpec () { } assertEqual(error, "Unknown template language 'pirateEngine'"); + }, + + testRenderingATemplateWithAnNotExistingTemplate: function () { + var myCollection, error, middleware; + + internal.db._drop("templateTest"); + myCollection = internal.db._create("templateTest"); + + middleware = new BaseMiddleware(myCollection); + middleware(request, response, options, next); + + try { + response.render("simple/path", { username: "moonglum" }); + } catch(e) { + error = e; + } + + assertEqual(error, "Template 'simple/path' does not exist"); } }; } - jsunity.run(CreateFrankSpec); jsunity.run(SetRoutesFrankSpec); jsunity.run(BaseMiddlewareWithoutTemplateSpec); From 7a6db162412ae778f3c564ffb24390cad6c311d6 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Tue, 15 Jan 2013 16:44:48 +0100 Subject: [PATCH 12/12] added db._version() --- .../HttpInterface/api-collection-spec.rb | 55 ++++++++++++++- UnitTests/Makefile.unittests | 1 + arangod/V8Server/v8-vocbase.cpp | 16 ++++- arangod/VocBase/index.c | 5 +- js/actions/system/api-collection.js | 26 +++++-- js/client/client.js | 22 +++++- js/common/tests/shell-database.js | 69 +++++++++++++++++++ js/server/version-check.js | 6 +- lib/BasicsC/associative-multi.c | 2 +- 9 files changed, 187 insertions(+), 15 deletions(-) create mode 100644 js/common/tests/shell-database.js diff --git a/UnitTests/HttpInterface/api-collection-spec.rb b/UnitTests/HttpInterface/api-collection-spec.rb index e2274b9225..339a5c65a7 100644 --- a/UnitTests/HttpInterface/api-collection-spec.rb +++ b/UnitTests/HttpInterface/api-collection-spec.rb @@ -422,7 +422,6 @@ describe ArangoDB do ## load a collection ################################################################################ - ArangoDB.drop_collection(@cn) context "loading:" do before do @cn = "UnitTestsCollectionBasics" @@ -443,6 +442,7 @@ describe ArangoDB do doc.parsed_response['name'].should eq(@cn) doc.parsed_response['status'].should eq(3) doc.parsed_response['count'].should be_kind_of(Integer) + doc.parsed_response['count'].should eq(0) ArangoDB.drop_collection(@cn) end @@ -462,6 +462,59 @@ describe ArangoDB do doc.parsed_response['name'].should eq(@cn) doc.parsed_response['status'].should eq(3) doc.parsed_response['count'].should be_kind_of(Integer) + doc.parsed_response['count'].should eq(0) + + ArangoDB.drop_collection(@cn) + end + + it "load a collection by name with explicit count" do + ArangoDB.drop_collection(@cn) + cid = ArangoDB.create_collection(@cn) + + cmd = "/_api/document?collection=#{@cn}" + body = "{ \"Hallo\" : \"World\" }" + + for i in ( 1 .. 10 ) + doc = ArangoDB.post(cmd, :body => body) + end + + cmd = api + "/" + @cn + "/load" + body = "{ \"count\" : true }" + doc = ArangoDB.log_put("#{prefix}-name-load", cmd, :body => body) + + doc.code.should eq(200) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(200) + doc.parsed_response['id'].should eq(cid) + doc.parsed_response['name'].should eq(@cn) + doc.parsed_response['status'].should eq(3) + doc.parsed_response['count'].should be_kind_of(Integer) + doc.parsed_response['count'].should eq(10) + + ArangoDB.drop_collection(@cn) + end + + it "load a collection by name without count" do + ArangoDB.drop_collection(@cn) + cid = ArangoDB.create_collection(@cn) + + cmd = "/_api/document?collection=#{@cn}" + body = "{ \"Hallo\" : \"World\" }" + doc = ArangoDB.post(cmd, :body => body) + + cmd = api + "/" + @cn + "/load" + body = "{ \"count\" : false }" + doc = ArangoDB.log_put("#{prefix}-name-load", cmd, :body => body) + + doc.code.should eq(200) + doc.headers['content-type'].should eq("application/json; charset=utf-8") + doc.parsed_response['error'].should eq(false) + doc.parsed_response['code'].should eq(200) + doc.parsed_response['id'].should eq(cid) + doc.parsed_response['name'].should eq(@cn) + doc.parsed_response['status'].should eq(3) + doc.parsed_response['count'].should be_nil ArangoDB.drop_collection(@cn) end diff --git a/UnitTests/Makefile.unittests b/UnitTests/Makefile.unittests index a4dc228a97..2801a61059 100755 --- a/UnitTests/Makefile.unittests +++ b/UnitTests/Makefile.unittests @@ -205,6 +205,7 @@ endif SHELL_COMMON = @top_srcdir@/js/common/tests/shell-document.js \ @top_srcdir@/js/common/tests/shell-edge.js \ + @top_srcdir@/js/common/tests/shell-database.js \ @top_srcdir@/js/common/tests/shell-collection.js \ @top_srcdir@/js/common/tests/shell-compactor.js \ @top_srcdir@/js/common/tests/shell-graph-traversal.js \ diff --git a/arangod/V8Server/v8-vocbase.cpp b/arangod/V8Server/v8-vocbase.cpp index d89e3cf44d..926ce9b5d3 100644 --- a/arangod/V8Server/v8-vocbase.cpp +++ b/arangod/V8Server/v8-vocbase.cpp @@ -5705,6 +5705,20 @@ static v8::Handle JS_UpdateVocbase (v8::Arguments const& argv) { return UpdateVocbaseCol(false, argv); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief return the server version string +/// +/// @FUN{@FA{db}._version()} +/// +/// Returns the server version string. +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_VersionVocbase (v8::Arguments const& argv) { + v8::HandleScope scope; + + return scope.Close(v8::String::New(TRIAGENS_VERSION)); +} + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// @@ -6466,6 +6480,7 @@ TRI_v8_global_t* TRI_InitV8VocBridge (v8::Handle context, TRI_AddMethodVocbase(rt, "_remove", JS_RemoveVocbase); TRI_AddMethodVocbase(rt, "_replace", JS_ReplaceVocbase); TRI_AddMethodVocbase(rt, "_update", JS_UpdateVocbase); + TRI_AddMethodVocbase(rt, "_version", JS_VersionVocbase); v8g->VocbaseTempl = v8::Persistent::New(rt); TRI_AddGlobalFunctionVocbase(context, "ArangoDatabase", ft->GetFunction()); @@ -6618,7 +6633,6 @@ TRI_v8_global_t* TRI_InitV8VocBridge (v8::Handle context, #endif v8::ReadOnly); - context->Global()->Set(TRI_V8_SYMBOL("VERSION"), v8::String::New(TRIAGENS_VERSION), v8::ReadOnly); context->Global()->Set(TRI_V8_SYMBOL("DATABASEPATH"), v8::String::New(vocbase->_path), v8::ReadOnly); // ............................................................................. diff --git a/arangod/VocBase/index.c b/arangod/VocBase/index.c index dd50c081c6..72b32f4bb3 100644 --- a/arangod/VocBase/index.c +++ b/arangod/VocBase/index.c @@ -548,6 +548,7 @@ static int InsertEdge (TRI_index_t* idx, TRI_doc_mptr_t const* doc) { TRI_doc_edge_key_marker_t const* edge; bool isReflexive; bool isBidirectional; + TRI_multi_pointer_t* edgesIndex = &(((TRI_edge_index_t*) idx)->_edges); edge = doc->_data; @@ -575,7 +576,7 @@ static int InsertEdge (TRI_index_t* idx, TRI_doc_mptr_t const* doc) { entryIn->_flags = TRI_FlagsEdge(TRI_EDGE_IN, isReflexive, isBidirectional); entryIn->_cid = edge->_toCid; entryIn->_key = ((char*) edge) + edge->_offsetToKey; - TRI_InsertElementMultiPointer(edgesIndex, entryIn, true, true); + TRI_InsertElementMultiPointer(edgesIndex, entryIn, true, false); // second slot: OUT entryOut = entries + 1; @@ -583,7 +584,7 @@ static int InsertEdge (TRI_index_t* idx, TRI_doc_mptr_t const* doc) { entryOut->_flags = TRI_FlagsEdge(TRI_EDGE_OUT, isReflexive, isBidirectional); entryOut->_cid = edge->_fromCid; entryOut->_key = ((char*) edge) + edge->_offsetFromKey; - TRI_InsertElementMultiPointer(edgesIndex, entryOut, true, true); + TRI_InsertElementMultiPointer(edgesIndex, entryOut, true, false); return TRI_ERROR_NO_ERROR; } diff --git a/js/actions/system/api-collection.js b/js/actions/system/api-collection.js index 83a41777da..3cecc3860f 100644 --- a/js/actions/system/api-collection.js +++ b/js/actions/system/api-collection.js @@ -269,7 +269,7 @@ function get_api_collections (req, res) { /// @REST{GET /_api/collection/@FA{collection-name}} ////////////////////////////////////////////////////////// /// -/// The result is an objects describing the collection with the following +/// The result is an object describing the collection with the following /// attributes: /// /// - @LIT{id}: The identifier of the collection. @@ -467,14 +467,24 @@ function get_api_collection (req, res) { /// /// @REST{PUT /_api/collection/@FA{collection-name}/load} /// -/// Loads a collection into memory. On success an object with the following -/// attributes is returned: +/// Loads a collection into memory. Returns the collection on success. +/// +/// The request might optionally contain the following attribute: +/// +/// - @LIT{count}: If set, this controls whether the return value should include +/// the number of documents in the collection. Setting @LIT{count} to +/// @LIT{false} may speed up loading a collection. The default value for +/// @LIT{count} is @LIT{true}. +/// +/// On success an object with the following attributes is returned: /// /// - @LIT{id}: The identifier of the collection. /// /// - @LIT{name}: The name of the collection. /// -/// - @LIT{count}: The number of documents inside the collection. +/// - @LIT{count}: The number of documents inside the collection. This is only +/// returned if the @LIT{count} input parameters is set to @LIT{true} or has +/// not been specified. /// /// - @LIT{status}: The status of the collection as number. /// @@ -495,7 +505,13 @@ function put_api_collection_load (req, res, collection) { try { collection.load(); - var result = collectionRepresentation(collection, false, true, false); + var showCount = true; + var body = actions.getJsonBody(req, res); + if (body && body.hasOwnProperty("count")) { + showCount = body.count; + } + + var result = collectionRepresentation(collection, false, showCount, false); actions.resultOk(req, res, actions.HTTP_OK, result); } diff --git a/js/client/client.js b/js/client/client.js index 584cccc977..ca7a39e69f 100755 --- a/js/client/client.js +++ b/js/client/client.js @@ -1528,8 +1528,14 @@ function ArangoCollection (database, data) { /// @brief loads a collection //////////////////////////////////////////////////////////////////////////////// - ArangoCollection.prototype.load = function () { - var requestResult = this._database._connection.PUT(this._baseurl("load"), ""); + ArangoCollection.prototype.load = function (count) { + var data = { count: true }; + // return the number of documents? this might slow down loading + if (count != undefined) { + data.count = count; + } + + var requestResult = this._database._connection.PUT(this._baseurl("load"), JSON.stringify(data)); client.checkRequestResult(requestResult); @@ -2369,6 +2375,18 @@ function ArangoDatabase (connection) { return true; }; +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the database version +//////////////////////////////////////////////////////////////////////////////// + + ArangoDatabase.prototype._version = function () { + var requestResult = this._connection.GET("/_api/version"); + + client.checkRequestResult(requestResult); + + return requestResult.version; + } + //////////////////////////////////////////////////////////////////////////////// /// @} //////////////////////////////////////////////////////////////////////////////// diff --git a/js/common/tests/shell-database.js b/js/common/tests/shell-database.js new file mode 100644 index 0000000000..35f1fbb229 --- /dev/null +++ b/js/common/tests/shell-database.js @@ -0,0 +1,69 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the database interface +/// +/// @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 +//////////////////////////////////////////////////////////////////////////////// + +var jsunity = require("jsunity"); +var internal = require("internal"); + +// ----------------------------------------------------------------------------- +// --SECTION-- database methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite: error handling +//////////////////////////////////////////////////////////////////////////////// + +function DatabaseSuite () { + return { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the version information +//////////////////////////////////////////////////////////////////////////////// + + testVersion : function () { + assertEqual("1.2.alpha", internal.db._version()); + } + + }; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- main +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief executes the test suite +//////////////////////////////////////////////////////////////////////////////// + +jsunity.run(DatabaseSuite); + +return jsunity.done(); + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" +// End: + diff --git a/js/server/version-check.js b/js/server/version-check.js index ed98fb01ee..a5d4ea72d6 100644 --- a/js/server/version-check.js +++ b/js/server/version-check.js @@ -109,7 +109,7 @@ } } - console.log("Starting upgrade from version " + (lastVersion || "unknown") + " to " + VERSION); + console.log("Starting upgrade from version " + (lastVersion || "unknown") + " to " + internal.db._version()); // -------------------------------------------------------------------------- // the actual upgrade tasks. all tasks defined here should be "re-entrant" @@ -333,10 +333,10 @@ var lastVersion = null; - var currentServerVersion = VERSION.match(/^(\d+\.\d+).*$/); + var currentServerVersion = internal.db._version().match(/^(\d+\.\d+).*$/); if (! currentServerVersion) { // server version is invalid for some reason - console.error("Unexpected ArangoDB server version: " + VERSION); + console.error("Unexpected ArangoDB server version: " + internal.db._version()); return false; } diff --git a/lib/BasicsC/associative-multi.c b/lib/BasicsC/associative-multi.c index c74d1e8746..6d5ef2a997 100644 --- a/lib/BasicsC/associative-multi.c +++ b/lib/BasicsC/associative-multi.c @@ -800,7 +800,7 @@ void* TRI_InsertElementMultiPointer (TRI_multi_pointer_t* array, // we use this flag to speed up initial insertion into the index, i.e. when the // index is built for a collection and we know for sure no duplicate elements // will be inserted - while (array->_table[i] != NULL && (checkEquality && ! array->isEqualElementElement(array, element, array->_table[i]))) { + while (array->_table[i] != NULL && (! checkEquality || ! array->isEqualElementElement(array, element, array->_table[i]))) { i = (i + 1) % array->_nrAlloc; #ifdef TRI_INTERNAL_STATS array->_nrProbesA++;