Merge pull request #2641 from atn34/atn34/configure-locked
Allow a new database to be configured locked
This commit is contained in:
commit
5e78d0ad1c
|
@ -1774,6 +1774,10 @@ ACTOR Future<bool> configure( Database db, std::vector<StringRef> tokens, Refere
|
|||
printf("Configuration changed\n");
|
||||
ret=false;
|
||||
break;
|
||||
case ConfigurationResult::LOCKED_NOT_NEW:
|
||||
printf("ERROR: `only new databases can be configured as locked`\n");
|
||||
ret = true;
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
ret=true;
|
||||
|
|
|
@ -52,6 +52,13 @@ std::map<std::string, std::string> configForToken( std::string const& mode ) {
|
|||
return out;
|
||||
}
|
||||
|
||||
if (mode == "locked") {
|
||||
// Setting this key is interpreted as an instruction to use the normal version-stamp-based mechanism for locking
|
||||
// the database.
|
||||
out[databaseLockedKey.toString()] = deterministicRandom()->randomUniqueID().toString();
|
||||
return out;
|
||||
}
|
||||
|
||||
size_t pos;
|
||||
|
||||
// key:=value is unvalidated and unchecked
|
||||
|
@ -297,6 +304,17 @@ ACTOR Future<ConfigurationResult::Type> changeConfig( Database cx, std::map<std:
|
|||
// make sure we have essential configuration options
|
||||
std::string initKey = configKeysPrefix.toString() + "initialized";
|
||||
state bool creating = m.count( initKey ) != 0;
|
||||
state Optional<UID> locked;
|
||||
{
|
||||
auto iter = m.find(databaseLockedKey.toString());
|
||||
if (iter != m.end()) {
|
||||
if (!creating) {
|
||||
return ConfigurationResult::LOCKED_NOT_NEW;
|
||||
}
|
||||
locked = UID::fromString(iter->second);
|
||||
m.erase(iter);
|
||||
}
|
||||
}
|
||||
if (creating) {
|
||||
m[initIdKey.toString()] = deterministicRandom()->randomUniqueID().toString();
|
||||
if (!isCompleteConfiguration(m)) {
|
||||
|
@ -484,7 +502,16 @@ ACTOR Future<ConfigurationResult::Type> changeConfig( Database cx, std::map<std:
|
|||
tr.addReadConflictRange( singleKeyRange(m.begin()->first) );
|
||||
}
|
||||
|
||||
for(auto i=m.begin(); i!=m.end(); ++i)
|
||||
if (locked.present()) {
|
||||
ASSERT(creating);
|
||||
tr.atomicOp(databaseLockedKey,
|
||||
BinaryWriter::toValue(locked.get(), Unversioned())
|
||||
.withPrefix(LiteralStringRef("0123456789"))
|
||||
.withSuffix(LiteralStringRef("\x00\x00\x00\x00")),
|
||||
MutationRef::SetVersionstampedValue);
|
||||
}
|
||||
|
||||
for (auto i = m.begin(); i != m.end(); ++i)
|
||||
tr.set( StringRef(i->first), StringRef(i->second) );
|
||||
|
||||
tr.addReadConflictRange( singleKeyRange(moveKeysLockOwnerKey) );
|
||||
|
|
|
@ -61,7 +61,8 @@ public:
|
|||
NOT_ENOUGH_WORKERS,
|
||||
REGION_REPLICATION_MISMATCH,
|
||||
DCID_MISSING,
|
||||
SUCCESS
|
||||
LOCKED_NOT_NEW,
|
||||
SUCCESS,
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1088,11 +1088,14 @@ void SimulationConfig::generateNormalConfig(int minimumReplication, int minimumR
|
|||
void setupSimulatedSystem(vector<Future<Void>>* systemActors, std::string baseFolder, int* pTesterCount,
|
||||
Optional<ClusterConnectionString>* pConnString, Standalone<StringRef>* pStartingConfiguration,
|
||||
int extraDB, int minimumReplication, int minimumRegions, Reference<TLSOptions> tlsOptions,
|
||||
std::string whitelistBinPaths) {
|
||||
std::string whitelistBinPaths, bool configureLocked) {
|
||||
// SOMEDAY: this does not test multi-interface configurations
|
||||
SimulationConfig simconfig(extraDB, minimumReplication, minimumRegions);
|
||||
StatusObject startingConfigJSON = simconfig.db.toJSON(true);
|
||||
std::string startingConfigString = "new";
|
||||
if (configureLocked) {
|
||||
startingConfigString += " locked";
|
||||
}
|
||||
for( auto kv : startingConfigJSON) {
|
||||
startingConfigString += " ";
|
||||
if( kv.second.type() == json_spirit::int_type ) {
|
||||
|
@ -1351,7 +1354,8 @@ void setupSimulatedSystem(vector<Future<Void>>* systemActors, std::string baseFo
|
|||
.detail("StartingConfiguration", pStartingConfiguration->toString());
|
||||
}
|
||||
|
||||
void checkExtraDB(const char *testFile, int &extraDB, int &minimumReplication, int &minimumRegions) {
|
||||
void checkTestConf(const char* testFile, int& extraDB, int& minimumReplication, int& minimumRegions,
|
||||
int& configureLocked) {
|
||||
std::ifstream ifs;
|
||||
ifs.open(testFile, std::ifstream::in);
|
||||
if (!ifs.good())
|
||||
|
@ -1383,6 +1387,10 @@ void checkExtraDB(const char *testFile, int &extraDB, int &minimumReplication, i
|
|||
if (attrib == "minimumRegions") {
|
||||
sscanf( value.c_str(), "%d", &minimumRegions );
|
||||
}
|
||||
|
||||
if (attrib == "configureLocked") {
|
||||
sscanf(value.c_str(), "%d", &configureLocked);
|
||||
}
|
||||
}
|
||||
|
||||
ifs.close();
|
||||
|
@ -1396,7 +1404,8 @@ ACTOR void setupAndRun(std::string dataFolder, const char *testFile, bool reboot
|
|||
state int extraDB = 0;
|
||||
state int minimumReplication = 0;
|
||||
state int minimumRegions = 0;
|
||||
checkExtraDB(testFile, extraDB, minimumReplication, minimumRegions);
|
||||
state int configureLocked = 0;
|
||||
checkTestConf(testFile, extraDB, minimumReplication, minimumRegions, configureLocked);
|
||||
|
||||
// TODO (IPv6) Use IPv6?
|
||||
wait(g_simulator.onProcess(
|
||||
|
@ -1427,7 +1436,7 @@ ACTOR void setupAndRun(std::string dataFolder, const char *testFile, bool reboot
|
|||
else {
|
||||
g_expect_full_pointermap = 1;
|
||||
setupSimulatedSystem(&systemActors, dataFolder, &testerCount, &connFile, &startingConfiguration, extraDB,
|
||||
minimumReplication, minimumRegions, tlsOptions, whitelistBinPaths);
|
||||
minimumReplication, minimumRegions, tlsOptions, whitelistBinPaths, configureLocked);
|
||||
wait( delay(1.0) ); // FIXME: WHY!!! //wait for machines to boot
|
||||
}
|
||||
std::string clusterFileDir = joinPath( dataFolder, deterministicRandom()->randomUniqueID().toString() );
|
||||
|
|
|
@ -970,6 +970,8 @@ vector<TestSpec> readTests( ifstream& ifs ) {
|
|||
TraceEvent("TestParserTest").detail("ParsedSimDrAgents", spec.simDrAgents);
|
||||
} else if( attrib == "extraDB" ) {
|
||||
TraceEvent("TestParserTest").detail("ParsedExtraDB", "");
|
||||
} else if ( attrib == "configureLocked" ) {
|
||||
TraceEvent("TestParserTest").detail("ParsedConfigureLocked", "");
|
||||
} else if( attrib == "minimumReplication" ) {
|
||||
TraceEvent("TestParserTest").detail("ParsedMinimumReplication", "");
|
||||
} else if( attrib == "minimumRegions" ) {
|
||||
|
|
|
@ -27,12 +27,14 @@
|
|||
struct LockDatabaseWorkload : TestWorkload {
|
||||
double lockAfter, unlockAfter;
|
||||
bool ok;
|
||||
bool onlyCheckLocked;
|
||||
|
||||
LockDatabaseWorkload(WorkloadContext const& wcx)
|
||||
: TestWorkload(wcx), ok(true)
|
||||
{
|
||||
lockAfter = getOption( options, LiteralStringRef("lockAfter"), 0.0 );
|
||||
unlockAfter = getOption( options, LiteralStringRef("unlockAfter"), 10.0 );
|
||||
onlyCheckLocked = getOption(options, LiteralStringRef("onlyCheckLocked"), false);
|
||||
ASSERT(unlockAfter > lockAfter);
|
||||
}
|
||||
|
||||
|
@ -42,9 +44,8 @@ struct LockDatabaseWorkload : TestWorkload {
|
|||
return Void();
|
||||
}
|
||||
|
||||
virtual Future<Void> start( Database const& cx ) {
|
||||
if( clientId == 0 )
|
||||
return lockWorker( cx, this );
|
||||
virtual Future<Void> start(Database const& cx) {
|
||||
if (clientId == 0) return onlyCheckLocked ? timeout(checkLocked(cx, this), 60, Void()) : lockWorker(cx, this);
|
||||
return Void();
|
||||
}
|
||||
|
||||
|
@ -110,6 +111,7 @@ struct LockDatabaseWorkload : TestWorkload {
|
|||
self->ok = false;
|
||||
return Void();
|
||||
} catch( Error &e ) {
|
||||
TEST(e.code() == error_code_database_locked); // Database confirmed locked
|
||||
wait( tr.onError(e) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ if(WITH_PYTHON)
|
|||
add_fdb_test(TEST_FILES fast/BackupToDBCorrectness.txt)
|
||||
add_fdb_test(TEST_FILES fast/BackupToDBCorrectnessClean.txt)
|
||||
add_fdb_test(TEST_FILES fast/CloggedSideband.txt)
|
||||
add_fdb_test(TEST_FILES fast/ConfigureLocked.txt)
|
||||
add_fdb_test(TEST_FILES fast/ConstrainedRandomSelector.txt)
|
||||
add_fdb_test(TEST_FILES fast/CycleAndLock.txt)
|
||||
add_fdb_test(TEST_FILES fast/CycleTest.txt)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
testTitle=ConfigureLocked
|
||||
testName=LockDatabase
|
||||
configureLocked=1
|
||||
onlyCheckLocked=true
|
||||
runConsistencyCheck=false
|
||||
clearAfterTest=false
|
Loading…
Reference in New Issue