1
0
Fork 0

insert standalone marker

This commit is contained in:
Jan Steemann 2014-04-11 13:01:00 +02:00
parent 3dce782d5d
commit 86398d7cde
26 changed files with 696 additions and 135 deletions

View File

@ -120,6 +120,7 @@ add_executable(
Transaction/Transaction.cpp
Transaction/WorkUnit.cpp
Utils/DocumentHelper.cpp
Utils/Exception.cpp
V8Server/ApplicationV8.cpp
V8Server/V8PeriodicTask.cpp
V8Server/V8PeriodicJob.cpp

View File

@ -86,6 +86,7 @@ bin_arangod_SOURCES = \
arangod/Transaction/Transaction.cpp \
arangod/Transaction/WorkUnit.cpp \
arangod/Utils/DocumentHelper.cpp \
arangod/Utils/Exception.cpp \
arangod/V8Server/ApplicationV8.cpp \
arangod/V8Server/V8PeriodicTask.cpp \
arangod/V8Server/V8PeriodicJob.cpp \

View File

@ -290,7 +290,6 @@ ArangoServer::ArangoServer (int argc, char** argv)
: _argc(argc),
_argv(argv),
_tempPath(),
_logfileManager(0),
_applicationScheduler(0),
_applicationDispatcher(0),
_applicationEndpointServer(0),
@ -387,10 +386,10 @@ void ArangoServer::buildApplicationServer () {
// arangod allows defining a user-specific configuration file. arangosh and the other binaries don't
_applicationServer->setUserConfigFile(".arango" + string(1, TRI_DIR_SEPARATOR_CHAR) + string(conf));
/*
_logfileManager = new wal::LogfileManager(&_databasePath);
_applicationServer->addFeature(_logfileManager);
*/
wal::LogfileManager::initialise(&_databasePath);
_applicationServer->addFeature(wal::LogfileManager::instance());
// .............................................................................
// dispatcher
// .............................................................................
@ -713,6 +712,11 @@ void ArangoServer::buildApplicationServer () {
// .............................................................................
// now run arangod
// .............................................................................
// make sure the logfile manager is ready
wal::LogfileManager::instance()->prepare();
wal::LogfileManager::instance()->start();
// dump version details
LOG_INFO("%s", rest::Version::getVerboseVersionString().c_str());

View File

@ -56,10 +56,6 @@ namespace triagens {
class HttpsServer;
}
namespace wal {
class LogfileManager;
}
namespace admin {
class ApplicationAdminServer;
}
@ -190,12 +186,6 @@ namespace triagens {
std::string _tempPath;
////////////////////////////////////////////////////////////////////////////////
/// @brief write-ahead log manager
////////////////////////////////////////////////////////////////////////////////
wal::LogfileManager* _logfileManager;
////////////////////////////////////////////////////////////////////////////////
/// @brief application scheduler
////////////////////////////////////////////////////////////////////////////////

View File

@ -27,7 +27,9 @@
#include "Collection.h"
#include "VocBase/vocbase.h"
#include "BasicsC/logging.h"
using namespace std;
using namespace triagens::transaction;
// -----------------------------------------------------------------------------
@ -38,13 +40,12 @@ using namespace triagens::transaction;
/// @brief create the transaction collection
////////////////////////////////////////////////////////////////////////////////
Collection::Collection (TRI_voc_cid_t id,
TRI_vocbase_col_t* collection,
Collection::Collection (TRI_vocbase_col_t* collection,
Collection::AccessType accessType,
bool responsibility,
bool locked)
: _id(id),
_collection(collection),
: _collection(collection),
_initialRevision(0),
_accessType(accessType),
_responsibility(responsibility),
_locked(locked),
@ -56,21 +57,32 @@ Collection::Collection (TRI_voc_cid_t id,
////////////////////////////////////////////////////////////////////////////////
Collection::~Collection () {
unlock();
done();
}
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief finalise usage of the collection
////////////////////////////////////////////////////////////////////////////////
int Collection::done () {
int res = unlock();
unuse();
return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief use the collection
////////////////////////////////////////////////////////////////////////////////
int Collection::use (TRI_vocbase_t* vocbase) {
int Collection::use () {
if (hasResponsibility()) {
if (! _used) {
TRI_vocbase_col_t* collection = TRI_UseCollectionByIdVocBase(vocbase, _id);
TRI_vocbase_col_t* collection = TRI_UseCollectionByIdVocBase(_collection->_vocbase, id());
if (collection == nullptr) {
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
@ -91,10 +103,10 @@ int Collection::use (TRI_vocbase_t* vocbase) {
/// @brief unuse the collection
////////////////////////////////////////////////////////////////////////////////
int Collection::unuse (TRI_vocbase_t* vocbase) {
int Collection::unuse () {
if (hasResponsibility()) {
if (_used) {
TRI_ReleaseCollectionVocBase(vocbase, _collection);
TRI_ReleaseCollectionVocBase(_collection->_vocbase, _collection);
_used = false;
}
}

View File

@ -74,8 +74,7 @@ namespace triagens {
/// @brief create the transaction collection
////////////////////////////////////////////////////////////////////////////////
Collection (TRI_voc_cid_t,
TRI_vocbase_col_t*,
Collection (TRI_vocbase_col_t*,
Collection::AccessType,
bool,
bool);
@ -92,6 +91,22 @@ namespace triagens {
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief collection id
////////////////////////////////////////////////////////////////////////////////
inline TRI_voc_cid_t id () const {
return _collection->_cid;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief database id
////////////////////////////////////////////////////////////////////////////////
inline TRI_voc_tick_t databaseId () const {
return _collection->_vocbase->_id;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not write access is allowed
////////////////////////////////////////////////////////////////////////////////
@ -124,17 +139,23 @@ namespace triagens {
return _collection->_collection;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief finalise usage of the collection
////////////////////////////////////////////////////////////////////////////////
int done ();
////////////////////////////////////////////////////////////////////////////////
/// @brief use the collection
////////////////////////////////////////////////////////////////////////////////
int use (TRI_vocbase_t*);
int use ();
////////////////////////////////////////////////////////////////////////////////
/// @brief unuse the collection
////////////////////////////////////////////////////////////////////////////////
int unuse (TRI_vocbase_t*);
int unuse ();
////////////////////////////////////////////////////////////////////////////////
/// @brief lock the collection
@ -160,18 +181,18 @@ namespace triagens {
private:
////////////////////////////////////////////////////////////////////////////////
/// @brief collection id
////////////////////////////////////////////////////////////////////////////////
TRI_voc_cid_t const _id;
////////////////////////////////////////////////////////////////////////////////
/// @brief the pointer to the vocbase collection
////////////////////////////////////////////////////////////////////////////////
TRI_vocbase_col_t* _collection;
////////////////////////////////////////////////////////////////////////////////
/// @brief initial revision of the collection
////////////////////////////////////////////////////////////////////////////////
TRI_voc_rid_t _initialRevision;
////////////////////////////////////////////////////////////////////////////////
/// @brief access type for the collection
////////////////////////////////////////////////////////////////////////////////

View File

@ -33,8 +33,13 @@
#include "Transaction/Transaction.h"
#include "Transaction/WorkUnit.h"
#include "VocBase/vocbase.h"
#include "Wal/LogfileManager.h"
#define CONTEXT_LOG(msg) LOG_INFO("%s", msg)
using namespace std;
using namespace triagens::transaction;
using namespace triagens::wal;
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
@ -45,9 +50,11 @@ using namespace triagens::transaction;
////////////////////////////////////////////////////////////////////////////////
Context::Context (Manager* manager,
wal::LogfileManager* logfileManager,
TRI_vocbase_t* vocbase,
Context** globalContext)
: _manager(manager),
_logfileManager(logfileManager),
_resolver(vocbase),
_globalContext(globalContext),
_transaction(0),
@ -55,7 +62,8 @@ Context::Context (Manager* manager,
_nextWorkUnitId(0),
_refCount(0) {
LOG_INFO("creating context");
CONTEXT_LOG("creating context");
if (_globalContext != nullptr) {
*_globalContext = this;
}
@ -72,7 +80,8 @@ Context::~Context () {
if (_globalContext != nullptr) {
*_globalContext = nullptr;
}
LOG_INFO("destroyed context");
CONTEXT_LOG("destroyed context");
}
// -----------------------------------------------------------------------------
@ -84,9 +93,10 @@ Context::~Context () {
////////////////////////////////////////////////////////////////////////////////
Context* Context::getContext (Manager* manager,
wal::LogfileManager* logfileManager,
TRI_vocbase_t* vocbase,
Context** globalContext) {
return createContext(manager, vocbase, globalContext);
return createContext(manager, logfileManager, vocbase, globalContext);
}
////////////////////////////////////////////////////////////////////////////////
@ -94,8 +104,9 @@ Context* Context::getContext (Manager* manager,
////////////////////////////////////////////////////////////////////////////////
Context* Context::getContext (Manager* manager,
wal::LogfileManager* logfileManager,
TRI_vocbase_t* vocbase) {
return createContext(manager, vocbase, nullptr);
return createContext(manager, logfileManager, vocbase, nullptr);
}
////////////////////////////////////////////////////////////////////////////////
@ -154,15 +165,13 @@ Collection* Context::findCollection (TRI_voc_cid_t id) const {
int Context::startWorkUnit (WorkUnit* workUnit) {
if (_workUnits.empty()) {
LOG_INFO("starting top-level work unit");
assert(_transaction == nullptr);
_transaction = _manager->createTransaction(workUnit->isSingleOperation());
assert(_transaction != nullptr);
}
else {
LOG_INFO("starting nested (%d) work unit", (int) _workUnits.size());
}
assert(_transaction != nullptr);
_workUnits.push_back(workUnit);
@ -182,17 +191,12 @@ int Context::endWorkUnit (WorkUnit* workUnit) {
_workUnits.pop_back();
if (_workUnits.empty()) {
LOG_INFO("ending top-level work unit");
// final level
if (_transaction != nullptr) {
delete _transaction;
_transaction = nullptr;
}
}
else {
LOG_INFO("ending nested (%d) work unit", (int) _workUnits.size());
}
return TRI_ERROR_NO_ERROR;
}
@ -206,11 +210,12 @@ int Context::endWorkUnit (WorkUnit* workUnit) {
////////////////////////////////////////////////////////////////////////////////
Context* Context::createContext (Manager* manager,
wal::LogfileManager* logfileManager,
TRI_vocbase_t* vocbase,
Context** globalContext) {
if (globalContext == nullptr ||
*globalContext == nullptr) {
return new Context(manager, vocbase, globalContext);
return new Context(manager, logfileManager, vocbase, globalContext);
}
return *globalContext;

View File

@ -33,6 +33,10 @@
#include "VocBase/vocbase.h"
namespace triagens {
namespace wal {
class LogfileManager;
}
namespace transaction {
class Collection;
@ -68,7 +72,8 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
Context (Manager*,
struct TRI_vocbase_s*,
triagens::wal::LogfileManager*,
TRI_vocbase_t*,
Context**);
////////////////////////////////////////////////////////////////////////////////
@ -91,6 +96,14 @@ namespace triagens {
return ++_nextWorkUnitId;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief logfile manager
////////////////////////////////////////////////////////////////////////////////
inline wal::LogfileManager* logfileManager () const {
return _logfileManager;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the current transaction
////////////////////////////////////////////////////////////////////////////////
@ -124,7 +137,8 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
static Context* getContext (Manager*,
struct TRI_vocbase_s*,
triagens::wal::LogfileManager*,
TRI_vocbase_t*,
Context**);
////////////////////////////////////////////////////////////////////////////////
@ -132,7 +146,8 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
static Context* getContext (Manager*,
struct TRI_vocbase_s*);
triagens::wal::LogfileManager*,
TRI_vocbase_t*);
////////////////////////////////////////////////////////////////////////////////
/// @brief increase the reference count
@ -170,7 +185,8 @@ namespace triagens {
////////////////////////////////////////////////////////////////////////////////
static Context* createContext (Manager*,
struct TRI_vocbase_s*,
triagens::wal::LogfileManager*,
TRI_vocbase_t*,
Context**);
// -----------------------------------------------------------------------------
@ -185,6 +201,12 @@ namespace triagens {
Manager* _manager;
////////////////////////////////////////////////////////////////////////////////
/// @brief the logfile manager
////////////////////////////////////////////////////////////////////////////////
triagens::wal::LogfileManager* _logfileManager;
////////////////////////////////////////////////////////////////////////////////
/// @brief the collection name resolver
////////////////////////////////////////////////////////////////////////////////

View File

@ -28,6 +28,7 @@
#include "IdGenerator.h"
#include "VocBase/server.h"
using namespace std;
using namespace triagens::transaction;
// -----------------------------------------------------------------------------

View File

@ -32,13 +32,14 @@
#include "Transaction/State.h"
#include "VocBase/vocbase.h"
using namespace std;
using namespace triagens::transaction;
////////////////////////////////////////////////////////////////////////////////
/// @brief the transaction manager singleton
////////////////////////////////////////////////////////////////////////////////
static Manager* ManagerInstance = 0;
static Manager* Instance = nullptr;
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
@ -48,7 +49,7 @@ static Manager* ManagerInstance = 0;
/// @brief create the transaction manager
////////////////////////////////////////////////////////////////////////////////
Manager::Manager ()
Manager::Manager ()
: _generator(),
_lock(),
_transactions() {
@ -72,17 +73,13 @@ Manager::~Manager () {
_transactions.clear();
}
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief get the transaction manager instance
////////////////////////////////////////////////////////////////////////////////
Manager* Manager::instance () {
assert(ManagerInstance != 0);
return ManagerInstance;
assert(Instance != nullptr);
return Instance;
}
////////////////////////////////////////////////////////////////////////////////
@ -90,9 +87,9 @@ Manager* Manager::instance () {
////////////////////////////////////////////////////////////////////////////////
void Manager::initialise () {
assert(ManagerInstance == 0);
assert(Instance == nullptr);
ManagerInstance = new Manager();
Instance = new Manager();
}
////////////////////////////////////////////////////////////////////////////////
@ -100,9 +97,9 @@ void Manager::initialise () {
////////////////////////////////////////////////////////////////////////////////
void Manager::shutdown () {
if (ManagerInstance != 0) {
delete ManagerInstance;
ManagerInstance = 0;
if (Instance != nullptr) {
delete Instance;
Instance = nullptr;
}
}

View File

@ -78,7 +78,7 @@ namespace triagens {
/// @brief initialise the transaction manager instance
////////////////////////////////////////////////////////////////////////////////
void initialise ();
static void initialise ();
////////////////////////////////////////////////////////////////////////////////
/// @brief shutdown the transaction manager instance

View File

@ -0,0 +1,101 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief transaction markers
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_TRANSACTION_MARKER_H
#define TRIAGENS_TRANSACTION_MARKER_H 1
#include "Basics/Common.h"
#include "Basics/BsonHelper.h"
#include "VocBase/datafile.h"
namespace triagens {
namespace transaction {
struct Marker {
Marker (TRI_df_marker_type_e type,
size_t size)
: buffer(new char[sizeof(TRI_df_marker_t) + size]),
size(sizeof(TRI_df_marker_t) + size) {
// initialise the marker header
auto h = header();
h->_type = type;
h->_size = static_cast<TRI_voc_size_t>(size);
h->_crc = 0;
h->_tick = 0;
}
virtual ~Marker () {
if (buffer != nullptr) {
delete buffer;
}
}
inline TRI_df_marker_t* header () const {
return (TRI_df_marker_t*) buffer;
}
inline char* data () const {
return (char*) buffer + sizeof(TRI_df_marker_t);
}
template <typename T> void storeValue (char*& ptr, T value) {
*((T*) ptr) = value;
ptr += sizeof(T);
}
char* buffer;
uint32_t const size;
};
struct DocumentMarker : public Marker {
DocumentMarker (TRI_voc_tick_t databaseId,
TRI_voc_cid_t collectionId,
triagens::basics::Bson const& document)
: Marker(TRI_WAL_MARKER_DOCUMENT_STANDALONE, sizeof(TRI_voc_tick_t) + sizeof(TRI_voc_cid_t) + document.getSize()) {
char* p = data();
storeValue<TRI_voc_tick_t>(p, databaseId);
storeValue<TRI_voc_cid_t>(p, collectionId);
memcpy(p, document.getBuffer(), document.getSize());
}
~DocumentMarker () {
}
};
}
}
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:

View File

@ -26,10 +26,10 @@
////////////////////////////////////////////////////////////////////////////////
#include "Operations.h"
//#include "Transaction/Transaction.h"
#include "BasicsC/logging.h"
using namespace std;
using namespace triagens::transaction;
////////////////////////////////////////////////////////////////////////////////

View File

@ -27,6 +27,7 @@
#include "State.h"
using namespace std;
using namespace triagens::transaction;
// -----------------------------------------------------------------------------

View File

@ -30,8 +30,11 @@
#include "BasicsC/logging.h"
#include "Transaction/Manager.h"
using namespace std;
using namespace triagens::transaction;
#define TRANSACTION_LOG(msg) LOG_INFO("trx #%llu: %s", (unsigned long long) _id, msg)
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
@ -51,7 +54,7 @@ Transaction::Transaction (Manager* manager,
_waitForSync(waitForSync),
_startTime() {
LOG_INFO("creating transaction %llu", (unsigned long long) id);
TRANSACTION_LOG("creating transaction");
}
////////////////////////////////////////////////////////////////////////////////
@ -64,7 +67,7 @@ Transaction::~Transaction () {
this->rollback();
}
LOG_INFO("destroyed transaction %llu", (unsigned long long) _id);
TRANSACTION_LOG("destroyed transaction");
}
// -----------------------------------------------------------------------------
@ -80,7 +83,7 @@ int Transaction::begin () {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
LOG_INFO("beginning transaction %llu", (unsigned long long) _id);
TRANSACTION_LOG("beginning transaction");
int res = _manager->beginTransaction(this);
if (res == TRI_ERROR_NO_ERROR) {
@ -98,7 +101,7 @@ int Transaction::commit (bool waitForSync) {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
LOG_INFO("committing transaction %llu", (unsigned long long) _id);
TRANSACTION_LOG("committing transaction");
return _manager->commitTransaction(this, waitForSync || _waitForSync);
}
@ -111,7 +114,7 @@ int Transaction::rollback () {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
LOG_INFO("rolling back transaction %llu", (unsigned long long) _id);
TRANSACTION_LOG("rolling back transaction");
return _manager->rollbackTransaction(this);
}

View File

@ -26,12 +26,20 @@
////////////////////////////////////////////////////////////////////////////////
#include "WorkUnit.h"
#include "BasicsC/logging.h"
#include "Transaction/Collection.h"
#include "Transaction/Context.h"
#include "Transaction/Marker.h"
#include "Transaction/Transaction.h"
#include "Utils/Exception.h"
#include "VocBase/vocbase.h"
#include "Wal/LogfileManager.h"
#define WORKUNIT_LOG(msg) LOG_INFO("workunit #%llu: %s", (unsigned long long) _id, msg)
using namespace std;
using namespace triagens::transaction;
using namespace triagens::wal;
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
@ -51,7 +59,9 @@ WorkUnit::WorkUnit (Context* context,
_done(false) {
_context->increaseRefCount();
_context->startWorkUnit(this);
WORKUNIT_LOG("starting");
}
////////////////////////////////////////////////////////////////////////////////
@ -59,7 +69,9 @@ WorkUnit::WorkUnit (Context* context,
////////////////////////////////////////////////////////////////////////////////
WorkUnit::~WorkUnit () {
WORKUNIT_LOG("destroyed");
done();
_context->decreaseRefCount();
}
@ -67,18 +79,40 @@ WorkUnit::~WorkUnit () {
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to the unit, assert a specific collection type
////////////////////////////////////////////////////////////////////////////////
Collection* WorkUnit::addCollection (string const& name,
Collection::AccessType accessType,
TRI_col_type_e collectionType,
bool lockResponsibility,
bool locked) {
TRI_vocbase_col_t* collection = _context->resolveCollection(name);
if (collection == nullptr) {
THROW_ARANGO_EXCEPTION_STRING(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, name);
}
if (collection->_type != static_cast<TRI_col_type_t>(collectionType)) {
THROW_ARANGO_EXCEPTION_STRING(TRI_ERROR_ARANGO_COLLECTION_TYPE_INVALID, name);
}
return addCollection(collection->_cid, collection, accessType, lockResponsibility, locked);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to the unit
////////////////////////////////////////////////////////////////////////////////
int WorkUnit::addCollection (string const& name,
Collection::AccessType accessType,
bool lockResponsibility,
bool locked) {
Collection* WorkUnit::addCollection (string const& name,
Collection::AccessType accessType,
bool lockResponsibility,
bool locked) {
TRI_vocbase_col_t* collection = _context->resolveCollection(name);
if (collection == nullptr) {
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
THROW_ARANGO_EXCEPTION_STRING(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, name);
}
return addCollection(collection->_cid, collection, accessType, lockResponsibility, locked);
@ -88,37 +122,36 @@ int WorkUnit::addCollection (string const& name,
/// @brief add a collection to the unit
////////////////////////////////////////////////////////////////////////////////
int WorkUnit::addCollection (TRI_voc_cid_t id,
TRI_vocbase_col_t* collection,
Collection::AccessType accessType,
bool lockResponsibility,
bool locked) {
Collection* WorkUnit::addCollection (TRI_voc_cid_t id,
TRI_vocbase_col_t* collection,
Collection::AccessType accessType,
bool lockResponsibility,
bool locked) {
if (id == 0) {
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND);
}
auto it = _collections.find(id);
if (it != _collections.end()) {
Collection* collection = (*it).second;
if (accessType == Collection::AccessType::WRITE &&
! collection->allowWriteAccess()) {
return TRI_ERROR_TRANSACTION_INTERNAL;
! (*it).second->allowWriteAccess()) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_TRANSACTION_INTERNAL);
}
return TRI_ERROR_NO_ERROR;
return (*it).second;
}
Collection* previous = _context->findCollection(id);
Collection* c = _context->findCollection(id);
if (previous != nullptr) {
// collection already present in a top-level work unit
return TRI_ERROR_NO_ERROR;
if (c == nullptr) {
// no previous collection found, now insert it
c = new Collection(collection, accessType, lockResponsibility, locked);
_collections.insert(make_pair(id, c));
}
_collections.insert(make_pair(id, new Collection(id, collection, accessType, lockResponsibility, locked)));
return TRI_ERROR_NO_ERROR;
return c;
}
////////////////////////////////////////////////////////////////////////////////
@ -142,9 +175,22 @@ int WorkUnit::begin () {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
int res;
WORKUNIT_LOG("begin");
int res = TRI_ERROR_NO_ERROR;
for (auto& it : _collections) {
res = it.second->use();
if (res != TRI_ERROR_NO_ERROR) {
return res;
}
res = it.second->lock();
if (res != TRI_ERROR_NO_ERROR) {
return res;
}
}
if (! isTopLevel()) {
// TODO: implement begin
res = TRI_ERROR_NO_ERROR;
}
else {
@ -165,10 +211,11 @@ int WorkUnit::commit (bool waitForSync) {
if (state() != State::StateType::BEGUN) {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
WORKUNIT_LOG("commit");
int res;
if (! isTopLevel()) {
// TODO: implement commit
res = TRI_ERROR_NO_ERROR;
}
else {
@ -176,8 +223,8 @@ int WorkUnit::commit (bool waitForSync) {
res = transaction->commit(waitForSync);
}
setState(State::StateType::COMMITTED);
done();
setState(State::StateType::COMMITTED);
return res;
}
@ -190,10 +237,11 @@ int WorkUnit::rollback () {
if (state() != State::StateType::BEGUN) {
return TRI_ERROR_TRANSACTION_INTERNAL;
}
WORKUNIT_LOG("rollback");
int res;
if (! isTopLevel()) {
// TODO: implement rollback
res = TRI_ERROR_NO_ERROR;
}
else {
@ -201,8 +249,27 @@ int WorkUnit::rollback () {
res = transaction->rollback();
}
setState(State::StateType::ABORTED);
done();
setState(State::StateType::ABORTED);
return res;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief save a single document
////////////////////////////////////////////////////////////////////////////////
int WorkUnit::saveDocument (Collection* collection,
triagens::basics::Bson const& document,
bool waitForSync) {
DocumentMarker marker(collection->databaseId(), collection->id(), document);
LogfileManager* logfileManager = _context->logfileManager();
int res = logfileManager->allocateAndWrite(marker.buffer,
marker.size,
waitForSync);
return res;
}
@ -217,9 +284,14 @@ int WorkUnit::rollback () {
void WorkUnit::done () {
if (! _done) {
for (auto& it : _collections) {
it.second->done();
}
_context->endWorkUnit(this);
_done = true;
}
cleanup();
}

View File

@ -29,6 +29,7 @@
#define TRIAGENS_TRANSACTION_WORK_UNIT_H 1
#include "Basics/Common.h"
#include "Basics/BsonHelper.h"
#include "Transaction/Collection.h"
#include "Transaction/State.h"
#include "Transaction/Transaction.h"
@ -93,24 +94,34 @@ namespace triagens {
return _singleOperation;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to the unit, assert a specific collection type
////////////////////////////////////////////////////////////////////////////////
Collection* addCollection (std::string const&,
Collection::AccessType,
TRI_col_type_e,
bool = true,
bool = false);
////////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to the unit
////////////////////////////////////////////////////////////////////////////////
int addCollection (std::string const&,
Collection::AccessType,
bool = true,
bool = false);
Collection* addCollection (std::string const&,
Collection::AccessType,
bool = true,
bool = false);
////////////////////////////////////////////////////////////////////////////////
/// @brief add a collection to the unit
////////////////////////////////////////////////////////////////////////////////
int addCollection (TRI_voc_cid_t,
TRI_vocbase_col_t*,
Collection::AccessType,
bool = true,
bool = false);
Collection* addCollection (TRI_voc_cid_t,
TRI_vocbase_col_t*,
Collection::AccessType,
bool = true,
bool = false);
////////////////////////////////////////////////////////////////////////////////
/// @brief find a collection in a unit of work
@ -136,6 +147,14 @@ namespace triagens {
int rollback ();
////////////////////////////////////////////////////////////////////////////////
/// @brief save a single document
////////////////////////////////////////////////////////////////////////////////
int saveDocument (Collection*,
triagens::basics::Bson const&,
bool);
// -----------------------------------------------------------------------------
// --SECTION-- private methods
// -----------------------------------------------------------------------------

View File

@ -0,0 +1,71 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief transaction macros
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2011-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_TRANSACTION_TRANSACTIONS_H
#define TRIAGENS_TRANSACTION_TRANSACTIONS_H 1
#include "Basics/Common.h"
#include "BasicsC/logging.h"
#include "Transaction/Context.h"
#include "Transaction/Manager.h"
#include "Transaction/Transaction.h"
#include "Transaction/WorkUnit.h"
#include "Utils/Exception.h"
#include "Wal/LogfileManager.h"
////////////////////////////////////////////////////////////////////////////////
/// @brief try block for a transaction
////////////////////////////////////////////////////////////////////////////////
#define TRANSACTION_TRY(vocbase, context, globalContext) \
try { \
triagens::transaction::Manager* manager = new triagens::transaction::Manager(); \
triagens::transaction::Context* context = triagens::transaction::Context::getContext(manager, triagens::wal::LogfileManager::instance(), vocbase, globalContext);
////////////////////////////////////////////////////////////////////////////////
/// @brief catch block for a transaction
////////////////////////////////////////////////////////////////////////////////
#define TRANSACTION_CATCH(ex) \
} \
catch (triagens::arango::Exception const &ex) { \
LOG_INFO("transaction exception: %s", ex.what()); \
////////////////////////////////////////////////////////////////////////////////
/// @brief final block for a transaction
////////////////////////////////////////////////////////////////////////////////
#define TRANSACTION_FINALLY \
}
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:

View File

@ -0,0 +1,96 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief arango exceptions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#include "Exception.h"
#include "Basics/StringUtils.h"
using namespace std;
using namespace triagens::arango;
////////////////////////////////////////////////////////////////////////////////
/// @brief constructor
////////////////////////////////////////////////////////////////////////////////
Exception::Exception (int code,
string const& details,
char const* file,
int line)
: _details(details),
_file(file),
_line(line),
_code(code) {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief destructor
////////////////////////////////////////////////////////////////////////////////
Exception::~Exception () throw () {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return exception message
////////////////////////////////////////////////////////////////////////////////
char const* Exception::what () const throw () {
string message("exception in '");
message.append(_file);
message.append("' at line ");
message.append(basics::StringUtils::itoa(_line));
message.append(": ");
message += this->message();
return message.c_str();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return exception message
////////////////////////////////////////////////////////////////////////////////
string Exception::message () const throw () {
string message(TRI_errno_string(_code));
if (! _details.empty()) {
message.append(": ");
message.append(_details);
}
return message;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return exception code
////////////////////////////////////////////////////////////////////////////////
int Exception::code () const throw () {
return _code;
}
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:

96
arangod/Utils/Exception.h Normal file
View File

@ -0,0 +1,96 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief arango exceptions
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2004-2013 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is triAGENS GmbH, Cologne, Germany
///
/// @author Jan Steemann
/// @author Copyright 2009-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef TRIAGENS_ARANGO_UTILS_EXCEPTION_H
#define TRIAGENS_ARANGO_UTILS_EXCEPTION_H 1
#include "Basics/Common.h"
#include "Basics/Exceptions.h"
#include <errno.h>
// -----------------------------------------------------------------------------
// --SECTION-- public macros
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief throws an arango exception with an error code
////////////////////////////////////////////////////////////////////////////////
#define THROW_ARANGO_EXCEPTION(code) \
throw triagens::arango::Exception(code, "", __FILE__, __LINE__)
////////////////////////////////////////////////////////////////////////////////
/// @brief throws an exception for internal errors
////////////////////////////////////////////////////////////////////////////////
#define THROW_ARANGO_EXCEPTION_STRING(code, details) \
throw triagens::arango::Exception(code, details, __FILE__, __LINE__)
// -----------------------------------------------------------------------------
// --SECTION-- public types
// -----------------------------------------------------------------------------
namespace triagens {
namespace arango {
////////////////////////////////////////////////////////////////////////////////
/// @brief arango exception type
////////////////////////////////////////////////////////////////////////////////
class Exception : public virtual std::exception {
public:
Exception (int code,
std::string const& details,
char const* file,
int line);
~Exception () throw ();
public:
char const * what () const throw ();
std::string message () const throw ();
int code () const throw();
protected:
std::string const _details;
char const* _file;
int const _line;
int const _code;
};
}
}
#endif
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:

View File

@ -176,6 +176,15 @@ typedef enum {
TRI_DOC_MARKER_COMMIT_TRANSACTION = 3101,
TRI_DOC_MARKER_ABORT_TRANSACTION = 3102,
TRI_DOC_MARKER_PREPARE_TRANSACTION = 3103,
TRI_WAL_MARKER_DOCUMENT_STANDALONE = 4000,
TRI_WAL_MARKER_EDGE_STANDALONE = 4001,
TRI_WAL_MARKER_DOCUMENT_TRANSACTION= 4002,
TRI_WAL_MARKER_EDGE_TRANSACTION = 4003,
TRI_WAL_MARKER_BEGIN_TRANSACTION = 4010,
TRI_WAL_MARKER_COMMIT_TRANSACTION = 4011,
TRI_WAL_MARKER_ABORT_TRANSACTION = 4012,
TRI_MARKER_MAX // again, this is not a real
// marker, but we use it for

View File

@ -41,10 +41,15 @@
#include "Wal/CollectorThread.h"
#include "Wal/Slots.h"
#include "Wal/SynchroniserThread.h"
#include "Wal/TestThread.h"
using namespace triagens::wal;
////////////////////////////////////////////////////////////////////////////////
/// @brief the logfile manager singleton
////////////////////////////////////////////////////////////////////////////////
static LogfileManager* Instance = nullptr;
// -----------------------------------------------------------------------------
// --SECTION-- class LogfileManager
// -----------------------------------------------------------------------------
@ -89,6 +94,8 @@ LogfileManager::LogfileManager (std::string* databasePath)
if (res != 0) {
THROW_INTERNAL_ERROR("could not compile regex");
}
_slots = new Slots(this, 1048576, 0);
}
////////////////////////////////////////////////////////////////////////////////
@ -98,6 +105,8 @@ LogfileManager::LogfileManager (std::string* databasePath)
LogfileManager::~LogfileManager () {
LOG_TRACE("shutting down wal logfile manager");
stop();
regfree(&_regex);
if (_slots != nullptr) {
@ -105,6 +114,29 @@ LogfileManager::~LogfileManager () {
}
}
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief get the logfile manager instance
////////////////////////////////////////////////////////////////////////////////
LogfileManager* LogfileManager::instance () {
assert(Instance != nullptr);
return Instance;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief initialise the logfile manager instance
////////////////////////////////////////////////////////////////////////////////
void LogfileManager::initialise (string* path) {
assert(Instance == nullptr);
Instance = new LogfileManager(path);
}
// -----------------------------------------------------------------------------
// --SECTION-- ApplicationFeature methods
// -----------------------------------------------------------------------------
@ -165,7 +197,10 @@ bool LogfileManager::prepare () {
////////////////////////////////////////////////////////////////////////////////
bool LogfileManager::start () {
_slots = new Slots(this, 1048576, 0);
if (_allocatorThread != nullptr) {
// we were already started
return true;
}
int res = inventory();
@ -242,22 +277,6 @@ bool LogfileManager::start () {
////////////////////////////////////////////////////////////////////////////////
bool LogfileManager::open () {
TestThread* threads[4];
for (size_t i = 0; i < 4; ++i) {
threads[i] = new TestThread(this);
threads[i]->start();
}
LOG_INFO("sleeping");
sleep(60);
for (size_t i = 0; i < 4; ++i) {
threads[i]->stop();
delete threads[i];
}
LOG_INFO("done");
return true;
}

View File

@ -76,6 +76,18 @@ namespace triagens {
~LogfileManager ();
////////////////////////////////////////////////////////////////////////////////
/// @brief get the logfile manager instance
////////////////////////////////////////////////////////////////////////////////
static LogfileManager* instance ();
////////////////////////////////////////////////////////////////////////////////
/// @brief initialise the logfile manager instance
////////////////////////////////////////////////////////////////////////////////
static void initialise (std::string*);
// -----------------------------------------------------------------------------
// --SECTION-- ApplicationFeature methods
// -----------------------------------------------------------------------------

View File

@ -96,12 +96,16 @@ void Slot::fill (void* src,
// set tick
marker->_tick = _tick;
// set size
marker->_size = static_cast<TRI_voc_size_t>(size);
// calculate the crc
marker->_crc = 0;
marker->_crc = 0;
TRI_voc_crc_t crc = TRI_InitialCrc32();
crc = TRI_BlockCrc32(crc, (char const*) marker, static_cast<TRI_voc_size_t>(size));
marker->_crc = TRI_FinalCrc32(crc);
// copy data into marker
memcpy(_mem, src, size);
}

View File

@ -121,7 +121,7 @@ Slot::TickType Slots::lastCommittedTick () {
SlotInfo Slots::nextUnused (uint32_t size) {
// we need to use the aligned size for writing
size = TRI_DF_ALIGN_BLOCK(size);
uint32_t alignedSize = TRI_DF_ALIGN_BLOCK(size);
bool hasWaited = false;
@ -146,7 +146,7 @@ SlotInfo Slots::nextUnused (uint32_t size) {
// cycle until we have a valid logfile
while (_logfile == nullptr ||
_logfile->freeSize() < static_cast<uint64_t>(size)) {
_logfile->freeSize() < static_cast<uint64_t>(alignedSize)) {
if (_logfile != nullptr) {
// seal existing logfile by creating a footer marker
@ -164,7 +164,7 @@ SlotInfo Slots::nextUnused (uint32_t size) {
// fetch the next free logfile (this may create a new one)
Logfile::StatusType status = Logfile::StatusType::UNKNOWN;
_logfile = _logfileManager->getWriteableLogfile(size, status);
_logfile = _logfileManager->getWriteableLogfile(alignedSize, status);
if (_logfile == nullptr) {
LOG_WARNING("unable to acquire writeable wal logfile!");
@ -190,7 +190,7 @@ SlotInfo Slots::nextUnused (uint32_t size) {
// if we get here, we got a free slot for the actual data...
char* mem = _logfile->reserve(size);
char* mem = _logfile->reserve(alignedSize);
if (mem == nullptr) {
return SlotInfo(TRI_ERROR_INTERNAL);

View File

@ -102,10 +102,14 @@ namespace triagens {
count = 0;
}
uint8_t const* getBuffer () {
uint8_t const* getBuffer () const {
// Only usable to copy out.
return bson_get_data(&_bson);
}
uint32_t getSize () const {
return _bson.len;
}
uint8_t* steal (uint32_t* length) {
// Ownership goes over to the caller.
@ -461,7 +465,7 @@ namespace triagens {
}
};
string EscapeUtf8ForJson (string s) {
inline string EscapeUtf8ForJson (string s) {
char* p = bson_utf8_escape_for_json (s.c_str(), s.size());
string res(p);
bson_free(p);