mirror of https://gitee.com/bigwinds/arangodb
180 lines
5.8 KiB
C++
180 lines
5.8 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
|
/// Copyright 2004-2014 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 ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// @author Jan Steemann
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "RocksDBTransactionCollection.h"
|
|
#include "Basics/Exceptions.h"
|
|
#include "Cluster/CollectionLockState.h"
|
|
#include "Logger/Logger.h"
|
|
#include "RocksDBCollection.h"
|
|
#include "StorageEngine/TransactionState.h"
|
|
#include "Transaction/Methods.h"
|
|
#include "Transaction/Hints.h"
|
|
#include "VocBase/LogicalCollection.h"
|
|
#include "VocBase/modes.h"
|
|
|
|
using namespace arangodb;
|
|
|
|
RocksDBTransactionCollection::RocksDBTransactionCollection(TransactionState* trx,
|
|
TRI_voc_cid_t cid,
|
|
AccessMode::Type accessType)
|
|
: TransactionCollection(trx, cid),
|
|
_accessType(accessType),
|
|
_operationSize(0),
|
|
_numInserts(0),
|
|
_numUpdates(0),
|
|
_numRemoves(0) {}
|
|
|
|
RocksDBTransactionCollection::~RocksDBTransactionCollection() {}
|
|
|
|
/// @brief request a main-level lock for a collection
|
|
int RocksDBTransactionCollection::lock() { return TRI_ERROR_NO_ERROR; }
|
|
|
|
/// @brief request a lock for a collection
|
|
int RocksDBTransactionCollection::lock(AccessMode::Type accessType, int /*nestingLevel*/) {
|
|
if (isWrite(accessType) && !isWrite(_accessType)) {
|
|
// wrong lock type
|
|
return TRI_ERROR_INTERNAL;
|
|
}
|
|
|
|
return TRI_ERROR_NO_ERROR;
|
|
}
|
|
|
|
/// @brief request an unlock for a collection
|
|
int RocksDBTransactionCollection::unlock(AccessMode::Type accessType, int /*nestingLevel*/) {
|
|
if (isWrite(accessType) && !isWrite(_accessType)) {
|
|
// wrong lock type: write-unlock requested but collection is read-only
|
|
return TRI_ERROR_INTERNAL;
|
|
}
|
|
|
|
return TRI_ERROR_NO_ERROR;
|
|
}
|
|
|
|
/// @brief check if a collection is locked in a specific mode in a transaction
|
|
bool RocksDBTransactionCollection::isLocked(AccessMode::Type accessType, int /*nestingLevel*/) const {
|
|
if (isWrite(accessType) && !isWrite(_accessType)) {
|
|
// wrong lock type
|
|
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "logic error. checking wrong lock type";
|
|
return false;
|
|
}
|
|
|
|
// TODO
|
|
return false;
|
|
}
|
|
|
|
/// @brief check whether a collection is locked at all
|
|
bool RocksDBTransactionCollection::isLocked() const {
|
|
// TODO
|
|
return false;
|
|
}
|
|
|
|
/// @brief whether or not any write operations for the collection happened
|
|
bool RocksDBTransactionCollection::hasOperations() const {
|
|
return (_numInserts > 0 || _numRemoves > 0 || _numUpdates > 0);
|
|
}
|
|
|
|
void RocksDBTransactionCollection::freeOperations(transaction::Methods* /*activeTrx*/, bool /*mustRollback*/) {}
|
|
|
|
bool RocksDBTransactionCollection::canAccess(AccessMode::Type accessType) const {
|
|
// check if access type matches
|
|
if (AccessMode::isWriteOrExclusive(accessType) &&
|
|
!AccessMode::isWriteOrExclusive(_accessType)) {
|
|
// type doesn't match. probably also a mistake by the caller
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int RocksDBTransactionCollection::updateUsage(AccessMode::Type accessType, int nestingLevel) {
|
|
if (AccessMode::isWriteOrExclusive(accessType) &&
|
|
!AccessMode::isWriteOrExclusive(_accessType)) {
|
|
if (nestingLevel > 0) {
|
|
// trying to write access a collection that is only marked with
|
|
// read-access
|
|
return TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION;
|
|
}
|
|
|
|
TRI_ASSERT(nestingLevel == 0);
|
|
|
|
// upgrade collection type to write-access
|
|
_accessType = accessType;
|
|
}
|
|
|
|
// all correct
|
|
return TRI_ERROR_NO_ERROR;
|
|
}
|
|
|
|
int RocksDBTransactionCollection::use(int nestingLevel) {
|
|
if (_collection == nullptr) {
|
|
TRI_vocbase_col_status_e status;
|
|
LOG_TRX(_transaction, nestingLevel) << "using collection " << _cid;
|
|
_collection = _transaction->vocbase()->useCollection(_cid, status);
|
|
|
|
if (_collection == nullptr) {
|
|
return TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND;
|
|
}
|
|
|
|
if (AccessMode::isWriteOrExclusive(_accessType) &&
|
|
TRI_GetOperationModeServer() == TRI_VOCBASE_MODE_NO_CREATE &&
|
|
!LogicalCollection::IsSystemName(_collection->name())) {
|
|
return TRI_ERROR_ARANGO_READ_ONLY;
|
|
}
|
|
}
|
|
|
|
return TRI_ERROR_NO_ERROR;
|
|
}
|
|
|
|
void RocksDBTransactionCollection::unuse(int /*nestingLevel*/) {}
|
|
|
|
void RocksDBTransactionCollection::release() {
|
|
// the top level transaction releases all collections
|
|
if (_collection != nullptr) {
|
|
// unuse collection, remove usage-lock
|
|
LOG_TRX(_transaction, 0) << "unusing collection " << _cid;
|
|
|
|
_transaction->vocbase()->releaseCollection(_collection);
|
|
_collection = nullptr;
|
|
}
|
|
}
|
|
|
|
/// @brief add an operation for a transaction collection
|
|
void RocksDBTransactionCollection::addOperation(TRI_voc_document_operation_e operationType,
|
|
uint64_t operationSize) {
|
|
switch (operationType) {
|
|
case TRI_VOC_DOCUMENT_OPERATION_UNKNOWN:
|
|
break;
|
|
case TRI_VOC_DOCUMENT_OPERATION_INSERT:
|
|
++_numInserts;
|
|
break;
|
|
case TRI_VOC_DOCUMENT_OPERATION_UPDATE:
|
|
case TRI_VOC_DOCUMENT_OPERATION_REPLACE:
|
|
++_numUpdates;
|
|
break;
|
|
case TRI_VOC_DOCUMENT_OPERATION_REMOVE:
|
|
++_numRemoves;
|
|
break;
|
|
}
|
|
|
|
_operationSize += operationSize;
|
|
}
|