1
0
Fork 0

added loader

This commit is contained in:
Frank Celler 2011-11-25 17:35:06 +01:00
parent 2be85a89be
commit 3ecf51c305
43 changed files with 3304 additions and 1761 deletions

View File

@ -306,7 +306,7 @@ namespace triagens {
/// Debug log information is generally useful to find out the state of the
/// server in the case of an error. For example,
///
/// @LIT{2010-09-17T13:02:53Z [13783] DEBUG (ApplicationServer/ApplicationServerImpl.cpp:1200) opened port 7000 for any}
/// @LIT{2010-09-17T13:02:53Z [13783] DEBUG opened port 7000 for any}
///
/// Note that, setting the log level to debug will also result in all errors,
/// warnings and server status information to be logged as well.
@ -316,7 +316,7 @@ namespace triagens {
///
/// For example,
///
/// @LIT{2010-09-20T08:23:12Z [5687] TRACE (ApplicationServer/ApplicationServerImpl.cpp:1088) trying to open port 8000 for http requests\, token = '0'}
/// @LIT{2010-09-20T08:23:12Z [5687] TRACE trying to open port 8000}
///
/// Note that, setting the log level to trace will also result in all errors,
/// warnings, status information, and debug information to be logged as well.
@ -403,13 +403,11 @@ namespace triagens {
/// log information. Setting this option appends the thread id of the calling
/// thread to the process id. For example,
///
/// @LIT{2010-09-20T13:04:01Z [19355] INFO SimpleVOC ready for business}
/// @LIT{2010-09-20T13:04:01Z [19355] INFO VOC version 1.6.1 (6734:6766)}
/// @LIT{2010-09-20T13:04:01Z [19355] INFO ready for business}
///
/// when no thread is logged and
///
/// @LIT{2010-09-20T13:04:17Z [19371-18446744072487317056] INFO SimpleVOC ready for business}
/// @LIT{2010-09-20T13:04:17Z [19371-18446744072487317056] INFO VOC version 1.6.1 (6734:6766)}
/// @LIT{2010-09-20T13:04:17Z [19371-18446744072487317056] ready for business}
///
/// when this command line option is set.
////////////////////////////////////////////////////////////////////////////////

View File

@ -1,78 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Mutex
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Achim Brandt
/// @author Copyright 2008-2011, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "Mutex-posix.h"
#include <Basics/Logger.h>
namespace triagens {
namespace basics {
// -----------------------------------------------------------------------------
// constructors and destructors
// -----------------------------------------------------------------------------
Mutex::Mutex () {
pthread_mutex_init(&_mutex, 0);
}
Mutex::~Mutex () {
pthread_mutex_destroy(&_mutex);
}
// -----------------------------------------------------------------------------
// public methods
// -----------------------------------------------------------------------------
bool Mutex::lock () {
int rc = pthread_mutex_lock(&_mutex);
if (rc != 0) {
LOGGER_ERROR << "could not lock the mutex: " << strerror(rc);
return false;
}
return true;
}
bool Mutex::unlock () {
int rc = pthread_mutex_unlock(&_mutex);
if (rc != 0) {
LOGGER_ERROR << "could not release the mutex: " << strerror(rc);
return false;
}
return true;
}
}
}

View File

@ -1,90 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Mutex
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Achim Brandt
/// @author Copyright 2008-2011, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_BASICS_MUTEX_POSIX_H
#define TRIAGENS_BASICS_MUTEX_POSIX_H 1
#include <Basics/Common.h>
namespace triagens {
namespace basics {
////////////////////////////////////////////////////////////////////////////////
/// @ingroup Threads
/// @brief mutex
///
/// Mutual exclusion (often abbreviated to mutex) algorithms are used in
/// concurrent programming to avoid the simultaneous use of a common resource,
/// such as a global variable, by pieces of computer code called critical
/// sections. A critical section is a piece of code in which a process or thread
/// accesses a common resource. The critical section by itself is not a
/// mechanism or algorithm for mutual exclusion. A program, process, or thread
/// can have the critical section in it without any mechanism or algorithm which
/// implements mutual exclusion. For details see www.wikipedia.org.
////////////////////////////////////////////////////////////////////////////////
class Mutex {
private:
Mutex (Mutex const&);
Mutex& operator= (Mutex const&);
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a mutex
////////////////////////////////////////////////////////////////////////////////
Mutex ();
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes the mutex
////////////////////////////////////////////////////////////////////////////////
~Mutex ();
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief acquires the lock
////////////////////////////////////////////////////////////////////////////////
bool lock () WARN_UNUSED;
////////////////////////////////////////////////////////////////////////////////
/// @brief releases the lock
////////////////////////////////////////////////////////////////////////////////
bool unlock () WARN_UNUSED;
private:
pthread_mutex_t _mutex;
};
}
}
#endif

94
Basics/Mutex.cpp Normal file
View File

@ -0,0 +1,94 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Mutex
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Achim Brandt
/// @author Copyright 2008-2011, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "Mutex.h"
using namespace triagens::basics;
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a mutex
////////////////////////////////////////////////////////////////////////////////
Mutex::Mutex () {
TRI_InitMutex(&_mutex);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes the mutex
////////////////////////////////////////////////////////////////////////////////
Mutex::~Mutex () {
TRI_DestroyMutex(&_mutex);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief acquires the lock
////////////////////////////////////////////////////////////////////////////////
void Mutex::lock () {
TRI_LockMutex(&_mutex);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief releases the lock
////////////////////////////////////////////////////////////////////////////////
void Mutex::unlock () {
TRI_UnlockMutex(&_mutex);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -23,7 +23,7 @@
///
/// @author Dr. Frank Celler
/// @author Achim Brandt
/// @author Copyright 2010-2011, triAGENS GmbH, Cologne, Germany
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_BASICS_MUTEX_H
@ -31,12 +31,114 @@
#include <Basics/Common.h>
#ifdef TRI_HAVE_POSIX_THREADS
#include <Basics/Mutex-posix.h>
#endif
#include <Basics/locks.h>
#ifdef TRI_HAVE_WIN32_THREADS
#include <Basics/Mutex-win32.h>
#endif
// -----------------------------------------------------------------------------
// --SECTION-- class Mutex
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace triagens {
namespace basics {
////////////////////////////////////////////////////////////////////////////////
/// @brief mutex
////////////////////////////////////////////////////////////////////////////////
class Mutex {
private:
Mutex (Mutex const&);
Mutex& operator= (Mutex const&);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a mutex
////////////////////////////////////////////////////////////////////////////////
Mutex ();
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes the mutex
////////////////////////////////////////////////////////////////////////////////
~Mutex ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief acquires the lock
////////////////////////////////////////////////////////////////////////////////
void lock ();
////////////////////////////////////////////////////////////////////////////////
/// @brief releases the lock
////////////////////////////////////////////////////////////////////////////////
void unlock ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief mutex variable
////////////////////////////////////////////////////////////////////////////////
TRI_mutex_t _mutex;
};
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -40,42 +40,20 @@ namespace triagens {
MutexLocker::MutexLocker (Mutex* mutex)
: _mutex(mutex), _file(0), _line(0) {
bool ok = _mutex->lock();
if (! ok) {
THROW_INTERNAL_ERROR("mutex lock failed");
}
_mutex->lock();
}
MutexLocker::MutexLocker (Mutex* mutex, char const* file, int line)
: _mutex(mutex), _file(file), _line(line) {
bool ok = _mutex->lock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("mutex lock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("mutex lock failed");
}
}
_mutex->lock();
}
MutexLocker::~MutexLocker () {
bool ok = _mutex->unlock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("mutex unlock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("mutex unlock failed");
}
}
_mutex->unlock();
}
}
}

View File

@ -40,42 +40,20 @@ namespace triagens {
ReadLocker::ReadLocker (ReadWriteLock* readWriteLock)
: _readWriteLock(readWriteLock), _file(0), _line(0) {
bool ok = _readWriteLock->readLock();
if (! ok) {
THROW_INTERNAL_ERROR("read lock failed");
}
_readWriteLock->readLock();
}
ReadLocker::ReadLocker (ReadWriteLock* readWriteLock, char const* file, int line)
: _readWriteLock(readWriteLock), _file(file), _line(line) {
bool ok = _readWriteLock->readLock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("read lock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("read lock failed");
}
}
_readWriteLock->readLock();
}
ReadLocker::~ReadLocker () {
bool ok = _readWriteLock->unlock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("read unlock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("read unlock failed");
}
}
_readWriteLock->unlock();
}
}
}

View File

@ -40,42 +40,20 @@ namespace triagens {
ReadUnlocker::ReadUnlocker (ReadWriteLock* readWriteLock)
: _readWriteLock(readWriteLock), _file(0), _line(0) {
bool ok = _readWriteLock->unlock();
if (! ok) {
THROW_INTERNAL_ERROR("read unlock failed");
}
_readWriteLock->unlock();
}
ReadUnlocker::ReadUnlocker (ReadWriteLock* readWriteLock, char const* file, int line)
: _readWriteLock(readWriteLock), _file(file), _line(line) {
bool ok = _readWriteLock->unlock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("read unlock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("read unlock failed");
}
}
_readWriteLock->unlock();
}
ReadUnlocker::~ReadUnlocker () {
bool ok = _readWriteLock->readLock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("read lock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("read lock failed");
}
}
_readWriteLock->readLock();
}
}
}

View File

@ -1,147 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Read-Write Lock
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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 Frank Celler
/// @author Achim Brandt
/// @author Copyright 2010-2011, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "ReadWriteLock-posix.h"
#include <Basics/Logger.h>
namespace triagens {
namespace basics {
// -----------------------------------------------------------------------------
// constructors and destructora
// -----------------------------------------------------------------------------
ReadWriteLock::ReadWriteLock () {
int rc = pthread_rwlock_init(&_rwlock, 0);
if (rc != 0) {
LOGGER_ERROR << "pthread_rwlock_init() != 0: " << strerror(rc);
}
#ifdef READ_WRITE_LOCK_COUNTER
pthread_mutex_init(&_mutex, 0);
_readLocked = 0;
_writeLocked = 0;
#endif
}
ReadWriteLock::~ReadWriteLock () {
int rc = pthread_rwlock_destroy(&_rwlock);
if (rc != 0) {
LOGGER_ERROR << "pthread_rwlock_destroy() != 0: " << strerror(rc);
}
#ifdef READ_WRITE_LOCK_COUNTER
pthread_mutex_destroy(&_mutex);
#endif
}
// -----------------------------------------------------------------------------
// public methods
// -----------------------------------------------------------------------------
bool ReadWriteLock::readLock () {
int rc = pthread_rwlock_rdlock(&_rwlock);
if (rc != 0) {
LOGGER_ERROR << "could not lock for reading: " << strerror(rc);
return false;
}
#ifdef READ_WRITE_LOCK_COUNTER
{
pthread_mutex_lock(&_mutex);
_readLocked++;
pthread_mutex_unlock(&_mutex);
}
#endif
return true;
}
bool ReadWriteLock::writeLock () {
int rc = pthread_rwlock_wrlock(&_rwlock);
if (rc != 0) {
LOGGER_ERROR << "could not lock for writing: " << strerror(rc);
return false;
}
#ifdef READ_WRITE_LOCK_COUNTER
{
pthread_mutex_lock(&_mutex);
_writeLocked++;
pthread_mutex_unlock(&_mutex);
}
#endif
return true;
}
bool ReadWriteLock::unlock () {
#ifdef READ_WRITE_LOCK_COUNTER
{
pthread_mutex_lock(&_mutex);
if (_writeLocked > 0) {
_writeLocked--;
}
else {
_readLocked--;
}
pthread_mutex_unlock(&_mutex);
}
#endif
int rc = pthread_rwlock_unlock(&_rwlock);
if (rc != 0) {
LOGGER_ERROR << "could not release lock: " << strerror(rc);
return false;
}
return true;
}
}
}

View File

@ -1,134 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief read-write lock
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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 Frank Celler
/// @author Achim Brandt
/// @author Copyright 2010-2011, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_BASICS_READ_WRITE_LOCK_POSIX_H
#define TRIAGENS_BASICS_READ_WRITE_LOCK_POSIX_H 1
#include <Basics/Common.h>
#define READ_WRITE_LOCK_COUNTER
namespace triagens {
namespace basics {
////////////////////////////////////////////////////////////////////////////////
/// @ingroup Threads
/// @brief read-write lock
///
/// A ReadWriteLock maintains a pair of associated locks, one for read-only
/// operations and one for writing. The read lock may be held simultaneously by
/// multiple reader threads, so long as there are no writers. The write lock is
/// exclusive.
///
/// A read-write lock allows for a greater level of concurrency in accessing
/// shared data than that permitted by a mutual exclusion lock. It exploits the
/// fact that while only a single thread at a time (a writer thread) can modify
/// the shared data, in many cases any number of threads can concurrently read
/// the data (hence reader threads). In theory, the increase in concurrency
/// permitted by the use of a read-write lock will lead to performance
/// improvements over the use of a mutual exclusion lock. In practice this
/// increase in concurrency will only be fully realized on a multi-processor,
/// and then only if the access patterns for the shared data are suitable.
////////////////////////////////////////////////////////////////////////////////
class ReadWriteLock {
private:
ReadWriteLock (ReadWriteLock const&);
ReadWriteLock& operator= (ReadWriteLock const&);
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a read-write lock
////////////////////////////////////////////////////////////////////////////////
ReadWriteLock ();
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes read-write lock
////////////////////////////////////////////////////////////////////////////////
~ReadWriteLock ();
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief check for read locked
////////////////////////////////////////////////////////////////////////////////
#ifdef READ_WRITE_LOCK_COUNTER
bool isReadLocked () const {
return _readLocked > 0;
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief locks for reading
////////////////////////////////////////////////////////////////////////////////
bool readLock () WARN_UNUSED;
////////////////////////////////////////////////////////////////////////////////
/// @brief check for write locked
////////////////////////////////////////////////////////////////////////////////
#ifdef READ_WRITE_LOCK_COUNTER
bool isWriteLocked () const {
return _writeLocked > 0;
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief locks for writing
////////////////////////////////////////////////////////////////////////////////
bool writeLock () WARN_UNUSED;
////////////////////////////////////////////////////////////////////////////////
/// @brief releases the read-lock or write-lock
////////////////////////////////////////////////////////////////////////////////
bool unlock () WARN_UNUSED;
private:
pthread_rwlock_t _rwlock;
#ifdef READ_WRITE_LOCK_COUNTER
pthread_mutex_t _mutex;
uint32_t _readLocked;
uint32_t _writeLocked;
#endif
};
}
}
#endif

178
Basics/ReadWriteLock.cpp Normal file
View File

@ -0,0 +1,178 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief Read-Write Lock
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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 Frank Celler
/// @author Achim Brandt
/// @author Copyright 2010-2011, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "ReadWriteLock.h"
using namespace triagens::basics;
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a read-write lock
////////////////////////////////////////////////////////////////////////////////
ReadWriteLock::ReadWriteLock () {
TRI_InitReadWriteLock(&_rwlock);
_writeLocked = false;
#ifdef READ_WRITE_LOCK_COUNTER
TRI_InitMutex(&_mutex);
_readLockedCounter = 0;
_writeLockedCounter = 0;
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes read-write lock
////////////////////////////////////////////////////////////////////////////////
ReadWriteLock::~ReadWriteLock () {
TRI_DestroyReadWriteLock(&_rwlock);
#ifdef READ_WRITE_LOCK_COUNTER
TRI_DestroyMutex(&_mutex);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief check for read locked
////////////////////////////////////////////////////////////////////////////////
#ifdef READ_WRITE_LOCK_COUNTER
bool ReadWriteLock::isReadLocked () const {
return _readLockedCounter > 0;
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief locks for reading
////////////////////////////////////////////////////////////////////////////////
void ReadWriteLock::readLock () {
TRI_ReadLockReadWriteLock(&_rwlock);
#ifdef READ_WRITE_LOCK_COUNTER
TRI_LockMutex(&_mutex);
_readLockedCounter++;
TRI_UnlockMutex(&_mutex);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @brief check for write locked
////////////////////////////////////////////////////////////////////////////////
#ifdef READ_WRITE_LOCK_COUNTER
bool ReadWriteLock::isWriteLocked () const {
return _writeLockedCounter > 0;
}
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief locks for writing
////////////////////////////////////////////////////////////////////////////////
void ReadWriteLock::writeLock () {
TRI_WriteLockReadWriteLock(&_rwlock);
_writeLocked = true;
#ifdef READ_WRITE_LOCK_COUNTER
TRI_LockMutex(&_mutex);
_writeLockedCounter++;
TRI_UnlockMutex(&_mutex);
#endif
}
////////////////////////////////////////////////////////////////////////////////
/// @brief releases the read-lock or write-lock
////////////////////////////////////////////////////////////////////////////////
void ReadWriteLock::unlock () {
#ifdef READ_WRITE_LOCK_COUNTER
TRI_LockMutex(&_mutex);
if (_writeLocked) {
_writeLockedCounter--;
}
else {
_readLockedCounter--;
}
TRI_UnlockMutex(&_mutex);
#endif
if (_writeLocked) {
_writeLocked = false;
TRI_WriteUnlockReadWriteLock(&_rwlock);
}
else {
TRI_ReadUnlockReadWriteLock(&_rwlock);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -31,12 +31,172 @@
#include <Basics/Common.h>
#ifdef TRI_HAVE_POSIX_THREADS
#include <Basics/ReadWriteLock-posix.h>
#endif
#include <Basics/locks.h>
#ifdef TRI_HAVE_WIN32_THREADS
#include <Basics/ReadWriteLock-win32.h>
#endif
#undef READ_WRITE_LOCK_COUNTER
// -----------------------------------------------------------------------------
// --SECTION-- class ReadWriteLock
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace triagens {
namespace basics {
////////////////////////////////////////////////////////////////////////////////
/// @brief read-write lock
////////////////////////////////////////////////////////////////////////////////
class ReadWriteLock {
private:
ReadWriteLock (ReadWriteLock const&);
ReadWriteLock& operator= (ReadWriteLock const&);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a read-write lock
////////////////////////////////////////////////////////////////////////////////
ReadWriteLock ();
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes read-write lock
////////////////////////////////////////////////////////////////////////////////
~ReadWriteLock ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief check for read locked
////////////////////////////////////////////////////////////////////////////////
#ifdef READ_WRITE_LOCK_COUNTER
bool isReadLocked () const;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief locks for reading
////////////////////////////////////////////////////////////////////////////////
void readLock ();
////////////////////////////////////////////////////////////////////////////////
/// @brief check for write locked
////////////////////////////////////////////////////////////////////////////////
#ifdef READ_WRITE_LOCK_COUNTER
bool isWriteLocked () const;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief locks for writing
////////////////////////////////////////////////////////////////////////////////
void writeLock ();
////////////////////////////////////////////////////////////////////////////////
/// @brief releases the read-lock or write-lock
////////////////////////////////////////////////////////////////////////////////
void unlock ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup Threading
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief read-write lock variable
////////////////////////////////////////////////////////////////////////////////
TRI_read_write_lock_t _rwlock;
////////////////////////////////////////////////////////////////////////////////
/// @brief write lock marker
////////////////////////////////////////////////////////////////////////////////
bool _writeLocked;
////////////////////////////////////////////////////////////////////////////////
/// @brief mutex for read-write counter
////////////////////////////////////////////////////////////////////////////////
#ifdef READ_WRITE_LOCK_COUNTER
TRI_mutex_t _mutex;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief read counter
////////////////////////////////////////////////////////////////////////////////
#ifdef READ_WRITE_LOCK_COUNTER
int32_t _readLockedCounter;
#endif
////////////////////////////////////////////////////////////////////////////////
/// @brief write counter
////////////////////////////////////////////////////////////////////////////////
#ifdef READ_WRITE_LOCK_COUNTER
int32_t _writeLockedCounter;
#endif
};
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -40,41 +40,19 @@ namespace triagens {
WriteLocker::WriteLocker (ReadWriteLock* readWriteLock)
: _readWriteLock(readWriteLock), _file(0), _line(0) {
bool ok = _readWriteLock->writeLock();
if (! ok) {
THROW_INTERNAL_ERROR("write lock failed");
}
_readWriteLock->writeLock();
}
WriteLocker::WriteLocker (ReadWriteLock* readWriteLock, char const* file, int line)
: _readWriteLock(readWriteLock), _file(file), _line(line) {
bool ok = _readWriteLock->writeLock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("write lock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("write lock failed");
}
}
_readWriteLock->writeLock();
}
WriteLocker::~WriteLocker () {
bool ok = _readWriteLock->unlock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("write unlock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("write unlock failed");
}
}
_readWriteLock->unlock();
}
}
}

View File

@ -40,43 +40,21 @@ namespace triagens {
WriteUnlocker::WriteUnlocker (ReadWriteLock* readWriteLock)
: _readWriteLock(readWriteLock), _file(0), _line(0) {
bool ok = _readWriteLock->unlock();
if (! ok) {
THROW_INTERNAL_ERROR("write unlock failed");
}
_readWriteLock->unlock();
}
WriteUnlocker::WriteUnlocker (ReadWriteLock* readWriteLock, char const* file, int line)
: _readWriteLock(readWriteLock), _file(file), _line(line) {
bool ok = _readWriteLock->unlock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("write unlock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("write unlock failed");
}
}
_readWriteLock->unlock();
}
WriteUnlocker::~WriteUnlocker () {
bool ok = _readWriteLock->writeLock();
if (! ok) {
if (_file != 0) {
THROW_INTERNAL_ERROR_L("write lock failed", _file, _line);
}
else {
THROW_INTERNAL_ERROR("write lock failed");
}
}
_readWriteLock->writeLock();
}
}
}

View File

@ -81,6 +81,15 @@ extern "C" {
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises a new mutex
///
/// Mutual exclusion (often abbreviated to mutex) algorithms are used in
/// concurrent programming to avoid the simultaneous use of a common resource,
/// such as a global variable, by pieces of computer code called critical
/// sections. A critical section is a piece of code in which a process or thread
/// accesses a common resource. The critical section by itself is not a
/// mechanism or algorithm for mutual exclusion. A program, process, or thread
/// can have the critical section in it without any mechanism or algorithm which
/// implements mutual exclusion. For details see www.wikipedia.org.
////////////////////////////////////////////////////////////////////////////////
void TRI_InitMutex (TRI_mutex_t*);
@ -189,6 +198,21 @@ void TRI_UnlockSpin (TRI_spin_t* spin);
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises a new read-write lock
///
/// A ReadWriteLock maintains a pair of associated locks, one for read-only
/// operations and one for writing. The read lock may be held simultaneously by
/// multiple reader threads, so long as there are no writers. The write lock is
/// exclusive.
///
/// A read-write lock allows for a greater level of concurrency in accessing
/// shared data than that permitted by a mutual exclusion lock. It exploits the
/// fact that while only a single thread at a time (a writer thread) can modify
/// the shared data, in many cases any number of threads can concurrently read
/// the data (hence reader threads). In theory, the increase in concurrency
/// permitted by the use of a read-write lock will lead to performance
/// improvements over the use of a mutual exclusion lock. In practice this
/// increase in concurrency will only be fully realized on a multi-processor,
/// and then only if the access patterns for the shared data are suitable.
////////////////////////////////////////////////////////////////////////////////
void TRI_InitReadWriteLock (TRI_read_write_lock_t* lock);

View File

@ -1188,7 +1188,7 @@ static void LogAppenderFile_Reopen (TRI_log_appender_t* appender) {
TRI_RenameFile(self->_filename, backup);
// open new log file
fd = TRI_CREATE(self->_filename, O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
fd = TRI_CREATE(self->_filename, O_APPEND | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
TRI_RenameFile(backup, self->_filename);
@ -1287,7 +1287,7 @@ TRI_log_appender_t* TRI_CreateLogAppenderFile (char const* filename) {
// logging to file
else {
appender->_fd = TRI_CREATE(filename, O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
appender->_fd = TRI_CREATE(filename, O_APPEND | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP);
if (appender->_fd < 0) {
TRI_Free(appender);

View File

@ -48,15 +48,15 @@ avocdb_SOURCES = \
Basics/LoggerTiming.cpp \
Basics/logging.c \
Basics/memory.c \
Basics/Mutex.cpp \
Basics/MutexLocker.cpp \
Basics/Mutex-posix.cpp \
Basics/ProgramOptions.cpp \
Basics/ProgramOptionsDescription.cpp \
Basics/Random.cpp \
Basics/randomx.c \
Basics/ReadLocker.cpp \
Basics/ReadUnlocker.cpp \
Basics/ReadWriteLock-posix.cpp \
Basics/ReadWriteLock.cpp \
Basics/SocketUtils.cpp \
Basics/string-buffer.c \
Basics/strings.c \
@ -133,7 +133,11 @@ avocdb_SOURCES = \
Rest/RestModel.cpp \
Rest/RestServer.cpp \
Rest/Scheduler.cpp \
RestServer/ActionDispatcherThread.cpp \
RestServer/avocado.cpp \
RestServer/AvocadoHttpServer.cpp \
RestServer/AvocadoServer.cpp \
RestServer/JSLoader.cpp \
Rest/SignalTask.cpp \
Rest/SocketTask.cpp \
Rest/SslInterface.cpp \

View File

@ -126,29 +126,30 @@ HttpHandler::status_e RestDocumentHandler::execute () {
////////////////////////////////////////////////////////////////////////////////
/// @brief creates a document
///
/// <b><tt>POST /_document/<em>collection-identifier</em></tt></b>
/// @REST{POST /_document/@FA{collection-identifier}}
///
/// Creates a new document in the collection identified by the @a
/// collection-identifier. A JSON representation of the document must be passed
/// in the body of the POST request. If the document was created, then a HTTP
/// 201 is returned and the "Location" header contains the path to the newly
/// created document. The "ETag" contains the revision of the newly created
/// document.
/// Creates a new document in the collection identified by the
/// @FA{collection-identifier}. A JSON representation of the document must be
/// passed in the body of the POST request. If the document was created, then a
/// @CODE{HTTP 201} is returned and the "Location" header contains the path to the
/// newly created document. The "ETag" contains the revision of the newly
/// created document.
///
/// @verbinclude rest3
///
/// If the @a collection-identifier is unknown, then a HTTP 404 is returned.
/// If the @FA{collection-identifier} is unknown, then a @CODE{HTTP 404} is
/// returned.
///
/// @verbinclude rest4
///
/// If the body does not contain a valid JSON representation of an document,
/// then a HTTP 400 is returned.
/// then a @CODE{HTTP 400} is returned.
///
/// @verbinclude rest5
///
/// <b><tt>POST /_document/<em>collection-name</em></tt></b>
/// @REST{POST /_document/@FA{collection-name}}
///
/// Creates a new document in the collection named @a collection-name.
/// Creates a new document in the collection named @FA{collection-name}.
///
/// @verbinclude rest6
////////////////////////////////////////////////////////////////////////////////
@ -215,16 +216,16 @@ bool RestDocumentHandler::createDocument () {
////////////////////////////////////////////////////////////////////////////////
/// @brief reads a document
///
/// <b><tt>GET /_document/<em>document-reference</em></tt></b>
/// @REST{GET /_document/@FA{document-reference}}
///
/// Returns the document referenced by @a document-reference. If the document
/// exists, then a HTTP 200 is returned and the JSON representation of the
/// Returns the document referenced by @FA{document-reference}. If the document
/// exists, then a @CODE{HTTP 200} is returned and the JSON representation of the
/// document is the body of the response.
///
/// @verbinclude rest1
///
/// If the document-reference points to a non-existing document, then a
/// HTTP 404 is returned and the body contains an error document.
/// @CODE{HTTP 404} is returned and the body contains an error document.
///
/// @verbinclude rest2
////////////////////////////////////////////////////////////////////////////////
@ -280,32 +281,32 @@ bool RestDocumentHandler::readDocument () {
////////////////////////////////////////////////////////////////////////////////
/// @brief updates a document
///
/// <b><tt>PUT /_document/<em>document-reference</em></tt></b>
/// @REST{PUT /_document/@FA{document-reference}}
///
/// Updates the document referenced by @a document-reference. If the document
/// exists and could be updated, then a HTTP 201 is returned and the "ETag"
/// header contains the new revision of the document.
/// Updates the document referenced by @FA{document-reference}. If the document
/// exists and could be updated, then a @CODE{HTTP 201} is returned and the
/// "ETag" header contains the new revision of the document.
///
/// @verbinclude rest7
///
/// If the document does not exists, then a HTTP 404 is returned.
/// If the document does not exists, then a @CODE{HTTP 404} is returned.
///
/// @verbinclude rest8
///
/// If an etag is supplied in the "ETag" field, then the AvocadoDB checks that
/// the revision of the document is equal to the etag. If there is a mismatch,
/// then a HTTP 409 conflict is returned and no update is performed.
/// then a @CODE{HTTP 409} conflict is returned and no update is performed.
///
/// @verbinclude rest9
///
/// <b><tt>PUT /_document/<em>document-reference</em>?policy=<em>policy</em></tt></b>
/// @REST{PUT /_document/@FA{document-reference}?policy=@FA{policy}}
///
/// As before, if @a policy is @c error. If @a pocily is @c last, then the last
/// write will win.
/// As before, if @FA{policy} is @CODE{error}. If @FA{policy} is @CODE{last},
/// then the last write will win.
///
/// @verbinclude rest10
///
/// <b><tt>PUT /_document/<em>document-reference</em>?_rev=<em>etag</em></tt></b>
/// @REST{PUT /_document/@FA{document-reference}?_rev=@FA{etag}}
///
/// You can also supply the etag using the parameter "_rev" instead of an "ETag"
/// header.
@ -395,29 +396,29 @@ bool RestDocumentHandler::updateDocument () {
////////////////////////////////////////////////////////////////////////////////
/// @brief deletes a document
///
/// <b><tt>DELETE /_document/<em>document-reference</em></tt></b>
/// @REST{DELETE /_document/@FA{document-reference}}
///
/// Deletes the document referenced by @a document-reference. If the document
/// exists and could be deleted, then a HTTP 204 is returned.
/// Deletes the document referenced by @FA{document-reference}. If the document
/// exists and could be deleted, then a @CODE{HTTP 204} is returned.
///
/// @verbinclude rest13
///
/// If the document does not exists, then a HTTP 404 is returned.
/// If the document does not exists, then a @CODE{HTTP 404} is returned.
///
/// @verbinclude rest14
///
/// If an etag is supplied in the "ETag" field, then the AvocadoDB checks that
/// the revision of the document is equal to the etag. If there is a mismatch,
/// then a HTTP 409 conflict is returned and no delete is performed.
/// then a @CODE{HTTP 409} conflict is returned and no delete is performed.
///
/// @verbinclude rest12
///
/// <b><tt>DELETE /_document/<em>document-reference</em>?policy=<em>policy</em></tt></b>
/// @REST{DELETE /_document/@FA{document-reference}?policy=@FA{policy}}
///
/// As before, if @a policy is @c error. If @a pocily is @c last, then the last
/// write will win.
/// As before, if @FA{policy} is @CODE{error}. If @FA{policy} is @CODE{last},
/// then the last write will win.
///
/// <b><tt>DELETE /_document/<em>document-reference</em>?_rev=<em>etag</em></tt></b>
/// @REST{DELETE /_document/@FA{document-reference}? _rev=@FA{etag}}
///
/// You can also supply the etag using the parameter "_rev" instead of an "ETag"
/// header.

View File

@ -30,6 +30,23 @@
#include "RestHandler/RestVocbaseBaseHandler.h"
////////////////////////////////////////////////////////////////////////////////
/// @page CRUDDocument CRUD for Documents
///
/// The basic operations (create, read, update, delete) for documents are mapped
/// to the standard HTTP methods (POST, GET, PUT, DELETE). An identifier for the
/// revision is returned in the "ETag" field. If you modify a document, you can
/// use the "ETag" field to detect conflicts.
///
/// @copydetails triagens::avocado::RestDocumentHandler::createDocument
///
/// @copydetails triagens::avocado::RestDocumentHandler::readDocument
///
/// @copydetails triagens::avocado::RestDocumentHandler::updateDocument
///
/// @copydetails triagens::avocado::RestDocumentHandler::deleteDocument
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- RestDocumentHandler
// -----------------------------------------------------------------------------

View File

@ -38,65 +38,18 @@
/// @page HttpInterface Lightweight HTTP Interface
///
/// The AvocadoDB has a REST interface for accessing the resources. It provides
/// a lightweight HTTP interface to execute actions.
/// a lightweight HTTP interface to execute actions. Actions are small
/// JavaScript functions which encapsulate business logic.
///
/// Next steps:
///
/// - learn more about @ref Actions "actions"
/// - learn more about the @ref RestInterface "REST interface"
/// - learn more about the @ref CRUDDocument "REST interface for documents"
////////////////////////////////////////////////////////////////////////////////
/// @section Actions Actions
////////////////////////////////////////////////////////////////////////////////
///
/// Actions are small JavaScript functions which are used to compute the result
/// of a request. Normally, the function will use the request parameter @a
/// collection to locate a collection, compute the result and return this result
/// as JSON object.
///
/// An action is defined using the function @c defineAction. You need to provide
/// a path, a function, and a description of the parameters.
///
/// @verbinclude action1
///
/// This will define a new action accessible under @c /_action/pagination, with
/// three parameters @a collection, @a blocksize, and @a page. The action
/// function is called with two parameters @a req and @a res. The variable @a
/// req contains the request parameters. The result is stored in the variable @a
/// res.
///
/// The function @c queryResult is predefined. It expects three parameters, the
/// request, the response, and a result set. The function @c queryResult uses
/// the parameters @a blocksize and @a page to paginate the result.
///
/// @verbinclude action2
///
/// The result contains the @a total number of documents, the number of
/// documents returned in @a count, the @a offset, the @a blocksize, the current
/// @a page, and the @a documents.
///
/// There is an alternative function @c queryReferences, which will only return
/// the document references, not the whole document.
///
/// @verbinclude action3
///
/// You can then use the rest interface to extract the documents.
///
/// @verbinclude action4
///
////////////////////////////////////////////////////////////////////////////////
/// @subsection JSFQueryBuilding Query Building Functions
////////////////////////////////////////////////////////////////////////////////
///
/// The following functions can be used to build the result-set.
///
/// @copydetails JS_AllQuery
/// @copydetails JS_DistanceQuery
/// @copydetails JS_DocumentQuery
/// @copydetails JS_GeoQuery
/// @copydetails JS_LimitQuery
/// @copydetails JS_NearQuery
/// @copydetails JS_SelectQuery
/// @copydetails JS_SkipQuery
/// @copydetails JS_WithinQuery
///
////////////////////////////////////////////////////////////////////////////////
/// @section RestInterface REST Interface
/// @page RestInterface REST Interface
////////////////////////////////////////////////////////////////////////////////
///
/// Each resource has an identifier, which allows to access the given resource.
@ -117,22 +70,9 @@
/// - etag:
/// A revision of a document has an etag.
///
////////////////////////////////////////////////////////////////////////////////
/// @subsection RestDocument CRUD for Documents
////////////////////////////////////////////////////////////////////////////////
/// Next steps:
///
/// The basic operations (create, read, update, delete) for documents are mapped
/// to the standard HTTP methods (POST, GET, PUT, DELETE). An identifier for the
/// revision is returned in the "ETag" field. If you modify a document, you can
/// use the "ETag" field to detect conflicts.
///
/// @copydetails triagens::avocado::RestDocumentHandler::createDocument
///
/// @copydetails triagens::avocado::RestDocumentHandler::readDocument
///
/// @copydetails triagens::avocado::RestDocumentHandler::updateDocument
///
/// @copydetails triagens::avocado::RestDocumentHandler::deleteDocument
/// - learn more about the @ref CRUDDocument "REST interface for documents"
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------

View File

@ -0,0 +1,261 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief dispatcher thread for actions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Copyright 2010-2011, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "ActionDispatcherThread.h"
#include <Basics/Logger.h>
#include <Basics/files.h>
#include <Basics/strings.h>
#include <Rest/Initialise.h>
#include "V8/v8-actions.h"
#include "V8/v8-globals.h"
#include "V8/v8-shell.h"
#include "V8/v8-utils.h"
#include "V8/v8-vocbase.h"
using namespace std;
using namespace triagens::basics;
using namespace triagens::rest;
using namespace triagens::avocado;
// -----------------------------------------------------------------------------
// --SECTION-- class ActionDisptacherThread
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public static variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief action path
////////////////////////////////////////////////////////////////////////////////
JSLoader* ActionDisptacherThread::_actionLoader = 0;
////////////////////////////////////////////////////////////////////////////////
/// @brief startup path
////////////////////////////////////////////////////////////////////////////////
JSLoader* ActionDisptacherThread::_startupLoader = 0;
////////////////////////////////////////////////////////////////////////////////
/// @brief vocbase
////////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* ActionDisptacherThread::_vocbase = 0;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new dispatcher thread
////////////////////////////////////////////////////////////////////////////////
ActionDisptacherThread::ActionDisptacherThread (DispatcherQueue* queue)
: DispatcherThread(queue),
_report(false),
_isolate(0),
_context() {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destructs a dispatcher thread
////////////////////////////////////////////////////////////////////////////////
ActionDisptacherThread::~ActionDisptacherThread () {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- DispatcherThread methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void ActionDisptacherThread::reportStatus () {
_report = true;
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void ActionDisptacherThread::tick () {
while(!v8::V8::IdleNotification()) {
}
if (! _report || _isolate == 0) {
return;
}
_report = false;
TRI_v8_global_t* v8g = (TRI_v8_global_t*) _isolate->GetData();
if (v8g == 0) {
return;
}
LOGGER_DEBUG << "active queries: " << v8g->JSQueries.size();
LOGGER_DEBUG << "active result-sets: " << v8g->JSResultSets.size();
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- Thread methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void ActionDisptacherThread::run () {
initialise();
_isolate->Enter();
_context->Enter();
DispatcherThread::run();
_context->Exit();
_context.Dispose();
_isolate->Exit();
_isolate->Dispose();
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises the isolate and context
////////////////////////////////////////////////////////////////////////////////
void ActionDisptacherThread::initialise () {
bool ok;
char* filename;
char const* files[] = { "json.js", "actions.js" };
size_t i;
// enter a new isolate
_isolate = v8::Isolate::New();
_isolate->Enter();
// create the context
_context = v8::Context::New(0);
if (_context.IsEmpty()) {
LOGGER_FATAL << "cannot initialize V8 engine";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
_context->Enter();
TRI_InitV8VocBridge(_context, _vocbase);
TRI_InitV8Actions(_context);
TRI_InitV8Utils(_context);
TRI_InitV8Shell(_context);
// load all init files
for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i) {
ok = _startupLoader->loadScript(_context, files[i]);
if (! ok) {
LOGGER_FATAL << "cannot load json utilities from file '" << filename << "'";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
}
// load all actions
ok = _actionLoader->loadAllScripts(_context);
if (! ok) {
LOGGER_FATAL << "cannot load actions from directory '" << filename << "'";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
// and return from the context
_context->Exit();
_isolate->Exit();
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -0,0 +1,233 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief dispatcher thread for actions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_AVOCADODB_RESTHANDLER_REST_ACTION_HANDLER2_H
#define TRIAGENS_AVOCADODB_RESTHANDLER_REST_ACTION_HANDLER2_H 1
#include "Dispatcher/DispatcherThread.h"
#include <v8.h>
#include <VocBase/vocbase.h>
#include "RestServer/JSLoader.h"
// -----------------------------------------------------------------------------
// --SECTION-- class ActionDisptacherThread
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace triagens {
namespace avocado {
////////////////////////////////////////////////////////////////////////////////
/// @brief dispatcher thread
////////////////////////////////////////////////////////////////////////////////
class ActionDisptacherThread : public rest::DispatcherThread {
ActionDisptacherThread (ActionDisptacherThread const&);
ActionDisptacherThread& operator= (ActionDisptacherThread const&);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public static variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief action path
////////////////////////////////////////////////////////////////////////////////
static JSLoader* _actionLoader;
////////////////////////////////////////////////////////////////////////////////
/// @brief startup path
////////////////////////////////////////////////////////////////////////////////
static JSLoader* _startupLoader;
////////////////////////////////////////////////////////////////////////////////
/// @brief vocbase
////////////////////////////////////////////////////////////////////////////////
static TRI_vocbase_t* _vocbase;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new dispatcher thread
////////////////////////////////////////////////////////////////////////////////
ActionDisptacherThread (rest::DispatcherQueue* queue);
////////////////////////////////////////////////////////////////////////////////
/// @brief destructs a dispatcher thread
////////////////////////////////////////////////////////////////////////////////
~ActionDisptacherThread ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- DispatcherThread methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void reportStatus ();
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void tick ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- Thread methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void run ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises the isolate and context
////////////////////////////////////////////////////////////////////////////////
void initialise ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief report required
////////////////////////////////////////////////////////////////////////////////
bool _report;
////////////////////////////////////////////////////////////////////////////////
/// @brief isolate
////////////////////////////////////////////////////////////////////////////////
v8::Isolate* _isolate;
////////////////////////////////////////////////////////////////////////////////
/// @brief context
////////////////////////////////////////////////////////////////////////////////
v8::Persistent<v8::Context> _context;
};
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -0,0 +1,61 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief avocado http server
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "AvocadoHttpServer.h"
using namespace triagens::rest;
using namespace triagens::avocado;
// -----------------------------------------------------------------------------
// --SECTION-- class AvocadoHttpServer
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new http server
////////////////////////////////////////////////////////////////////////////////
AvocadoHttpServer::AvocadoHttpServer (Scheduler* scheduler, Dispatcher* dispatcher)
: HttpServerImpl(scheduler, dispatcher) {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -0,0 +1,84 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief avocado http server
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_AVOCADODB_RESTHANDLER_REST_ACTION_HANDLER3_H
#define TRIAGENS_AVOCADODB_RESTHANDLER_REST_ACTION_HANDLER3_H 1
#include "HttpServer/HttpServerImpl.h"
// -----------------------------------------------------------------------------
// --SECTION-- class AvocadoHttpServer
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace triagens {
namespace avocado {
////////////////////////////////////////////////////////////////////////////////
/// @brief specialized http server
////////////////////////////////////////////////////////////////////////////////
class AvocadoHttpServer : public rest::HttpServerImpl {
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new http server
////////////////////////////////////////////////////////////////////////////////
AvocadoHttpServer (rest::Scheduler* scheduler, rest::Dispatcher* dispatcher);
};
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -0,0 +1,540 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief avocado server
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "AvocadoServer.h"
#include <v8.h>
#include "build.h"
#include <Basics/Logger.h>
#include <Basics/ProgramOptions.h>
#include <Basics/ProgramOptionsDescription.h>
#include <Basics/files.h>
#include <Basics/init.h>
#include <Basics/logging.h>
#include <Basics/safe_cast.h>
#include <Basics/strings.h>
#include <Rest/ApplicationServerDispatcher.h>
#include <Rest/HttpHandlerFactory.h>
#include <Rest/Initialise.h>
#include "Dispatcher/DispatcherImpl.h"
#include <Admin/RestHandlerCreator.h>
#include "RestHandler/RestActionHandler.h"
#include "RestHandler/RestDocumentHandler.h"
#include "RestServer/ActionDispatcherThread.h"
#include "RestServer/AvocadoHttpServer.h"
#include "RestServer/JSLoader.h"
#include "V8/v8-actions.h"
#include "V8/v8-globals.h"
#include "V8/v8-shell.h"
#include "V8/v8-utils.h"
#include "V8/v8-vocbase.h"
using namespace std;
using namespace triagens::basics;
using namespace triagens::rest;
using namespace triagens::admin;
using namespace triagens::avocado;
#include "RestServer/js-actions.h"
#include "RestServer/js-json.h"
#include "RestServer/js-shell.h"
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief startup loader
////////////////////////////////////////////////////////////////////////////////
static JSLoader StartupLoader;
////////////////////////////////////////////////////////////////////////////////
/// @brief action loader
////////////////////////////////////////////////////////////////////////////////
static JSLoader ActionLoader;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief action dispatcher thread creator
////////////////////////////////////////////////////////////////////////////////
static DispatcherThread* ActionDisptacherThreadCreator (DispatcherQueue* queue) {
return new ActionDisptacherThread(queue);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- class AvocadoServer
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief UnviversalVoc constructor
////////////////////////////////////////////////////////////////////////////////
AvocadoServer::AvocadoServer (int argc, char** argv)
: _argc(argc),
_argv(argv),
_applicationAdminServer(0),
_applicationHttpServer(0),
_httpServer(0),
_httpPort("localhost:8529"),
_dispatcherThreads(1),
_startupPath(),
_actionPath(),
_actionThreads(1),
_databasePath("/var/lib/avocado"),
_vocbase(0) {
_workingDirectory = "/var/tmp";
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- AnyServer methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void AvocadoServer::buildApplicationServer () {
_applicationServer = ApplicationServerDispatcher::create("[<options>] - starts the triAGENS AvocadoDB", TRIAGENS_VERSION);
_applicationServer->setSystemConfigFile("avocado.conf");
_applicationServer->setUserConfigFile(".avocado/avocado.conf");
// .............................................................................
// allow multi-threading scheduler
// .............................................................................
_applicationServer->allowMultiScheduler(true);
// .............................................................................
// and start a simple admin server
// .............................................................................
_applicationAdminServer = ApplicationAdminServer::create(_applicationServer);
_applicationServer->addFeature(_applicationAdminServer);
_applicationAdminServer->allowLogViewer();
_applicationAdminServer->allowVersion("avocado", TRIAGENS_VERSION);
// .............................................................................
// a http server
// .............................................................................
_applicationHttpServer = ApplicationHttpServer::create(_applicationServer);
_applicationServer->addFeature(_applicationHttpServer);
// .............................................................................
// daemon and supervisor mode
// .............................................................................
map<string, ProgramOptionsDescription> additional;
additional[ApplicationServer::OPTIONS_CMDLINE]
("shell", "do not start as server, start in shell mode instead")
("daemon", "run as daemon")
("supervisor", "starts a supervisor and runs as daemon")
("pid-file", &_pidFile, "pid-file in daemon mode")
;
// .............................................................................
// for this server we display our own options such as port to use
// .............................................................................
_applicationHttpServer->showPortOptions(false);
additional["PORT Options"]
("server.http-port", &_httpPort, "port for client access")
("dispatcher.threads", &_dispatcherThreads, "number of dispatcher threads")
;
// .............................................................................
// database options
// .............................................................................
additional["DATABASE Options"]
("database.directory", &_databasePath, "path to the database directory")
;
// .............................................................................
// JavaScript options
// .............................................................................
additional["JAVASCRIPT Options"]
("startup.directory", &_startupPath, "path to the directory containing the startup scripts")
("action.directory", &_actionPath, "path to the action directory, defaults to <database.directory>/_ACTIONS")
("action.threads", &_actionThreads, "threads for actions")
;
// .............................................................................
// parse the command line options - exit if there is a parse error
// .............................................................................
if (! _applicationServer->parse(_argc, _argv, additional)) {
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
// .............................................................................
// set directories and scripts
// .............................................................................
if (_startupPath.empty()) {
StartupLoader.defineScript("json.js", JS_json);
StartupLoader.defineScript("shell.js", JS_shell);
StartupLoader.defineScript("actions.js", JS_actions);
}
else {
StartupLoader.setDirectory(_startupPath);
}
if (_actionPath.empty()) {
string path = TRI_Concatenate2File(_databasePath.c_str(), "_ACTIONS");
if (! TRI_IsDirectory(path.c_str())) {
bool ok = TRI_ExistsFile(path.c_str());
if (ok) {
LOGGER_FATAL << "action directory '" << path << "' must be a directory";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
ok = TRI_CreateDirectory(path.c_str());
if (! ok) {
LOGGER_FATAL << "cannot create action directory '" << path << "': " << TRI_last_error();
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
}
ActionLoader.setDirectory(path);
}
else {
ActionLoader.setDirectory(_actionPath);
}
// .............................................................................
// in shell mode ignore the rest
// .............................................................................
if (_applicationServer->programOptions().has("shell")) {
executeShell();
exit(EXIT_SUCCESS);
}
// .............................................................................
// sanity checks
// .............................................................................
if (_applicationServer->programOptions().has("daemon")) {
_daemonMode = true;
}
if (_applicationServer->programOptions().has("supervisor")) {
_supervisorMode = true;
}
if (_daemonMode) {
if (_pidFile.empty()) {
LOGGER_FATAL << "no pid-file defined, but daemon mode requested";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
}
if (_databasePath.empty()) {
LOGGER_FATAL << "no database path has been supplied, giving up";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
int AvocadoServer::startupServer () {
v8::HandleScope handle_scope;
// .............................................................................
// open the database
// .............................................................................
openDatabase();
// .............................................................................
// create the action dispatcher thread infor
// .............................................................................
ActionDisptacherThread::_actionLoader = &ActionLoader;
ActionDisptacherThread::_startupLoader = &StartupLoader;
ActionDisptacherThread::_vocbase = _vocbase;
// .............................................................................
// create the various parts of the universalVoc server
// .............................................................................
_applicationServer->buildScheduler();
_applicationServer->buildSchedulerReporter();
_applicationServer->buildControlCHandler();
safe_cast<ApplicationServerDispatcher*>(_applicationServer)->buildDispatcher();
safe_cast<ApplicationServerDispatcher*>(_applicationServer)->buildDispatcherReporter();
safe_cast<ApplicationServerDispatcher*>(_applicationServer)->buildStandardQueue(_dispatcherThreads);
Dispatcher* dispatcher = safe_cast<ApplicationServerDispatcher*>(_applicationServer)->dispatcher();
if (_actionThreads < 1) {
_actionThreads = 1;
}
safe_cast<DispatcherImpl*>(dispatcher)->addQueue("ACTION", ActionDisptacherThreadCreator, _actionThreads);
// .............................................................................
// create a http server and http handler factory
// .............................................................................
HttpHandlerFactory* factory = new HttpHandlerFactory();
vector<AddressPort> ports;
ports.push_back(AddressPort(_httpPort));
_applicationAdminServer->addBasicHandlers(factory);
factory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator<RestDocumentHandler>::createData<TRI_vocbase_t*>, _vocbase);
factory->addPrefixHandler(RestVocbaseBaseHandler::ACTION_PATH, RestHandlerCreator<RestActionHandler>::createData<TRI_vocbase_t*>, _vocbase);
Scheduler* scheduler = _applicationServer->scheduler();
_httpServer = _applicationHttpServer->buildServer(new AvocadoHttpServer(scheduler, dispatcher), factory, ports);
// .............................................................................
// start the main event loop
// .............................................................................
_applicationServer->start();
_applicationServer->wait();
// .............................................................................
// and cleanup
// .............................................................................
closeDatabase();
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the shell
////////////////////////////////////////////////////////////////////////////////
void AvocadoServer::executeShell () {
v8::Isolate* isolate;
v8::Persistent<v8::Context> context;
bool ok;
char const* files[] = { "shell.js", "json.js" };
size_t i;
// only simple logging
TRI_ShutdownLogging();
TRI_InitialiseLogging(false);
TRI_CreateLogAppenderFile("+");
// open the database
openDatabase();
// enter a new isolate
isolate = v8::Isolate::New();
isolate->Enter();
// global scope
v8::HandleScope globalScope;
// create the context
context = v8::Context::New(0);
if (context.IsEmpty()) {
LOGGER_FATAL << "cannot initialize V8 engine";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
context->Enter();
TRI_InitV8VocBridge(context, _vocbase);
TRI_InitV8Utils(context);
TRI_InitV8Shell(context);
// load all init files
for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i) {
ok = StartupLoader.loadScript(context, files[i]);
if (ok) {
LOGGER_TRACE << "loaded json file '" << files[i] << "'";
}
else {
LOGGER_FATAL << "cannot load json file '" << files[i] << "'";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
}
// run the shell
printf("AvocadoDB shell [V8 version %s, DB version %s]\n", v8::V8::GetVersion(), TRIAGENS_VERSION);
v8::Context::Scope contextScope(context);
v8::Local<v8::String> name(v8::String::New("(avocado)"));
V8LineEditor* console = new V8LineEditor();
console->open();
while (true) {
while(! v8::V8::IdleNotification()) {
}
char* input = console->prompt("avocado> ");
if (input == 0) {
break;
}
if (*input == '\0') {
TRI_FreeString(input);
continue;
}
console->addHistory(input);
v8::HandleScope scope;
TRI_ExecuteStringVocBase(context, v8::String::New(input), name, true, true);
TRI_FreeString(input);
}
// and return from the context and isolate
context->Exit();
isolate->Exit();
// close the database
closeDatabase();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief opens the database
////////////////////////////////////////////////////////////////////////////////
void AvocadoServer::openDatabase () {
_vocbase = TRI_OpenVocBase(_databasePath.c_str());
if (_vocbase == 0) {
LOGGER_FATAL << "cannot open database '" << _databasePath << "'";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief closes the database
////////////////////////////////////////////////////////////////////////////////
void AvocadoServer::closeDatabase () {
TRI_CloseVocBase(_vocbase);
_vocbase = 0;
LOGGER_INFO << "AvocadoDB has been shut down";
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

243
RestServer/AvocadoServer.h Normal file
View File

@ -0,0 +1,243 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief avocado server
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_AVOCADODB_RESTHANDLER_REST_ACTION_HANDLER45_H
#define TRIAGENS_AVOCADODB_RESTHANDLER_REST_ACTION_HANDLER45_H 1
#include <Rest/AnyServer.h>
#include <Admin/ApplicationAdminServer.h>
#include <Rest/ApplicationHttpServer.h>
#include <VocBase/vocbase.h>
// -----------------------------------------------------------------------------
// --SECTION-- class AvocadoServer
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace triagens {
namespace avocado {
////////////////////////////////////////////////////////////////////////////////
/// @brief AvocadoDB server
////////////////////////////////////////////////////////////////////////////////
class AvocadoServer : public rest::AnyServer {
private:
AvocadoServer (const AvocadoServer&);
AvocadoServer& operator= (const AvocadoServer&);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief UnviversalVoc constructor
////////////////////////////////////////////////////////////////////////////////
AvocadoServer (int argc, char** argv);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- AnyServer methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void buildApplicationServer ();
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
int startupServer ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the shell
////////////////////////////////////////////////////////////////////////////////
void executeShell ();
////////////////////////////////////////////////////////////////////////////////
/// @brief opens the database
////////////////////////////////////////////////////////////////////////////////
void openDatabase ();
////////////////////////////////////////////////////////////////////////////////
/// @brief closes the database
////////////////////////////////////////////////////////////////////////////////
void closeDatabase ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief number of command line arguments
////////////////////////////////////////////////////////////////////////////////
int _argc;
////////////////////////////////////////////////////////////////////////////////
/// @brief command line arguments
////////////////////////////////////////////////////////////////////////////////
char** _argv;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructed admin server application
////////////////////////////////////////////////////////////////////////////////
admin::ApplicationAdminServer* _applicationAdminServer;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructed http server application
////////////////////////////////////////////////////////////////////////////////
rest::ApplicationHttpServer* _applicationHttpServer;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructed http server
////////////////////////////////////////////////////////////////////////////////
rest::HttpServer* _httpServer;
////////////////////////////////////////////////////////////////////////////////
/// @brief list port for client requests
////////////////////////////////////////////////////////////////////////////////
string _httpPort;
////////////////////////////////////////////////////////////////////////////////
/// @brief number of dispatcher threads
////////////////////////////////////////////////////////////////////////////////
int _dispatcherThreads;
////////////////////////////////////////////////////////////////////////////////
/// @brief path to the directory containing the startup scripts
////////////////////////////////////////////////////////////////////////////////
string _startupPath;
////////////////////////////////////////////////////////////////////////////////
/// @brief path to the action directory
////////////////////////////////////////////////////////////////////////////////
string _actionPath;
////////////////////////////////////////////////////////////////////////////////
/// @brief number of action threads
////////////////////////////////////////////////////////////////////////////////
int _actionThreads;
////////////////////////////////////////////////////////////////////////////////
/// @brief path to the database
///
/// @CMDOPT{--database.directory @CA{directory}}
///
/// The directory containing the collections and data-files. Defaults
/// to @CODE{/var/lib/avocado}.
////////////////////////////////////////////////////////////////////////////////
string _databasePath;
////////////////////////////////////////////////////////////////////////////////
/// @brief vocbase
////////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* _vocbase;
};
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

168
RestServer/JSLoader.cpp Normal file
View File

@ -0,0 +1,168 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief source code loader
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "JSLoader.h"
#include <Basics/MutexLocker.h>
#include <Basics/Logger.h>
#include <Basics/files.h>
#include <Basics/strings.h>
#include "V8/v8-utils.h"
using namespace std;
using namespace triagens::basics;
using namespace triagens::avocado;
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a loader
////////////////////////////////////////////////////////////////////////////////
JSLoader::JSLoader ()
: _scripts(),
_directory(),
_lock() {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief sets the directory for scripts
////////////////////////////////////////////////////////////////////////////////
void JSLoader::setDirectory (string const& directory) {
MUTEX_LOCKER(_lock);
_directory = directory;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief defines a new named script
////////////////////////////////////////////////////////////////////////////////
void JSLoader::defineScript (string const& name, string const& script) {
MUTEX_LOCKER(_lock);
_scripts[name] = script;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief finds a named script
////////////////////////////////////////////////////////////////////////////////
string const& JSLoader::findScript (string const& name) {
MUTEX_LOCKER(_lock);
static string empty = "";
map<string, string>::iterator i = _scripts.find(name);
if (i != _scripts.end()) {
return i->second;
}
if (! _directory.empty()) {
char* filename = TRI_Concatenate2File(_directory.c_str(), name.c_str());
char* result = TRI_SlurpFile(filename);
if (result == 0) {
LOGGER_ERROR << "cannot load file '" << filename << "': " << TRI_last_error();
}
TRI_FreeString(filename);
if (result != 0) {
_scripts[name] = result;
TRI_FreeString(result);
return _scripts[name];
}
}
return empty;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief loads a named script
////////////////////////////////////////////////////////////////////////////////
bool JSLoader::loadScript (v8::Persistent<v8::Context> context, string const& name) {
v8::HandleScope scope;
findScript(name);
map<string, string>::iterator i = _scripts.find(name);
if (i == _scripts.end()) {
return false;
}
return TRI_ExecuteStringVocBase(context,
v8::String::New(i->second.c_str()),
v8::String::New(name.c_str()),
false,
true);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief loads all scripts
////////////////////////////////////////////////////////////////////////////////
bool JSLoader::loadAllScripts (v8::Persistent<v8::Context> context) {
if (_directory.empty()) {
return true;
}
return TRI_LoadJavaScriptDirectory(context, _directory.c_str());
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

166
RestServer/JSLoader.h Normal file
View File

@ -0,0 +1,166 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief source code loader
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2010-2011 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. Frank Celler
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_AVOCADODB_RESTHANDLER_REST_ACTION_HANDLER37_H
#define TRIAGENS_AVOCADODB_RESTHANDLER_REST_ACTION_HANDLER37_H 1
#include <Basics/Common.h>
#include <v8.h>
#include <Basics/Mutex.h>
// -----------------------------------------------------------------------------
// --SECTION-- class JSLoader
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace triagens {
namespace avocado {
////////////////////////////////////////////////////////////////////////////////
/// @brief JavaScript source code loader
////////////////////////////////////////////////////////////////////////////////
class JSLoader {
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a loader
////////////////////////////////////////////////////////////////////////////////
JSLoader ();
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief sets the directory for scripts
////////////////////////////////////////////////////////////////////////////////
void setDirectory (string const& directory);
////////////////////////////////////////////////////////////////////////////////
/// @brief defines a new named script
////////////////////////////////////////////////////////////////////////////////
void defineScript (string const& name, string const& script);
////////////////////////////////////////////////////////////////////////////////
/// @brief finds a named script
////////////////////////////////////////////////////////////////////////////////
string const& findScript (string const& name);
////////////////////////////////////////////////////////////////////////////////
/// @brief loads a named script
////////////////////////////////////////////////////////////////////////////////
bool loadScript (v8::Persistent<v8::Context>, string const& name);
////////////////////////////////////////////////////////////////////////////////
/// @brief loads all scripts
////////////////////////////////////////////////////////////////////////////////
bool loadAllScripts (v8::Persistent<v8::Context>);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief all scripts
////////////////////////////////////////////////////////////////////////////////
std::map<string, string> _scripts;
////////////////////////////////////////////////////////////////////////////////
/// @brief script directory
////////////////////////////////////////////////////////////////////////////////
std::string _directory;
////////////////////////////////////////////////////////////////////////////////
/// @brief mutex for _scripts
////////////////////////////////////////////////////////////////////////////////
basics::Mutex _lock;
};
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\)"
// End:

View File

@ -27,47 +27,13 @@
#include <Basics/Common.h>
#include <v8.h>
#include "build.h"
#include <Basics/logging.h>
#include <Basics/Logger.h>
#include <Basics/ProgramOptions.h>
#include <Basics/ProgramOptionsDescription.h>
#include <Basics/files.h>
#include <Basics/init.h>
#include <Basics/safe_cast.h>
#include <Basics/strings.h>
#include <Rest/AnyServer.h>
#include <Rest/ApplicationHttpServer.h>
#include <Rest/ApplicationServerDispatcher.h>
#include <Rest/HttpHandlerFactory.h>
#include <Rest/Initialise.h>
#include <Admin/ApplicationAdminServer.h>
#include <Admin/RestHandlerCreator.h>
#include <VocBase/vocbase.h>
#include "RestHandler/RestActionHandler.h"
#include "RestHandler/RestDocumentHandler.h"
#include "HttpServer/HttpServerImpl.h"
#include "Dispatcher/DispatcherThread.h"
#include "Dispatcher/DispatcherImpl.h"
#include "V8/v8-actions.h"
#include "V8/v8-globals.h"
#include "V8/v8-shell.h"
#include "V8/v8-utils.h"
#include "V8/v8-vocbase.h"
#include "RestServer/AvocadoServer.h"
using namespace triagens;
using namespace triagens::basics;
using namespace triagens::rest;
using namespace triagens::admin;
using namespace triagens::avocado;
////////////////////////////////////////////////////////////////////////////////
@ -79,6 +45,12 @@ using namespace triagens::avocado;
///
/// The following main command-line options are available.
///
/// @copydetails triagens::avocado::AvocadoServer::_databasePath
///
/// @CMDOPT{--shell}
///
/// Opens a debug shell instead of starting the HTTP server.
///
/// @CMDOPT{--log.level @CA{level}}
///
/// Allows the user to choose the level of information which is logged by the
@ -87,898 +59,6 @@ using namespace triagens::avocado;
/// @ref CommandLineLogging "here".
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- class ActionDisptacherThread
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace {
////////////////////////////////////////////////////////////////////////////////
/// @brief dispatcher thread
////////////////////////////////////////////////////////////////////////////////
class ActionDisptacherThread : public DispatcherThread {
ActionDisptacherThread (ActionDisptacherThread const&);
ActionDisptacherThread& operator= (ActionDisptacherThread const&);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public static variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief action path
////////////////////////////////////////////////////////////////////////////////
static string _actionPath;
////////////////////////////////////////////////////////////////////////////////
/// @brief startup path
////////////////////////////////////////////////////////////////////////////////
static string _startupPath;
////////////////////////////////////////////////////////////////////////////////
/// @brief vocbase
////////////////////////////////////////////////////////////////////////////////
static TRI_vocbase_t* _vocbase;
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new dispatcher thread
////////////////////////////////////////////////////////////////////////////////
ActionDisptacherThread (DispatcherQueue* queue)
: DispatcherThread(queue),
_report(false),
_isolate(0),
_context() {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destructs a dispatcher thread
////////////////////////////////////////////////////////////////////////////////
~ActionDisptacherThread () {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- DispatcherThread methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void reportStatus () {
_report = true;
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void tick () {
while(!v8::V8::IdleNotification()) {
}
if (! _report || _isolate == 0) {
return;
}
_report = false;
TRI_v8_global_t* v8g = (TRI_v8_global_t*) _isolate->GetData();
if (v8g == 0) {
return;
}
LOGGER_DEBUG << "active queries: " << v8g->JSQueries.size();
LOGGER_DEBUG << "active result-sets: " << v8g->JSResultSets.size();
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- Thread methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void run () {
initialise();
_isolate->Enter();
_context->Enter();
DispatcherThread::run();
_context->Exit();
_context.Dispose();
_isolate->Exit();
_isolate->Dispose();
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief initialises the isolate and context
////////////////////////////////////////////////////////////////////////////////
void initialise () {
bool ok;
char* filename;
char const* files[] = { "json.js", "actions.js" };
size_t i;
// enter a new isolate
_isolate = v8::Isolate::New();
_isolate->Enter();
// create the context
_context = v8::Context::New(0);
if (_context.IsEmpty()) {
LOGGER_FATAL << "cannot initialize V8 engine";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
_context->Enter();
TRI_InitV8VocBridge(_context, _vocbase);
TRI_InitV8Actions(_context);
TRI_InitV8Utils(_context);
TRI_InitV8Shell(_context);
// load all init files
for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i) {
filename = TRI_Concatenate2File(_startupPath.c_str(), files[i]);
ok = TRI_LoadJavaScriptFile(_context, filename);
if (! ok) {
LOGGER_FATAL << "cannot load json utilities from file '" << filename << "'";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
TRI_FreeString(filename);
}
// load all actions
ok = TRI_LoadJavaScriptDirectory(_context, _actionPath.c_str());
if (! ok) {
LOGGER_FATAL << "cannot load actions from directory '" << filename << "'";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
// and return from the context
_context->Exit();
_isolate->Exit();
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief report required
////////////////////////////////////////////////////////////////////////////////
bool _report;
////////////////////////////////////////////////////////////////////////////////
/// @brief isolate
////////////////////////////////////////////////////////////////////////////////
v8::Isolate* _isolate;
////////////////////////////////////////////////////////////////////////////////
/// @brief context
////////////////////////////////////////////////////////////////////////////////
v8::Persistent<v8::Context> _context;
};
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public static variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief action path
////////////////////////////////////////////////////////////////////////////////
string ActionDisptacherThread::_actionPath;
////////////////////////////////////////////////////////////////////////////////
/// @brief startup path
////////////////////////////////////////////////////////////////////////////////
string ActionDisptacherThread::_startupPath;
////////////////////////////////////////////////////////////////////////////////
/// @brief vocbase
////////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* ActionDisptacherThread::_vocbase;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief action dispatcher thread creator
////////////////////////////////////////////////////////////////////////////////
static DispatcherThread* ActionDisptacherThreadCreator (DispatcherQueue* queue) {
return new ActionDisptacherThread(queue);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- class AvocadoHttpServer
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace {
////////////////////////////////////////////////////////////////////////////////
/// @brief specialized http server
////////////////////////////////////////////////////////////////////////////////
class AvocadoHttpServer : public HttpServerImpl {
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief constructs a new http server
////////////////////////////////////////////////////////////////////////////////
AvocadoHttpServer (Scheduler* scheduler, Dispatcher* dispatcher)
: HttpServerImpl(scheduler, dispatcher) {
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- GeneralServer methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void handleConnected (socket_t socket, ConnectionInfo& info) {
SocketTask* task
= new SpecificCommTask<AvocadoHttpServer, HttpHandlerFactory, HttpCommTask>(
this,
socket,
info);
_scheduler->registerTask(task);
}
};
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- class AvocadoDB
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
namespace {
////////////////////////////////////////////////////////////////////////////////
/// @brief AvocadoDB server
////////////////////////////////////////////////////////////////////////////////
class AvocadoDB : public AnyServer {
private:
AvocadoDB (const AvocadoDB&);
AvocadoDB& operator= (const AvocadoDB&);
public:
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief UnviversalVoc constructor
////////////////////////////////////////////////////////////////////////////////
AvocadoDB (int argc, char** argv)
: _argc(argc),
_argv(argv),
_applicationAdminServer(0),
_applicationHttpServer(0),
_httpServer(0),
_httpPort("localhost:8529"),
_dispatcherThreads(1),
_startupPath("/usr/share/avocado/js"),
_actionPath("/usr/share/avocado/js/actions"),
_actionThreads(1),
_databasePath("/var/lib/avocado"),
_vocbase(0) {
_workingDirectory = "/var/tmp";
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- AnyServer methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
public:
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
void buildApplicationServer () {
_applicationServer = ApplicationServerDispatcher::create("[<options>] - starts the triAGENS AvocadoDB", TRIAGENS_VERSION);
_applicationServer->setSystemConfigFile("avocado.conf");
_applicationServer->setUserConfigFile(".avocado/avocado.conf");
// .............................................................................
// allow multi-threading scheduler
// .............................................................................
_applicationServer->allowMultiScheduler(true);
// .............................................................................
// and start a simple admin server
// .............................................................................
_applicationAdminServer = ApplicationAdminServer::create(_applicationServer);
_applicationServer->addFeature(_applicationAdminServer);
_applicationAdminServer->allowLogViewer();
_applicationAdminServer->allowVersion("avocado", TRIAGENS_VERSION);
// .............................................................................
// a http server
// .............................................................................
_applicationHttpServer = ApplicationHttpServer::create(_applicationServer);
_applicationServer->addFeature(_applicationHttpServer);
// .............................................................................
// daemon and supervisor mode
// .............................................................................
map<string, ProgramOptionsDescription> additional;
additional[ApplicationServer::OPTIONS_CMDLINE]
("shell", "do not start as server, start in shell mode instead")
("daemon", "run as daemon")
("supervisor", "starts a supervisor and runs as daemon")
("pid-file", &_pidFile, "pid-file in daemon mode")
;
// .............................................................................
// for this server we display our own options such as port to use
// .............................................................................
_applicationHttpServer->showPortOptions(false);
additional["PORT Options"]
("server.http-port", &_httpPort, "port for client access")
("dispatcher.threads", &_dispatcherThreads, "number of dispatcher threads")
;
// .............................................................................
// database options
// .............................................................................
additional["DATABASE Options"]
("database.path", &_databasePath, "path to the database directory")
;
// .............................................................................
// JavaScript options
// .............................................................................
additional["JAVASCRIPT Options"]
("startup.directory", &_startupPath, "path to the directory containing the startup scripts")
("action.directory", &_actionPath, "path to the action directory")
("action.threads", &_actionThreads, "threads for actions")
;
// .............................................................................
// parse the command line options - exit if there is a parse error
// .............................................................................
if (! _applicationServer->parse(_argc, _argv, additional)) {
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
// .............................................................................
// in shell mode ignore the rest
// .............................................................................
if (_applicationServer->programOptions().has("shell")) {
executeShell();
exit(EXIT_SUCCESS);
}
// .............................................................................
// sanity checks
// .............................................................................
if (_applicationServer->programOptions().has("daemon")) {
_daemonMode = true;
}
if (_applicationServer->programOptions().has("supervisor")) {
_supervisorMode = true;
}
if (_daemonMode) {
if (_pidFile.empty()) {
LOGGER_FATAL << "no pid-file defined, but daemon mode requested";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
}
if (_databasePath.empty()) {
LOGGER_FATAL << "no database path has been supplied, giving up";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// {@inheritDoc}
////////////////////////////////////////////////////////////////////////////////
int startupServer () {
v8::HandleScope handle_scope;
// .............................................................................
// open the database
// .............................................................................
openDatabase();
// .............................................................................
// create the action dispatcher thread infor
// .............................................................................
ActionDisptacherThread::_actionPath = _actionPath;
ActionDisptacherThread::_startupPath = _startupPath;
ActionDisptacherThread::_vocbase = _vocbase;
// .............................................................................
// create the various parts of the universalVoc server
// .............................................................................
_applicationServer->buildScheduler();
_applicationServer->buildSchedulerReporter();
_applicationServer->buildControlCHandler();
safe_cast<ApplicationServerDispatcher*>(_applicationServer)->buildDispatcher();
safe_cast<ApplicationServerDispatcher*>(_applicationServer)->buildDispatcherReporter();
safe_cast<ApplicationServerDispatcher*>(_applicationServer)->buildStandardQueue(_dispatcherThreads);
Dispatcher* dispatcher = safe_cast<ApplicationServerDispatcher*>(_applicationServer)->dispatcher();
if (_actionThreads < 1) {
_actionThreads = 1;
}
safe_cast<DispatcherImpl*>(dispatcher)->addQueue("ACTION", ActionDisptacherThreadCreator, _actionThreads);
// .............................................................................
// create a http server and http handler factory
// .............................................................................
HttpHandlerFactory* factory = new HttpHandlerFactory();
vector<AddressPort> ports;
ports.push_back(AddressPort(_httpPort));
_applicationAdminServer->addBasicHandlers(factory);
factory->addPrefixHandler(RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator<RestDocumentHandler>::createData<TRI_vocbase_t*>, _vocbase);
factory->addPrefixHandler(RestVocbaseBaseHandler::ACTION_PATH, RestHandlerCreator<RestActionHandler>::createData<TRI_vocbase_t*>, _vocbase);
Scheduler* scheduler = _applicationServer->scheduler();
_httpServer = _applicationHttpServer->buildServer(new AvocadoHttpServer(scheduler, dispatcher), factory, ports);
// .............................................................................
// start the main event loop
// .............................................................................
_applicationServer->start();
_applicationServer->wait();
// .............................................................................
// and cleanup
// .............................................................................
closeDatabase();
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief executes the shell
////////////////////////////////////////////////////////////////////////////////
void executeShell () {
v8::Isolate* isolate;
v8::Persistent<v8::Context> context;
bool ok;
char* filename;
char const* files[] = { "shell.js", "json.js" };
size_t i;
// open the database
openDatabase();
// enter a new isolate
isolate = v8::Isolate::New();
isolate->Enter();
// global scope
v8::HandleScope globalScope;
// create the context
context = v8::Context::New(0);
if (context.IsEmpty()) {
LOGGER_FATAL << "cannot initialize V8 engine";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
context->Enter();
TRI_InitV8VocBridge(context, _vocbase);
TRI_InitV8Utils(context);
TRI_InitV8Shell(context);
// load all init files
for (i = 0; i < sizeof(files) / sizeof(files[0]); ++i) {
filename = TRI_Concatenate2File(_startupPath.c_str(), files[i]);
ok = TRI_LoadJavaScriptFile(context, filename);
if (! ok) {
LOGGER_FATAL << "cannot load json utilities from file '" << filename << "'";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
TRI_FreeString(filename);
}
// run the shell
printf("AvocadoDB shell [V8 version %s, DB version %s]\n", v8::V8::GetVersion(), TRIAGENS_VERSION);
v8::Context::Scope contextScope(context);
v8::Local<v8::String> name(v8::String::New("(avocado)"));
V8LineEditor* console = new V8LineEditor();
console->open();
while (true) {
while(! v8::V8::IdleNotification()) {
}
char* input = console->prompt("avocado> ");
if (input == 0) {
break;
}
if (*input == '\0') {
TRI_FreeString(input);
continue;
}
console->addHistory(input);
v8::HandleScope scope;
TRI_ExecuteStringVocBase(context, v8::String::New(input), name, true, true);
TRI_FreeString(input);
}
// and return from the context and isolate
context->Exit();
isolate->Exit();
// close the database
closeDatabase();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief opens the database
////////////////////////////////////////////////////////////////////////////////
void openDatabase () {
_vocbase = TRI_OpenVocBase(_databasePath.c_str());
if (_vocbase == 0) {
LOGGER_FATAL << "cannot open database '" << _databasePath << "'";
TRIAGENS_REST_SHUTDOWN;
exit(EXIT_FAILURE);
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief closes the database
////////////////////////////////////////////////////////////////////////////////
void closeDatabase () {
TRI_CloseVocBase(_vocbase);
LOGGER_INFO << "AvocadoDB has been shut down";
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- private variables
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @addtogroup AvocadoDB
/// @{
////////////////////////////////////////////////////////////////////////////////
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief number of command line arguments
////////////////////////////////////////////////////////////////////////////////
int _argc;
////////////////////////////////////////////////////////////////////////////////
/// @brief command line arguments
////////////////////////////////////////////////////////////////////////////////
char** _argv;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructed admin server application
////////////////////////////////////////////////////////////////////////////////
ApplicationAdminServer* _applicationAdminServer;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructed http server application
////////////////////////////////////////////////////////////////////////////////
ApplicationHttpServer* _applicationHttpServer;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructed http server
////////////////////////////////////////////////////////////////////////////////
HttpServer* _httpServer;
////////////////////////////////////////////////////////////////////////////////
/// @brief list port for client requests
////////////////////////////////////////////////////////////////////////////////
string _httpPort;
////////////////////////////////////////////////////////////////////////////////
/// @brief number of dispatcher threads
////////////////////////////////////////////////////////////////////////////////
int _dispatcherThreads;
////////////////////////////////////////////////////////////////////////////////
/// @brief path to the directory containing the startup scripts
////////////////////////////////////////////////////////////////////////////////
string _startupPath;
////////////////////////////////////////////////////////////////////////////////
/// @brief path to the action directory
////////////////////////////////////////////////////////////////////////////////
string _actionPath;
////////////////////////////////////////////////////////////////////////////////
/// @brief number of action threads
////////////////////////////////////////////////////////////////////////////////
int _actionThreads;
////////////////////////////////////////////////////////////////////////////////
/// @brief path to the database
////////////////////////////////////////////////////////////////////////////////
string _databasePath;
////////////////////////////////////////////////////////////////////////////////
/// @brief vocbase
////////////////////////////////////////////////////////////////////////////////
TRI_vocbase_t* _vocbase;
};
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
@ -997,7 +77,7 @@ int main (int argc, char* argv[]) {
TRI_InitialiseVocBase();
// create and start a AvocadoDB server
AvocadoDB server(argc, argv);
AvocadoServer server(argc, argv);
int res = server.start();

130
RestServer/js-actions.h Normal file
View File

@ -0,0 +1,130 @@
string JS_actions =
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief JavaScript actions functions\n"
"///\n"
"/// @file\n"
"///\n"
"/// DISCLAIMER\n"
"///\n"
"/// Copyright by triAGENS GmbH - All rights reserved.\n"
"///\n"
"/// The Programs (which include both the software and documentation)\n"
"/// contain proprietary information of triAGENS GmbH; they are\n"
"/// provided under a license agreement containing restrictions on use and\n"
"/// disclosure and are also protected by copyright, patent and other\n"
"/// intellectual and industrial property laws. Reverse engineering,\n"
"/// disassembly or decompilation of the Programs, except to the extent\n"
"/// required to obtain interoperability with other independently created\n"
"/// software or as specified by law, is prohibited.\n"
"///\n"
"/// The Programs are not intended for use in any nuclear, aviation, mass\n"
"/// transit, medical, or other inherently dangerous applications. It shall\n"
"/// be the licensee's responsibility to take all appropriate fail-safe,\n"
"/// backup, redundancy, and other measures to ensure the safe use of such\n"
"/// applications if the Programs are used for such purposes, and triAGENS\n"
"/// GmbH disclaims liability for any damages caused by such use of\n"
"/// the Programs.\n"
"///\n"
"/// This software is the confidential and proprietary information of\n"
"/// triAGENS GmbH. You shall not disclose such confidential and\n"
"/// proprietary information and shall use it only in accordance with the\n"
"/// terms of the license agreement you entered into with triAGENS GmbH.\n"
"///\n"
"/// Copyright holder is triAGENS GmbH, Cologne, Germany\n"
"///\n"
"/// @author Dr. Frank Celler\n"
"/// @author Copyright 2011, triAGENS GmbH, Cologne, Germany\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// -----------------------------------------------------------------------------\n"
"// --SECTION-- actions output helper\n"
"// -----------------------------------------------------------------------------\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @addtogroup V8Json V8 JSON\n"
"/// @{\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief returns a result of a query as documents\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function queryResult (req, res, query) {\n"
" var result;\n"
" var offset = 0;\n"
" var page = 0;\n"
" var blocksize = 0;\n"
"\n"
" if (req.blocksize) {\n"
" blocksize = req.blocksize;\n"
"\n"
" if (req.page) {\n"
" page = req.page;\n"
" offset = page * blocksize;\n"
" query = query.skip(offset).limit(blocksize);\n"
" }\n"
" else {\n"
" query = query.limit(blocksize);\n"
" }\n"
" }\n"
"\n"
" result = {\n"
" total : query.count(),\n"
" count : query.count(true),\n"
" offset : offset,\n"
" blocksize : blocksize,\n"
" page : page,\n"
" documents : query.toArray()\n"
" };\n"
"\n"
" res.responseCode = 200;\n"
" res.contentType = \"application/json\";\n"
" res.body = toJson(result);\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief returns a result of a query as references\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"function queryReferences (req, res, query) {\n"
" var result;\n"
" var offset = 0;\n"
" var page = 0;\n"
" var blocksize = 0;\n"
"\n"
" if (req.blocksize) {\n"
" blocksize = req.blocksize;\n"
"\n"
" if (req.page) {\n"
" page = req.page;\n"
" offset = page * blocksize;\n"
" query = query.skip(offset).limit(blocksize);\n"
" }\n"
" else {\n"
" query = query.limit(blocksize);\n"
" }\n"
" }\n"
"\n"
" result = {\n"
" total : query.count(),\n"
" count : query.count(true),\n"
" offset : offset,\n"
" blocksize : blocksize,\n"
" page : page,\n"
" references : query.toArray().map(function(doc) { return doc._id; })\n"
" };\n"
"\n"
" res.responseCode = 200;\n"
" res.contentType = \"application/json\";\n"
" res.body = toJson(result);\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @}\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// Local Variables:\n"
"// mode: outline-minor\n"
"// outline-regexp: \"^\\\\(/// @brief\\\\|/// @addtogroup\\\\|// --SECTION--\\\\)\"\n"
"// End:\n"
;

209
RestServer/js-json.h Normal file
View File

@ -0,0 +1,209 @@
string JS_json =
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief JavaScript JSON utility functions\n"
"///\n"
"/// @file\n"
"///\n"
"/// DISCLAIMER\n"
"///\n"
"/// Copyright by triAGENS GmbH - All rights reserved.\n"
"///\n"
"/// The Programs (which include both the software and documentation)\n"
"/// contain proprietary information of triAGENS GmbH; they are\n"
"/// provided under a license agreement containing restrictions on use and\n"
"/// disclosure and are also protected by copyright, patent and other\n"
"/// intellectual and industrial property laws. Reverse engineering,\n"
"/// disassembly or decompilation of the Programs, except to the extent\n"
"/// required to obtain interoperability with other independently created\n"
"/// software or as specified by law, is prohibited.\n"
"///\n"
"/// The Programs are not intended for use in any nuclear, aviation, mass\n"
"/// transit, medical, or other inherently dangerous applications. It shall\n"
"/// be the licensee's responsibility to take all appropriate fail-safe,\n"
"/// backup, redundancy, and other measures to ensure the safe use of such\n"
"/// applications if the Programs are used for such purposes, and triAGENS\n"
"/// GmbH disclaims liability for any damages caused by such use of\n"
"/// the Programs.\n"
"///\n"
"/// This software is the confidential and proprietary information of\n"
"/// triAGENS GmbH. You shall not disclose such confidential and\n"
"/// proprietary information and shall use it only in accordance with the\n"
"/// terms of the license agreement you entered into with triAGENS GmbH.\n"
"///\n"
"/// Copyright holder is triAGENS GmbH, Cologne, Germany\n"
"///\n"
"/// @author Dr. Frank Celler\n"
"/// @author Copyright 2011, triAGENS GmbH, Cologne, Germany\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// -----------------------------------------------------------------------------\n"
"// --SECTION-- toJson\n"
"// -----------------------------------------------------------------------------\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @addtogroup V8Json V8 JSON\n"
"/// @{\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief JSON representation of an object\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"toJson = function(x, indent , useNL) {\n"
" if (x === null) {\n"
" return \"null\";\n"
" }\n"
" \n"
" if (x === undefined) {\n"
" return \"undefined\";\n"
" }\n"
"\n"
" if (useNL === undefined && (indent === true || indent === false)) {\n"
" useNL = indent;\n"
" indent = \"\";\n"
" }\n"
" \n"
" if (! indent) {\n"
" indent = \"\";\n"
" }\n"
"\n"
" if (x instanceof String || typeof x === \"string\") {\n"
" var s = \"\\\"\";\n"
"\n"
" for (var i = 0; i < x.length; i++){\n"
" switch (x[i]) {\n"
" case '\"': s += '\\\\\"'; break;\n"
" case '\\\\': s += '\\\\\\\\'; break;\n"
" case '\\b': s += '\\\\b'; break;\n"
" case '\\f': s += '\\\\f'; break;\n"
" case '\\n': s += '\\\\n'; break;\n"
" case '\\r': s += '\\\\r'; break;\n"
" case '\\t': s += '\\\\t'; break;\n"
"\n"
" default: {\n"
" var code = x.charCodeAt(i);\n"
"\n"
" if (code < 0x20) {\n"
" s += (code < 0x10 ? '\\\\u000' : '\\\\u00') + code.toString(16);\n"
" }\n"
" else {\n"
" s += x[i];\n"
" }\n"
" }\n"
" }\n"
" }\n"
"\n"
" return s + \"\\\"\";\n"
" }\n"
"\n"
" if (x instanceof Number || typeof x === \"number\") {\n"
" return \"\" + x;\n"
" }\n"
"\n"
" if (x instanceof Boolean || typeof x === \"boolean\") {\n"
" return \"\" + x;\n"
" }\n"
"\n"
" if (x instanceof Function) {\n"
" return x.toString();\n"
" }\n"
"\n"
" if (x instanceof Object) {\n"
" return toJsonObject(x, indent , useNL);\n"
" }\n"
"\n"
" return \"\" + x;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief JSON representation of an array\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"Array.toJson = function(a, indent, useNL) {\n"
" var nl = useNL ? \"\\n\" : \" \";\n"
"\n"
" if (! indent) {\n"
" indent = \"\";\n"
" }\n"
" \n"
" if (! useNL) {\n"
" indent = \"\";\n"
" }\n"
"\n"
" if (a.length == 0) {\n"
" return indent + \"[]\";\n"
" }\n"
"\n"
" var s = \"[\" + nl;\n"
" var oldIndent = indent;\n"
"\n"
" if (useNL) {\n"
" indent += \" \";\n"
" }\n"
"\n"
" for (var i = 0; i < a.length; i++) {\n"
" s += indent + toJson(a[i], indent , useNL);\n"
"\n"
" if (i < a.length - 1) {\n"
" s += \",\" + nl;\n"
" }\n"
" }\n"
"\n"
" s += nl + oldIndent + \"]\";\n"
"\n"
" return s;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief JSON representation of an object\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"toJsonObject = function(x, indent , useNL) {\n"
" var nl = useNL ? \"\\n\" : \" \";\n"
" \n"
" if (! indent) {\n"
" indent = \"\";\n"
" }\n"
" \n"
" if (typeof(x.toJson) == \"function\" && x.toJson != toJson) {\n"
" return indent + x.toJson(indent, useNL);\n"
" }\n"
" \n"
" if (x.constructor && typeof(x.constructor.toJson) == \"function\" && x.constructor.toJson != toJson) {\n"
" return x.constructor.toJson(x, indent , useNL);\n"
" }\n"
"\n"
" var s = \"{\" + nl;\n"
"\n"
" // push one level of indent\n"
" var oldIndent = indent;\n"
" indent += \" \";\n"
" \n"
" if (! useNL) {\n"
" indent = \"\";\n"
" }\n"
"\n"
" var sep = \"\";\n"
"\n"
" for (var k in x) {\n"
" var val = x[k];\n"
"\n"
" s += sep + indent + \"\\\"\" + k + \"\\\" : \" + toJson(val, indent , useNL);\n"
" sep = \",\" + nl;\n"
" }\n"
"\n"
" // pop one level of indent\n"
" indent = oldIndent;\n"
"\n"
" return s + nl + indent + \"}\";\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @}\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// Local Variables:\n"
"// mode: outline-minor\n"
"// outline-regexp: \"^\\\\(/// @brief\\\\|/// @addtogroup\\\\|// --SECTION--\\\\)\"\n"
"// End:\n"
;

257
RestServer/js-shell.h Normal file
View File

@ -0,0 +1,257 @@
string JS_shell =
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief JavaScript server functions\n"
"///\n"
"/// @file\n"
"///\n"
"/// DISCLAIMER\n"
"///\n"
"/// Copyright by triAGENS GmbH - All rights reserved.\n"
"///\n"
"/// The Programs (which include both the software and documentation)\n"
"/// contain proprietary information of triAGENS GmbH; they are\n"
"/// provided under a license agreement containing restrictions on use and\n"
"/// disclosure and are also protected by copyright, patent and other\n"
"/// intellectual and industrial property laws. Reverse engineering,\n"
"/// disassembly or decompilation of the Programs, except to the extent\n"
"/// required to obtain interoperability with other independently created\n"
"/// software or as specified by law, is prohibited.\n"
"///\n"
"/// The Programs are not intended for use in any nuclear, aviation, mass\n"
"/// transit, medical, or other inherently dangerous applications. It shall\n"
"/// be the licensee's responsibility to take all appropriate fail-safe,\n"
"/// backup, redundancy, and other measures to ensure the safe use of such\n"
"/// applications if the Programs are used for such purposes, and triAGENS\n"
"/// GmbH disclaims liability for any damages caused by such use of\n"
"/// the Programs.\n"
"///\n"
"/// This software is the confidential and proprietary information of\n"
"/// triAGENS GmbH. You shall not disclose such confidential and\n"
"/// proprietary information and shall use it only in accordance with the\n"
"/// terms of the license agreement you entered into with triAGENS GmbH.\n"
"///\n"
"/// Copyright holder is triAGENS GmbH, Cologne, Germany\n"
"///\n"
"/// @author Dr. Frank Celler\n"
"/// @author Copyright 2011, triAGENS GmbH, Cologne, Germany\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// -----------------------------------------------------------------------------\n"
"// --SECTION-- query evaluation\n"
"// -----------------------------------------------------------------------------\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @addtogroup V8Shell V8 Shell\n"
"/// @{\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief global variable holding the current printed query\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"var it = undefined;\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief number of results to print\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"var queryLimit = 20;\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief prints a query\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"AvocadoQuery.prototype.print = function(q) {\n"
" var count = 0;\n"
"\n"
" try {\n"
" while (q.hasNext() && count++ < queryLimit) {\n"
" output(toJson(q.next()), \"\\n\");\n"
" }\n"
"\n"
" if (q.hasNext()) {\n"
" output(\"...more results...\");\n"
" }\n"
"\n"
" it = q;\n"
" }\n"
" catch (e) {\n"
" output(\"encountered error while printing: \" + e);\n"
" }\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @}\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// -----------------------------------------------------------------------------\n"
"// --SECTION-- toJson\n"
"// -----------------------------------------------------------------------------\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @addtogroup V8Shell V8 Shell\n"
"/// @{\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief JSON representation of an object\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"toJson = function(x, indent , useNL) {\n"
" if (x === null) {\n"
" return \"null\";\n"
" }\n"
" \n"
" if (x === undefined) {\n"
" return \"undefined\";\n"
" }\n"
"\n"
" if (useNL === undefined && (indent === true || indent === false)) {\n"
" useNL = indent;\n"
" indent = \"\";\n"
" }\n"
" \n"
" if (! indent) {\n"
" indent = \"\";\n"
" }\n"
"\n"
" if (x instanceof String || typeof x === \"string\") {\n"
" var s = \"\\\"\";\n"
"\n"
" for (var i = 0; i < x.length; i++){\n"
" switch (x[i]) {\n"
" case '\"': s += '\\\\\"'; break;\n"
" case '\\\\': s += '\\\\\\\\'; break;\n"
" case '\\b': s += '\\\\b'; break;\n"
" case '\\f': s += '\\\\f'; break;\n"
" case '\\n': s += '\\\\n'; break;\n"
" case '\\r': s += '\\\\r'; break;\n"
" case '\\t': s += '\\\\t'; break;\n"
"\n"
" default: {\n"
" var code = x.charCodeAt(i);\n"
"\n"
" if (code < 0x20) {\n"
" s += (code < 0x10 ? '\\\\u000' : '\\\\u00') + code.toString(16);\n"
" }\n"
" else {\n"
" s += x[i];\n"
" }\n"
" }\n"
" }\n"
" }\n"
"\n"
" return s + \"\\\"\";\n"
" }\n"
"\n"
" if (x instanceof Number || typeof x === \"number\") {\n"
" return \"\" + x;\n"
" }\n"
"\n"
" if (x instanceof Boolean || typeof x === \"boolean\") {\n"
" return \"\" + x;\n"
" }\n"
"\n"
" if (x instanceof Function) {\n"
" return x.toString();\n"
" }\n"
"\n"
" if (x instanceof Object) {\n"
" return toJsonObject(x, indent , useNL);\n"
" }\n"
"\n"
" return \"\" + x;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief JSON representation of an array\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"Array.toJson = function(a, indent, useNL) {\n"
" var nl = useNL ? \"\\n\" : \" \";\n"
"\n"
" if (! indent) {\n"
" indent = \"\";\n"
" }\n"
" \n"
" if (! useNL) {\n"
" indent = \"\";\n"
" }\n"
"\n"
" if (a.length == 0) {\n"
" return indent + \"[]\";\n"
" }\n"
"\n"
" var s = \"[\" + nl;\n"
" var oldIndent = indent;\n"
"\n"
" if (useNL) {\n"
" indent += \" \";\n"
" }\n"
"\n"
" for (var i = 0; i < a.length; i++) {\n"
" s += indent + toJson(a[i], indent , useNL);\n"
"\n"
" if (i < a.length - 1) {\n"
" s += \",\" + nl;\n"
" }\n"
" }\n"
"\n"
" s += nl + oldIndent + \"]\";\n"
"\n"
" return s;\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @brief JSON representation of an object\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"toJsonObject = function(x, indent , useNL) {\n"
" var nl = useNL ? \"\\n\" : \" \";\n"
" \n"
" if (! indent) {\n"
" indent = \"\";\n"
" }\n"
" \n"
" if (typeof(x.toJson) == \"function\" && x.toJson != toJson) {\n"
" return indent + x.toJson(indent, useNL);\n"
" }\n"
" \n"
" if (x.constructor && typeof(x.constructor.toJson) == \"function\" && x.constructor.toJson != toJson) {\n"
" return x.constructor.toJson(x, indent , useNL);\n"
" }\n"
"\n"
" var s = \"{\" + nl;\n"
"\n"
" // push one level of indent\n"
" var oldIndent = indent;\n"
" indent += \" \";\n"
" \n"
" if (! useNL) {\n"
" indent = \"\";\n"
" }\n"
"\n"
" var sep = \"\";\n"
"\n"
" for (var k in x) {\n"
" var val = x[k];\n"
"\n"
" s += sep + indent + \"\\\"\" + k + \"\\\" : \" + toJson(val, indent , useNL);\n"
" sep = \",\" + nl;\n"
" }\n"
"\n"
" // pop one level of indent\n"
" indent = oldIndent;\n"
"\n"
" return s + nl + indent + \"}\";\n"
"}\n"
"\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"/// @}\n"
"////////////////////////////////////////////////////////////////////////////////\n"
"\n"
"// Local Variables:\n"
"// mode: outline-minor\n"
"// outline-regexp: \"^\\\\(/// @brief\\\\|/// @addtogroup\\\\|// --SECTION--\\\\)\"\n"
"// End:\n"
;

View File

@ -94,10 +94,7 @@ namespace triagens {
else {
// put the register request unto the queue
if (! queueLock.lock()) {
LOGGER_FATAL << "cannot lock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.lock();
Work w(SETUP, scheduler, task);
queue.push_back(w);
@ -105,10 +102,7 @@ namespace triagens {
scheduler->wakeupLoop(loop);
if (! queueLock.unlock()) {
LOGGER_FATAL << "cannot unlock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.unlock();
}
}
@ -127,10 +121,7 @@ namespace triagens {
else {
// put the unregister request unto the queue
if (! queueLock.lock()) {
LOGGER_FATAL << "cannot lock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.lock();
Work w(CLEANUP, 0, task);
queue.push_back(w);
@ -138,10 +129,7 @@ namespace triagens {
scheduler->wakeupLoop(loop);
if (! queueLock.unlock()) {
LOGGER_FATAL << "cannot unlock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.unlock();
}
}
@ -161,10 +149,7 @@ namespace triagens {
else {
// put the unregister request unto the queue
if (! queueLock.lock()) {
LOGGER_FATAL << "cannot lock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.lock();
Work w(DESTROY, 0, task);
queue.push_back(w);
@ -172,10 +157,7 @@ namespace triagens {
scheduler->wakeupLoop(loop);
if (! queueLock.unlock()) {
LOGGER_FATAL << "cannot unlock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.unlock();
}
}
@ -213,19 +195,13 @@ namespace triagens {
#endif
if (hasWork != 0) {
if (! queueLock.lock()) {
LOGGER_FATAL << "cannot lock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.lock();
while (! queue.empty()) {
Work w = queue.front();
queue.pop_front();
if (! queueLock.unlock()) {
LOGGER_FATAL << "cannot unlock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.unlock();
switch (w.work) {
case CLEANUP:
@ -242,18 +218,12 @@ namespace triagens {
break;
}
if (! queueLock.lock()) {
LOGGER_FATAL << "cannot lock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.lock();
}
hasWork = 0;
if (! queueLock.unlock()) {
LOGGER_FATAL << "cannot unlock in " << __FILE__ << "@" << __LINE__;
exit(EXIT_FAILURE);
}
queueLock.unlock();
}
}

View File

@ -936,7 +936,7 @@ static TRI_json_t* JsonShapeDataShortString (TRI_shaper_t* shaper,
l = * (TRI_shape_length_short_string_t const*) data;
data += sizeof(TRI_shape_length_short_string_t);
return TRI_CreateString2CopyJson(data, l);
return TRI_CreateString2CopyJson(data, l - 1);
}
////////////////////////////////////////////////////////////////////////////////
@ -952,7 +952,7 @@ static TRI_json_t* JsonShapeDataLongString (TRI_shaper_t* shaper,
l = * (TRI_shape_length_long_string_t const*) data;
data += sizeof(TRI_shape_length_long_string_t);
return TRI_CreateString2CopyJson(data, l);
return TRI_CreateString2CopyJson(data, l - 1);
}
////////////////////////////////////////////////////////////////////////////////
@ -1340,7 +1340,7 @@ static bool StringifyJsonShapeDataShortString (TRI_shaper_t* shaper,
data += sizeof(TRI_shape_length_short_string_t);
TRI_AppendCharStringBuffer(buffer, '"');
TRI_AppendString2StringBuffer(buffer, data, l);
TRI_AppendString2StringBuffer(buffer, data, l - 1);
TRI_AppendCharStringBuffer(buffer, '"');
return true;
@ -1361,7 +1361,7 @@ static bool StringifyJsonShapeDataLongString (TRI_shaper_t* shaper,
data += sizeof(TRI_shape_length_long_string_t);
TRI_AppendCharStringBuffer(buffer, '"');
TRI_AppendString2StringBuffer(buffer, data, l);
TRI_AppendString2StringBuffer(buffer, data, l - 1);
TRI_AppendCharStringBuffer(buffer, '"');
return true;

View File

@ -34,6 +34,73 @@
#include <VocBase/vocbase.h>
////////////////////////////////////////////////////////////////////////////////
/// @page Actions Actions
///
/// Actions are small JavaScript functions which are used to compute the result
/// of a request. Normally, the function will use the request parameter @a
/// collection to locate a collection, compute the result and return this result
/// as JSON object.
///
/// An action is defined using the function @c defineAction. You need to provide
/// a path, a function, and a description of the parameters.
///
/// @verbinclude action1
///
/// This will define a new action accessible under @c /_action/pagination, with
/// three parameters @a collection, @a blocksize, and @a page. The action
/// function is called with two parameters @a req and @a res. The variable @a
/// req contains the request parameters. The result is stored in the variable @a
/// res.
///
/// The function @c queryResult is predefined. It expects three parameters, the
/// request, the response, and a result set. The function @c queryResult uses
/// the parameters @a blocksize and @a page to paginate the result.
///
/// @verbinclude action2
///
/// The result contains the @a total number of documents, the number of
/// documents returned in @a count, the @a offset, the @a blocksize, the current
/// @a page, and the @a documents.
///
/// There is an alternative function @c queryReferences, which will only return
/// the document references, not the whole document.
///
/// @verbinclude action3
///
/// You can then use the rest interface to extract the documents.
///
/// @verbinclude action4
///
/// Next steps:
///
/// - learn about @ref ActionsQueryBuilding "query building functions"
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @page ActionsQueryBuilding Query Building Functions for Actions
///
/// The following functions can be used to build the result-set.
///
/// @copydetails JS_AllQuery
///
/// @copydetails JS_DistanceQuery
///
/// @copydetails JS_DocumentQuery
///
/// @copydetails JS_GeoQuery
///
/// @copydetails JS_LimitQuery
///
/// @copydetails JS_NearQuery
///
/// @copydetails JS_SelectQuery
///
/// @copydetails JS_SkipQuery
///
/// @copydetails JS_WithinQuery
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
// --SECTION-- forward declarations
// -----------------------------------------------------------------------------

View File

@ -31,6 +31,8 @@
#include <Basics/Common.h>
#include <regex.h>
#include <map>
#include <v8.h>
#include <Basics/ReadWriteLock.h>
@ -64,7 +66,8 @@ typedef struct TRI_v8_global_s {
VocbaseColTempl(),
VocbaseTempl(),
OutputFuncName(),
PrintQueryFuncName(),
PrintFuncName(),
ToJsonFuncName(),
ToStringFuncName(),
CollectionQueryType(),
ContentType(),
@ -136,10 +139,16 @@ typedef struct TRI_v8_global_s {
v8::Persistent<v8::String> OutputFuncName;
////////////////////////////////////////////////////////////////////////////////
/// @brief "printQuery" function name
/// @brief "print" function name
////////////////////////////////////////////////////////////////////////////////
v8::Persistent<v8::String> PrintQueryFuncName;
v8::Persistent<v8::String> PrintFuncName;
////////////////////////////////////////////////////////////////////////////////
/// @brief "toJson" function name
////////////////////////////////////////////////////////////////////////////////
v8::Persistent<v8::String> ToJsonFuncName;
////////////////////////////////////////////////////////////////////////////////
/// @brief "toString" function name

View File

@ -40,6 +40,7 @@
#include <fstream>
#include "V8/v8-json.h"
#include "V8/v8-globals.h"
#include "V8/v8-utils.h"
using namespace std;
@ -108,6 +109,26 @@ static void ProcessCsvEnd (TRI_csv_parser_t* parser, char const* field, size_t r
////////////////////////////////////////////////////////////////////////////////
/// @brief processes a CSV file
///
/// @FUN{processCsvFile(@FA{filename}, @FA{callback})}
///
/// Processes a CSV file. The @FA{callback} function is called for line in the
/// file. The seperator is @CODE{\,} and the quote is @CODE{"}.
///
/// Create the input file @CODE{csv.txt}
///
/// @verbinclude fluent48
///
/// If you use @FN{processCsvFile} on this file, you get
///
/// @verbinclude fluent47
///
/// @FUN{processCsvFile(@FA{filename}, @FA{callback}, @FA{options})}
///
/// Processes a CSV file. The @FA{callback} function is called for line in the
/// file. The @FA{options} argument must be an object. The value of
/// @CODE{seperator} sets the seperator character and @CODE{quote} the quote
/// character.
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_ProcessCsvFile (v8::Arguments const& argv) {
@ -203,6 +224,20 @@ static v8::Handle<v8::Value> JS_ProcessCsvFile (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
/// @brief processes a JSON file
///
/// @FUN{processJsonFile(@FA{filename}, @FA{callback})}
///
/// Processes a JSON file. The file must contain the JSON objects each on its
/// own line. The @FA{callback} function is called for each object.
///
/// Create the input file @CODE{json.txt}
///
/// @verbinclude fluent49
///
/// If you use @FN{processJsonFile} on this file, you get
///
/// @verbinclude fluent50
///
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_ProcessJsonFile (v8::Arguments const& argv) {
@ -378,8 +413,13 @@ static v8::Handle<v8::Value> JS_Output (v8::Arguments const& argv) {
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_Print (v8::Arguments const& argv) {
TRI_v8_global_t* v8g;
v8::HandleScope globalScope;
v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8::Handle<v8::Function> toJson = v8::Handle<v8::Function>::Cast(
argv.Holder()->CreationContext()->Global()->Get(v8::String::New("toJson")));
argv.Holder()->CreationContext()->Global()->Get(v8g->ToJsonFuncName));
for (int i = 0; i < argv.Length(); i++) {
v8::HandleScope scope;
@ -394,10 +434,9 @@ static v8::Handle<v8::Value> JS_Print (v8::Arguments const& argv) {
// convert the object into json - if possible
if (val->IsObject()) {
v8::Handle<v8::Object> obj = val->ToObject();
v8::Handle<v8::String> printFuncName = v8::String::New("print");
if (obj->Has(printFuncName)) {
v8::Handle<v8::Function> print = v8::Handle<v8::Function>::Cast(obj->Get(printFuncName));
if (obj->Has(v8g->PrintFuncName)) {
v8::Handle<v8::Function> print = v8::Handle<v8::Function>::Cast(obj->Get(v8g->PrintFuncName));
v8::Handle<v8::Value> args[] = { val };
print->Call(obj, 1, args);
printBuffer = false;
@ -423,9 +462,14 @@ static v8::Handle<v8::Value> JS_Print (v8::Arguments const& argv) {
TRI_AppendStringStringBuffer(&buffer, "[string]");
}
else {
size_t out;
char* e = TRI_EscapeCString(*utf8, utf8.length(), &out);
TRI_AppendCharStringBuffer(&buffer, '"');
TRI_AppendString2StringBuffer(&buffer, *utf8, utf8.length());
TRI_AppendString2StringBuffer(&buffer, e, out);
TRI_AppendCharStringBuffer(&buffer, '"');
TRI_FreeString(e);
}
}
else {
@ -491,6 +535,27 @@ static v8::Handle<v8::Value> JS_Print (v8::Arguments const& argv) {
void TRI_InitV8Shell (v8::Handle<v8::Context> context) {
v8::HandleScope scope;
// check the isolate
v8::Isolate* isolate = v8::Isolate::GetCurrent();
TRI_v8_global_t* v8g = (TRI_v8_global_t*) isolate->GetData();
if (v8g == 0) {
v8g = new TRI_v8_global_t;
isolate->SetData(v8g);
}
// .............................................................................
// global function names
// .............................................................................
if (v8g->PrintFuncName.IsEmpty()) {
v8g->PrintFuncName = v8::Persistent<v8::String>::New(v8::String::New("print"));
}
if (v8g->ToJsonFuncName.IsEmpty()) {
v8g->ToJsonFuncName = v8::Persistent<v8::String>::New(v8::String::New("toJson"));
}
// .............................................................................
// create the global functions
// .............................................................................
@ -503,7 +568,7 @@ void TRI_InitV8Shell (v8::Handle<v8::Context> context) {
v8::FunctionTemplate::New(JS_Output)->GetFunction(),
v8::ReadOnly);
context->Global()->Set(v8::String::New("print"),
context->Global()->Set(v8g->PrintFuncName,
v8::FunctionTemplate::New(JS_Print)->GetFunction(),
v8::ReadOnly);

View File

@ -1828,9 +1828,12 @@ bool TRI_ExecuteStringVocBase (v8::Handle<v8::Context> context,
v8::Handle<v8::Value> name,
bool printResult,
bool reportExceptions) {
TRI_v8_global_t* v8g;
v8::HandleScope handleScope;
v8::TryCatch tryCatch;
v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
// compilation failed, print errors that happened during compilation
@ -1861,8 +1864,7 @@ bool TRI_ExecuteStringVocBase (v8::Handle<v8::Context> context,
// if all went well and the result wasn't undefined then print the returned value
if (printResult && ! result->IsUndefined()) {
v8::Handle<v8::String> printFuncName = v8::String::New("print");
v8::Handle<v8::Function> print = v8::Handle<v8::Function>::Cast(context->Global()->Get(printFuncName));
v8::Handle<v8::Function> print = v8::Handle<v8::Function>::Cast(context->Global()->Get(v8g->PrintFuncName));
v8::Handle<v8::Value> args[] = { result };
print->Call(print, 1, args);
@ -1889,6 +1891,14 @@ void TRI_InitV8Utils (v8::Handle<v8::Context> context) {
isolate->SetData(v8g);
}
// .............................................................................
// global function names
// .............................................................................
if (v8g->PrintFuncName.IsEmpty()) {
v8g->PrintFuncName = v8::Persistent<v8::String>::New(v8::String::New("print"));
}
// .............................................................................
// create the global functions
// .............................................................................

View File

@ -261,8 +261,8 @@ static v8::Handle<v8::Value> JS_PrintUsingToString (v8::Arguments const& argv) {
v8::Handle<v8::Function> output = v8::Handle<v8::Function>::Cast(self->CreationContext()->Global()->Get(v8g->OutputFuncName));
v8::Handle<v8::Value> args2[] = { str, v8::String::New("\n") };
output->Call(output, 2, args2);
v8::Handle<v8::Value> args2[] = { str };
output->Call(output, 1, args2);
return scope.Close(v8::Undefined());
}
@ -631,25 +631,6 @@ static bool OptimiseQuery (v8::Handle<v8::Object> queryObject) {
/// @{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief calls the "printQuery" function
////////////////////////////////////////////////////////////////////////////////
static v8::Handle<v8::Value> JS_PrintQuery (v8::Arguments const& argv) {
TRI_v8_global_t* v8g;
v8::HandleScope scope;
v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
v8::Handle<v8::Object> self = argv.Holder();
v8::Handle<v8::Function> print = v8::Handle<v8::Function>::Cast(self->CreationContext()->Global()->Get(v8g->PrintQueryFuncName));
v8::Handle<v8::Value> args[] = { self };
print->Call(print, 1, args);
return scope.Close(v8::Undefined());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief converts a query into a fluent interface representation
///
@ -2129,6 +2110,10 @@ static v8::Handle<v8::Value> MapGetVocBase (v8::Local<v8::String> name,
// convert the JavaScript string to a string
string key = TRI_ObjectToString(name);
if (key == "toString" || key == "print") {
return v8::Handle<v8::Value>();
}
// look up the value if it exists
TRI_vocbase_col_t const* collection = TRI_FindCollectionByNameVocBase(vocbase, key.c_str());
@ -2379,6 +2364,7 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> rt;
v8::Handle<v8::FunctionTemplate> ft;
// check the isolate
v8::Isolate* isolate = v8::Isolate::GetCurrent();
@ -2399,9 +2385,17 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
// global function names
// .............................................................................
v8g->OutputFuncName = v8::Persistent<v8::String>::New(v8::String::New("output"));
v8g->PrintQueryFuncName = v8::Persistent<v8::String>::New(v8::String::New("printQuery"));
v8g->ToStringFuncName = v8::Persistent<v8::String>::New(v8::String::New("toString"));
if (v8g->OutputFuncName.IsEmpty()) {
v8g->OutputFuncName = v8::Persistent<v8::String>::New(v8::String::New("output"));
}
if (v8g->PrintFuncName.IsEmpty()) {
v8g->PrintFuncName = v8::Persistent<v8::String>::New(v8::String::New("print"));
}
if (v8g->ToStringFuncName.IsEmpty()) {
v8g->ToStringFuncName = v8::Persistent<v8::String>::New(v8::String::New("toString"));
}
// .............................................................................
// local function names
@ -2423,7 +2417,6 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
v8::Handle<v8::String> NextFuncName = v8::Persistent<v8::String>::New(v8::String::New("next"));
v8::Handle<v8::String> OptimiseFuncName = v8::Persistent<v8::String>::New(v8::String::New("optimise"));
v8::Handle<v8::String> ParameterFuncName = v8::Persistent<v8::String>::New(v8::String::New("parameter"));
v8::Handle<v8::String> PrintFuncName = v8::Persistent<v8::String>::New(v8::String::New("print"));
v8::Handle<v8::String> ReplaceFuncName = v8::Persistent<v8::String>::New(v8::String::New("replace"));
v8::Handle<v8::String> SaveFuncName = v8::Persistent<v8::String>::New(v8::String::New("save"));
v8::Handle<v8::String> SelectFuncName = v8::Persistent<v8::String>::New(v8::String::New("select"));
@ -2451,22 +2444,31 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
// generate the TRI_vocbase_t template
// .............................................................................
rt = v8::ObjectTemplate::New();
ft = v8::FunctionTemplate::New();
ft->SetClassName(v8::String::New("AvocadoCollection"));
rt = ft->InstanceTemplate();
rt->SetInternalFieldCount(1);
rt->Set(PrintFuncName, v8::FunctionTemplate::New(JS_PrintUsingToString));
rt->Set(v8g->ToStringFuncName, v8::FunctionTemplate::New(JS_ToStringVocBase));
rt->SetNamedPropertyHandler(MapGetVocBase);
rt->Set(v8g->PrintFuncName, v8::FunctionTemplate::New(JS_PrintUsingToString));
rt->Set(v8g->ToStringFuncName, v8::FunctionTemplate::New(JS_ToStringVocBase));
v8g->VocbaseTempl = v8::Persistent<v8::ObjectTemplate>::New(rt);
// must come after SetInternalFieldCount
context->Global()->Set(v8::String::New("AvocadoCollection"),
ft->GetFunction());
// .............................................................................
// generate the TRI_vocbase_col_t template
// .............................................................................
rt = v8::ObjectTemplate::New();
ft = v8::FunctionTemplate::New();
ft->SetClassName(v8::String::New("AvocadoCollection"));
rt = ft->InstanceTemplate();
rt->SetInternalFieldCount(SLOT_END);
rt->Set(AllFuncName, v8::FunctionTemplate::New(JS_AllQuery));
@ -2481,7 +2483,7 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
rt->Set(LimitFuncName, v8::FunctionTemplate::New(JS_LimitQuery));
rt->Set(NearFuncName, v8::FunctionTemplate::New(JS_NearQuery));
rt->Set(ParameterFuncName, v8::FunctionTemplate::New(JS_ParameterVocbaseCol));
rt->Set(PrintFuncName, v8::FunctionTemplate::New(JS_PrintUsingToString));
rt->Set(v8g->PrintFuncName, v8::FunctionTemplate::New(JS_PrintUsingToString));
rt->Set(ReplaceFuncName, v8::FunctionTemplate::New(JS_ReplaceVocbaseCol));
rt->Set(SaveFuncName, v8::FunctionTemplate::New(JS_SaveVocbaseCol));
rt->Set(SelectFuncName, v8::FunctionTemplate::New(JS_SelectQuery));
@ -2492,12 +2494,18 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
v8g->VocbaseColTempl = v8::Persistent<v8::ObjectTemplate>::New(rt);
// must come after SetInternalFieldCount
context->Global()->Set(v8::String::New("AvocadoCollection"),
ft->GetFunction());
// .............................................................................
// generate the query template
// .............................................................................
rt = v8::ObjectTemplate::New();
ft = v8::FunctionTemplate::New();
ft->SetClassName(v8::String::New("AvocadoQuery"));
rt = ft->InstanceTemplate();
rt->SetInternalFieldCount(SLOT_END);
rt->Set(AllFuncName, v8::FunctionTemplate::New(JS_AllQuery));
@ -2511,7 +2519,6 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
rt->Set(NearFuncName, v8::FunctionTemplate::New(JS_NearQuery));
rt->Set(NextFuncName, v8::FunctionTemplate::New(JS_NextQuery));
rt->Set(OptimiseFuncName, v8::FunctionTemplate::New(JS_OptimiseQuery));
rt->Set(PrintFuncName, v8::FunctionTemplate::New(JS_PrintQuery));
rt->Set(SelectFuncName, v8::FunctionTemplate::New(JS_SelectQuery));
rt->Set(ShowFuncName, v8::FunctionTemplate::New(JS_ShowQuery));
rt->Set(SkipFuncName, v8::FunctionTemplate::New(JS_SkipQuery));
@ -2520,6 +2527,10 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
v8g->QueryTempl = v8::Persistent<v8::ObjectTemplate>::New(rt);
// must come after SetInternalFieldCount
context->Global()->Set(v8::String::New("AvocadoQuery"),
ft->GetFunction());
// .............................................................................
// create the global variables
// .............................................................................

View File

@ -54,14 +54,41 @@
/// A complete list of the available JavaScript functions can be found
/// @ref JavaScriptFunc "here".
///
////////////////////////////////////////////////////////////////////////////////
/// @section FirstStepsFI First Steps
////////////////////////////////////////////////////////////////////////////////
///
/// For instance, in order to select all elements of a collection "examples",
/// one can use the @FN{all} operator.
/// All documents are stored in collections. All collections are stored in a
/// database.
///
/// @verbinclude fluent1
/// @verbinclude fluent41
///
/// Printing the @VAR{db} variable will show you the location, where the
/// datafiles of the collections are stored by default.
///
/// Creating a collection is simple. It will automatically be created
/// when accessing the members of the @VAR{db}.
///
/// @verbinclude fluent42
///
/// If the collections does not exists, it is called a new-born. No file has
/// been created so far. If you access the collection, then the directory
/// and corresponding files will be created.
///
/// @verbinclude fluent43
///
/// If you restart the server and access the collection again, it will
/// now show as "unloaded".
///
/// @verbinclude fluent44
///
/// In order to create new documents in a collection, use the @FN{save}
/// operator.
///
/// @verbinclude fluent45
///
/// In order to select all elements of a collection, one can use the @FN{all}
/// operator.
///
/// @verbinclude fluent46
///
/// This will select all documents and prints the first 20 documents. If there
/// are more than 20 documents, then @CODE{...more results...} is printed and
@ -74,14 +101,19 @@
/// first 20 documents are printed and the query (resp. cursor) is assigned to
/// the variable @VAR{it}.
///
/// A cursor can also be queried using @FN{hasNext} and @FN{next}. Calling
/// either of these functions also executes the query, turning it into a cursor.
/// A query can also be executed using @FN{hasNext} and @FN{next}.
///
/// @verbinclude fluent3
///
/// Next steps:
///
/// - learn about @ref GeoCoordinates "geo coordinates"
/// - learn about @ref Pagination "pagination"
/// - look at all the @ref JavaScriptFunc "functions"
////////////////////////////////////////////////////////////////////////////////
/// @section GeoFI Geo Coordinates
////////////////////////////////////////////////////////////////////////////////
/// @page GeoCoordinates Geo Coordinates
///
/// The AvocadoDB allows to selects documents based on geographic
/// coordinates. In order for this to work, a geo-spatial index must be defined.
@ -98,33 +130,29 @@
/// It is possible to define more than one geo-spatial index per collection. In
/// this case you must give a hint which of indexes should be used in a query.
///
////////////////////////////////////////////////////////////////////////////////
/// @subsection EnsureGeoIndexFI Create a Geo-Spatial Index
////////////////////////////////////////////////////////////////////////////////
/// @section EnsureGeoIndex Create a Geo-Spatial Index
///
/// First create an index.
///
/// @copydetails JS_EnsureGeoIndexVocbaseCol
///
////////////////////////////////////////////////////////////////////////////////
/// @subsection NearFI The Near Operator
////////////////////////////////////////////////////////////////////////////////
/// @section NearOperator The Near Operator
///
/// @copydetails JS_NearQuery
///
////////////////////////////////////////////////////////////////////////////////
/// @subsection WithinFI The Within Operator
////////////////////////////////////////////////////////////////////////////////
/// @section WithinOperator The Within Operator
///
/// @copydetails JS_WithinQuery
///
////////////////////////////////////////////////////////////////////////////////
/// @subsection GeoOperatorFI The Geo Operator
////////////////////////////////////////////////////////////////////////////////
/// @section GeoOperator The Geo Operator
///
/// @copydetails JS_GeoQuery
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @page Pagination Pagination
///
////////////////////////////////////////////////////////////////////////////////
/// @section LimitFI The Limit Operator
////////////////////////////////////////////////////////////////////////////////
/// @section LimitOperator The Limit Operator
///
/// If, for example, you display the result of a user search, then you are in
/// general not interested in the completed result set, but only the first 10
@ -136,9 +164,7 @@
///
/// @copydetails JS_LimitQuery
///
////////////////////////////////////////////////////////////////////////////////
/// @section SkipFI The Skip Operator
////////////////////////////////////////////////////////////////////////////////
/// @section SkipOperator The Skip Operator
///
/// @FN{skip} used together with @FN{limit} can be used to implement
/// pagination. The @FN{skip} operator skips over the first n documents. So, in
@ -148,19 +174,6 @@
/// @verbinclude fluent5
///
/// @copydetails JS_SkipQuery
///
////////////////////////////////////////////////////////////////////////////////
/// @section CountFI The Count Operator
////////////////////////////////////////////////////////////////////////////////
///
/// @copydetails JS_CountQuery
///
////////////////////////////////////////////////////////////////////////////////
/// @section ExplainFI The Explain Operator
////////////////////////////////////////////////////////////////////////////////
///
/// @copydetails JS_ExplainQuery
///
////////////////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------

View File

@ -251,9 +251,16 @@ static void ScanPath (TRI_vocbase_t* vocbase, char const* path) {
n = TRI_SizeVectorString(&files);
for (i = 0; i < n; ++i) {
char* name;
char* file;
file = TRI_Concatenate2File(path, TRI_AtVectorString(&files, i));
name = TRI_AtVectorString(&files, i);
if (name[0] == '\0' || name[0] == '_' || name[0] == '.') {
continue;
}
file = TRI_Concatenate2File(path, name);
if (TRI_IsDirectory(file)) {
TRI_col_info_t info;

View File

@ -1 +1 @@
#define TRIAGENS_VERSION "0.0.4 (9595)"
#define TRIAGENS_VERSION "0.0.4 (9617)"

View File

@ -50,7 +50,7 @@ var queryLimit = 20;
/// @brief prints a query
////////////////////////////////////////////////////////////////////////////////
printQuery = function(q) {
AvocadoQuery.prototype.print = function(q) {
var count = 0;
try {
@ -59,13 +59,13 @@ printQuery = function(q) {
}
if (q.hasNext()) {
output("...more results...\n");
output("...more results...");
}
it = q;
}
catch (e) {
output("encountered error while printing: " + e + "\n");
output("encountered error while printing: " + e);
}
}