mirror of https://gitee.com/bigwinds/arangodb
added loader
This commit is contained in:
parent
2be85a89be
commit
3ecf51c305
|
@ -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.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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:
|
116
Basics/Mutex.h
116
Basics/Mutex.h
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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:
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -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"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -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:
|
|
@ -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:
|
|
@ -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:
|
|
@ -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:
|
|
@ -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:
|
|
@ -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:
|
|
@ -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:
|
|
@ -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:
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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"
|
||||
;
|
|
@ -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"
|
||||
;
|
|
@ -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"
|
||||
;
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
// .............................................................................
|
||||
|
|
|
@ -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
|
||||
// .............................................................................
|
||||
|
|
|
@ -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
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
|
|
2
build.h
2
build.h
|
@ -1 +1 @@
|
|||
#define TRIAGENS_VERSION "0.0.4 (9595)"
|
||||
#define TRIAGENS_VERSION "0.0.4 (9617)"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue