1
0
Fork 0
arangodb/arangod/StorageEngine/TransactionCollection.cpp

131 lines
4.3 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB 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 "TransactionCollection.h"
#include "Logger/Logger.h"
#include "StorageEngine/TransactionState.h"
#include "VocBase/LogicalCollection.h"
using namespace arangodb;
TransactionCollection::~TransactionCollection() {
TRI_ASSERT(_collection == nullptr);
}
std::string TransactionCollection::collectionName() const {
TRI_ASSERT(_collection != nullptr);
return _collection->name();
}
static_assert(AccessMode::Type::NONE < AccessMode::Type::READ &&
AccessMode::Type::READ < AccessMode::Type::WRITE &&
AccessMode::Type::WRITE < AccessMode::Type::EXCLUSIVE,
"AccessMode::Type total order fail");
/// @brief check if a collection is locked in a specific mode in a transaction
bool TransactionCollection::isLocked(AccessMode::Type accessType, int nestingLevel) const {
if (accessType > _accessType) {
// wrong lock type
LOG_TOPIC("39ef2", WARN, arangodb::Logger::ENGINES)
<< "logic error. checking wrong lock type";
return false;
}
return isLocked();
}
bool TransactionCollection::isLocked() const {
if (_collection == nullptr) {
return false;
}
return _lockType > AccessMode::Type::NONE;
}
/// @brief request a main-level lock for a collection
/// returns TRI_ERROR_LOCKED in case the lock was successfully acquired
/// returns TRI_ERROR_NO_ERROR in case the lock does not need to be acquired and
/// no other error occurred returns any other error code otherwise
int TransactionCollection::lockRecursive() {
return lockRecursive(_accessType, 0);
}
/// @brief request a lock for a collection
/// returns TRI_ERROR_LOCKED in case the lock was successfully acquired
/// returns TRI_ERROR_NO_ERROR in case the lock does not need to be acquired and
/// no other error occurred returns any other error code otherwise
int TransactionCollection::lockRecursive(AccessMode::Type accessType, int nestingLevel) {
if (AccessMode::isWriteOrExclusive(accessType) &&
!AccessMode::isWriteOrExclusive(_accessType)) {
// wrong lock type
return TRI_ERROR_INTERNAL;
}
if (isLocked()) {
// already locked
return TRI_ERROR_NO_ERROR;
}
return doLock(accessType, nestingLevel);
}
/// @brief request an unlock for a collection
int TransactionCollection::unlockRecursive(AccessMode::Type accessType, int nestingLevel) {
if (AccessMode::isWriteOrExclusive(accessType) &&
!AccessMode::isWriteOrExclusive(_accessType)) {
// wrong lock type: write-unlock requested but collection is read-only
return TRI_ERROR_INTERNAL;
}
if (!isLocked()) {
// already unlocked
return TRI_ERROR_NO_ERROR;
}
return doUnlock(accessType, nestingLevel);
}
Result TransactionCollection::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 Result(TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION,
std::string(TRI_errno_string(TRI_ERROR_TRANSACTION_UNREGISTERED_COLLECTION)) + ": " + collectionName() +
" [" + AccessMode::typeString(accessType) + "]");
}
TRI_ASSERT(nestingLevel == 0);
// upgrade collection type to write-access
_accessType = accessType;
}
adjustNestingLevel(nestingLevel);
// all correct
return {};
}