1
0
Fork 0
arangodb/arangod/RocksDBEngine/RocksDBUpgrade.cpp

125 lines
4.5 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2018 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 Simon Grätzer
////////////////////////////////////////////////////////////////////////////////
#include "RocksDBUpgrade.h"
#include "Logger/Logger.h"
#include "RocksDBEngine/RocksDBColumnFamily.h"
#include "RocksDBEngine/RocksDBCommon.h"
#include "RocksDBEngine/RocksDBFormat.h"
#include <rocksdb/convenience.h>
#include <rocksdb/db.h>
#include <rocksdb/env.h>
#include <rocksdb/filter_policy.h>
#include <rocksdb/iterator.h>
#include <rocksdb/options.h>
#include <rocksdb/slice_transform.h>
#include <rocksdb/statistics.h>
#include <rocksdb/table.h>
#include <rocksdb/transaction_log.h>
#include <rocksdb/utilities/transaction_db.h>
#include <rocksdb/write_batch.h>
#include <velocypack/Iterator.h>
#include <velocypack/velocypack-aliases.h>
using namespace arangodb;
void arangodb::rocksdbStartupVersionCheck(rocksdb::TransactionDB* db, bool dbExisted) {
static_assert(std::is_same<char, std::underlying_type<RocksDBEndianness>::type>::value,
"RocksDBEndianness has wrong type");
// try to find version
char version = rocksDBFormatVersion();
RocksDBKey versionKey, endianKey;
versionKey.constructSettingsValue(RocksDBSettingsType::Version);
endianKey.constructSettingsValue(RocksDBSettingsType::Endianness);
// read the co
rocksdb::PinnableSlice oldVersion;
rocksdb::Status s;
s = db->Get(rocksdb::ReadOptions(), RocksDBColumnFamily::definitions(),
versionKey.string(), &oldVersion);
// default endianess for existing DBs
RocksDBEndianness endianess = RocksDBEndianness::Invalid;
if (dbExisted) {
if (s.IsNotFound() || oldVersion.size() != 1) {
LOG_TOPIC("614d7", FATAL, Logger::ENGINES) << "Your db directory is invalid";
FATAL_ERROR_EXIT();
} else if (oldVersion.data()[0] < version) {
// Performing 'upgrade' routine
if (oldVersion.data()[0] == '0' && version == '1') {
endianess = RocksDBEndianness::Little;
} else {
LOG_TOPIC("c30ee", FATAL, Logger::ENGINES)
<< "Your db directory is in an old "
<< "format. Please downgrade the server, "
<< "export & re-import your data.";
FATAL_ERROR_EXIT();
}
} else if (oldVersion.data()[0] > version) {
LOG_TOPIC("c9009", FATAL, Logger::ENGINES)
<< "You are using an old version of ArangoDB, please update "
<< "before opening this dir.";
FATAL_ERROR_EXIT();
} else {
TRI_ASSERT(oldVersion.data()[0] == version);
// read current endianess
rocksdb::PinnableSlice endianSlice;
s = db->Get(rocksdb::ReadOptions(), RocksDBColumnFamily::definitions(),
endianKey.string(), &endianSlice);
if (s.ok() && endianSlice.size() == 1) {
TRI_ASSERT(endianSlice.data()[0] == 'L' || endianSlice.data()[0] == 'B');
endianess = static_cast<RocksDBEndianness>(endianSlice.data()[0]);
} else {
LOG_TOPIC("b0083", FATAL, Logger::ENGINES)
<< "Error reading key-format, your db directory is invalid";
FATAL_ERROR_EXIT();
}
}
} else {
// new DBs are always created with Big endian data-format
endianess = RocksDBEndianness::Big;
}
// enable correct key format
rocksutils::setRocksDBKeyFormatEndianess(endianess);
// store endianess forever
const char endVal = static_cast<char>(endianess);
s = db->Put(rocksdb::WriteOptions(), RocksDBColumnFamily::definitions(),
endianKey.string(), rocksdb::Slice(&endVal, sizeof(char)));
if (!s.ok()) {
LOG_TOPIC("3d88b", FATAL, Logger::ENGINES) << "Error storing endianess";
FATAL_ERROR_EXIT();
}
// store current version
s = db->Put(rocksdb::WriteOptions(), RocksDBColumnFamily::definitions(),
versionKey.string(), rocksdb::Slice(&version, sizeof(char)));
TRI_ASSERT(s.ok());
}