diff --git a/bindings/bindingtester/tests/api.py b/bindings/bindingtester/tests/api.py index cf7eb39b072..e31b8636fbd 100644 --- a/bindings/bindingtester/tests/api.py +++ b/bindings/bindingtester/tests/api.py @@ -18,7 +18,6 @@ # limitations under the License. # -import ctypes import random import struct @@ -169,7 +168,7 @@ def generate(self, args, thread_number): op_choices += resets idempotent_atomic_ops = [u'BIT_AND', u'BIT_OR', u'MAX', u'MIN', u'BYTE_MIN', u'BYTE_MAX'] - atomic_ops = idempotent_atomic_ops + [u'ADD', u'BIT_XOR'] + atomic_ops = idempotent_atomic_ops + [u'ADD', u'BIT_XOR', u'APPEND_IF_FITS'] if args.concurrency > 1: self.max_keys = random.randint(100, 1000) diff --git a/bindings/flow/tester/Tester.actor.cpp b/bindings/flow/tester/Tester.actor.cpp index bec2476837f..0acc9d885d7 100644 --- a/bindings/flow/tester/Tester.actor.cpp +++ b/bindings/flow/tester/Tester.actor.cpp @@ -1654,6 +1654,7 @@ void populateAtomicOpMap() { optionInfo["BIT_OR"] = FDBMutationType::FDB_MUTATION_TYPE_BIT_OR; optionInfo["XOR"] = FDBMutationType::FDB_MUTATION_TYPE_XOR; optionInfo["BIT_XOR"] = FDBMutationType::FDB_MUTATION_TYPE_BIT_XOR; + optionInfo["APPEND_IF_FITS"] = FDBMutationType::FDB_MUTATION_TYPE_APPEND_IF_FITS; optionInfo["MAX"] = FDBMutationType::FDB_MUTATION_TYPE_MAX; optionInfo["MIN"] = FDBMutationType::FDB_MUTATION_TYPE_MIN; optionInfo["SET_VERSIONSTAMPED_KEY"] = FDBMutationType::FDB_MUTATION_TYPE_SET_VERSIONSTAMPED_KEY; diff --git a/fdbclient/BackupAgent.h b/fdbclient/BackupAgent.h index 1b06315165c..cf0a343a0c3 100644 --- a/fdbclient/BackupAgent.h +++ b/fdbclient/BackupAgent.h @@ -421,7 +421,7 @@ Future logError(Database cx, Key keyErrors, const std::string& message); Future logError(Reference tr, Key keyErrors, const std::string& message); Future checkVersion(Reference const& tr); Future readCommitted(Database const& cx, PromiseStream const& results, Reference const& lock, KeyRangeRef const& range, bool const& terminator = true, bool const& systemAccess = false, bool const& lockAware = false); -Future readCommitted(Database const& cx, PromiseStream const& results, Future const& active, Reference const& lock, KeyRangeRef const& range, std::function< std::pair(Key key) > const& groupBy, bool const& terminator = true, bool const& systemAccess = false, bool const& lockAware = false, std::function< Future(Reference tr) > const& withEachFunction = nullptr); +Future readCommitted(Database const& cx, PromiseStream const& results, Future const& active, Reference const& lock, KeyRangeRef const& range, std::function< std::pair(Key key) > const& groupBy, bool const& terminator = true, bool const& systemAccess = false, bool const& lockAware = false); Future applyMutations(Database const& cx, Key const& uid, Key const& addPrefix, Key const& removePrefix, Version const& beginVersion, Version* const& endVersion, RequestStream const& commit, NotifiedVersion* const& committedVersion, Reference> const& keyVersion); typedef BackupAgentBase::enumState EBackupState; diff --git a/fdbclient/BackupAgentBase.actor.cpp b/fdbclient/BackupAgentBase.actor.cpp index e6e5cbbf908..cbd33d0e7ad 100644 --- a/fdbclient/BackupAgentBase.actor.cpp +++ b/fdbclient/BackupAgentBase.actor.cpp @@ -328,7 +328,7 @@ ACTOR Future readCommitted(Database cx, PromiseStream tr(new ReadYourWritesTransaction(cx)); + state Transaction tr(cx); state FlowLock::Releaser releaser; loop{ @@ -336,16 +336,16 @@ ACTOR Future readCommitted(Database cx, PromiseStreamROW_LIMIT_UNLIMITED, (g_network->isSimulated() && !g_simulator.speedUpSimulation) ? CLIENT_KNOBS->BACKUP_SIMULATED_LIMIT_BYTES : CLIENT_KNOBS->BACKUP_GET_RANGE_LIMIT_BYTES); if (systemAccess) - tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); + tr.setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); if (lockAware) - tr->setOption(FDBTransactionOptions::LOCK_AWARE); + tr.setOption(FDBTransactionOptions::LOCK_AWARE); //add lock releaser.release(); Void _ = wait(lock->take(TaskDefaultYield, limits.bytes + CLIENT_KNOBS->VALUE_SIZE_LIMIT + CLIENT_KNOBS->SYSTEM_KEY_SIZE_LIMIT)); releaser = FlowLock::Releaser(*lock, limits.bytes + CLIENT_KNOBS->VALUE_SIZE_LIMIT + CLIENT_KNOBS->SYSTEM_KEY_SIZE_LIMIT); - state Standalone values = wait(tr->getRange(begin, end, limits)); + state Standalone values = wait(tr.getRange(begin, end, limits)); // When this buggify line is enabled, if there are more than 1 result then use half of the results if(values.size() > 1 && BUGGIFY) { @@ -359,7 +359,7 @@ ACTOR Future readCommitted(Database cx, PromiseStream= 0); - results.send(RangeResultWithVersion(values, tr->getReadVersion().get())); + results.send(RangeResultWithVersion(values, tr.getReadVersion().get())); if (values.size() > 0) begin = firstGreaterThan(values.end()[-1].key); @@ -373,21 +373,21 @@ ACTOR Future readCommitted(Database cx, PromiseStream(new ReadYourWritesTransaction(cx)); + tr = Transaction(cx); } } } ACTOR Future readCommitted(Database cx, PromiseStream results, Future active, Reference lock, KeyRangeRef range, std::function< std::pair(Key key) > groupBy, - bool terminator, bool systemAccess, bool lockAware, std::function< Future(Reference tr) > withEachFunction) + bool terminator, bool systemAccess, bool lockAware) { state KeySelector nextKey = firstGreaterOrEqual(range.begin); state KeySelector end = firstGreaterOrEqual(range.end); state RCGroup rcGroup = RCGroup(); state uint64_t skipGroup(ULLONG_MAX); - state Reference tr(new ReadYourWritesTransaction(cx)); + state Transaction tr(cx); state FlowLock::Releaser releaser; loop{ @@ -395,14 +395,11 @@ ACTOR Future readCommitted(Database cx, PromiseStream results, Fu state GetRangeLimits limits(CLIENT_KNOBS->ROW_LIMIT_UNLIMITED, (g_network->isSimulated() && !g_simulator.speedUpSimulation) ? CLIENT_KNOBS->BACKUP_SIMULATED_LIMIT_BYTES : CLIENT_KNOBS->BACKUP_GET_RANGE_LIMIT_BYTES); if (systemAccess) - tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); + tr.setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); if (lockAware) - tr->setOption(FDBTransactionOptions::LOCK_AWARE); + tr.setOption(FDBTransactionOptions::LOCK_AWARE); - state Future withEach = Void(); - if (withEachFunction) withEach = withEachFunction(tr); - - state Standalone rangevalue = wait(tr->getRange(nextKey, end, limits)); + state Standalone rangevalue = wait(tr.getRange(nextKey, end, limits)); // When this buggify line is enabled, if there are more than 1 result then use half of the results if(rangevalue.size() > 1 && BUGGIFY) { @@ -413,8 +410,6 @@ ACTOR Future readCommitted(Database cx, PromiseStream results, Fu Void _ = wait(delay(6.0)); } - Void _ = wait(withEach); - //add lock Void _ = wait(active); releaser.release(); @@ -427,7 +422,7 @@ ACTOR Future readCommitted(Database cx, PromiseStream results, Fu //TraceEvent("log_readCommitted").detail("groupKey", groupKey).detail("skipGroup", skipGroup).detail("nextKey", printable(nextKey.key)).detail("end", printable(end.key)).detail("valuesize", value.size()).detail("index",index++).detail("size",s.value.size()); if (groupKey != skipGroup){ if (rcGroup.version == -1){ - rcGroup.version = tr->getReadVersion().get(); + rcGroup.version = tr.getReadVersion().get(); rcGroup.groupKey = groupKey; } else if (rcGroup.groupKey != groupKey) { @@ -444,7 +439,7 @@ ACTOR Future readCommitted(Database cx, PromiseStream results, Fu skipGroup = rcGroup.groupKey; rcGroup = RCGroup(); - rcGroup.version = tr->getReadVersion().get(); + rcGroup.version = tr.getReadVersion().get(); rcGroup.groupKey = groupKey; } rcGroup.items.push_back_deep(rcGroup.items.arena(), s); @@ -469,94 +464,13 @@ ACTOR Future readCommitted(Database cx, PromiseStream results, Fu catch (Error &e) { if (e.code() != error_code_transaction_too_old && e.code() != error_code_future_version) throw; - Void _ = wait(tr->onError(e)); + Void _ = wait(tr.onError(e)); } } } -ACTOR Future readCommitted(Database cx, PromiseStream results, Reference lock, - KeyRangeRef range, std::function< std::pair(Key key) > groupBy) -{ - state KeySelector nextKey = firstGreaterOrEqual(range.begin); - state KeySelector end = firstGreaterOrEqual(range.end); - - state RCGroup rcGroup = RCGroup(); - state uint64_t skipGroup(ULLONG_MAX); - state Reference tr(new ReadYourWritesTransaction(cx)); - state FlowLock::Releaser releaser; - - loop{ - try { - state GetRangeLimits limits(CLIENT_KNOBS->ROW_LIMIT_UNLIMITED, (g_network->isSimulated() && !g_simulator.speedUpSimulation) ? CLIENT_KNOBS->BACKUP_SIMULATED_LIMIT_BYTES : CLIENT_KNOBS->BACKUP_GET_RANGE_LIMIT_BYTES); - - tr->setOption(FDBTransactionOptions::ACCESS_SYSTEM_KEYS); - tr->setOption(FDBTransactionOptions::LOCK_AWARE); - - state Standalone rangevalue = wait(tr->getRange(nextKey, end, limits)); - - // When this buggify line is enabled, if there are more than 1 result then use half of the results - if(rangevalue.size() > 1 && BUGGIFY) { - rangevalue.resize(rangevalue.arena(), rangevalue.size() / 2); - rangevalue.more = true; - // Half of the time wait for this tr to expire so that the next read is at a different version - if(g_random->random01() < 0.5) - Void _ = wait(delay(6.0)); - } - - releaser.release(); - Void _ = wait(lock->take(TaskDefaultYield, rangevalue.expectedSize() + rcGroup.items.expectedSize())); - releaser = FlowLock::Releaser(*lock, rangevalue.expectedSize() + rcGroup.items.expectedSize()); - - int index(0); - for (auto & s : rangevalue){ - uint64_t groupKey = groupBy(s.key).first; - //TraceEvent("log_readCommitted").detail("groupKey", groupKey).detail("skipGroup", skipGroup).detail("nextKey", printable(nextKey.key)).detail("end", printable(end.key)).detail("valuesize", value.size()).detail("index",index++).detail("size",s.value.size()); - if (groupKey != skipGroup){ - if (rcGroup.version == -1){ - rcGroup.version = tr->getReadVersion().get(); - rcGroup.groupKey = groupKey; - } - else if (rcGroup.groupKey != groupKey) { - //TraceEvent("log_readCommitted").detail("sendGroup0", rcGroup.groupKey).detail("itemSize", rcGroup.items.size()).detail("data_length",rcGroup.items[0].value.size()); - state uint32_t len(0); - for (size_t j = 0; j < rcGroup.items.size(); ++j) { - len += rcGroup.items[j].value.size(); - } - //TraceEvent("SendGroup").detail("groupKey", rcGroup.groupKey).detail("version", rcGroup.version).detail("length", len).detail("releaser.remaining", releaser.remaining); - releaser.remaining -= rcGroup.items.expectedSize(); //its the responsibility of the caller to release after this point - ASSERT(releaser.remaining >= 0); - results.send(rcGroup); - nextKey = firstGreaterThan(rcGroup.items.end()[-1].key); - skipGroup = rcGroup.groupKey; - - rcGroup = RCGroup(); - rcGroup.version = tr->getReadVersion().get(); - rcGroup.groupKey = groupKey; - } - rcGroup.items.push_back_deep(rcGroup.items.arena(), s); - } - } - - if (!rangevalue.more) { - if (rcGroup.version != -1){ - releaser.remaining -= rcGroup.items.expectedSize(); //its the responsibility of the caller to release after this point - ASSERT(releaser.remaining >= 0); - //TraceEvent("log_readCommitted").detail("sendGroup1", rcGroup.groupKey).detail("itemSize", rcGroup.items.size()).detail("data_length", rcGroup.items[0].value.size()); - results.send(rcGroup); - } - - results.sendError(end_of_stream()); - return Void(); - } - - nextKey = firstGreaterThan(rangevalue.end()[-1].key); - } - catch (Error &e) { - if (e.code() != error_code_transaction_too_old && e.code() != error_code_future_version) - throw; - Void _ = wait(tr->onError(e)); - } - } +Future readCommitted(Database cx, PromiseStream results, Reference lock, KeyRangeRef range, std::function< std::pair(Key key) > groupBy) { + return readCommitted(cx, results, Void(), lock, range, groupBy, true, true, true); } ACTOR Future dumpData(Database cx, PromiseStream results, Reference lock, Key uid, Key addPrefix, Key removePrefix, RequestStream commit, diff --git a/fdbclient/DatabaseBackupAgent.actor.cpp b/fdbclient/DatabaseBackupAgent.actor.cpp index 32f9d28564c..f8f9abba275 100644 --- a/fdbclient/DatabaseBackupAgent.actor.cpp +++ b/fdbclient/DatabaseBackupAgent.actor.cpp @@ -651,7 +651,7 @@ namespace dbBackup { for (int i = 0; i < ranges.size(); ++i) { results.push_back(PromiseStream()); - rc.push_back(readCommitted(taskBucket->src, results[i], Future(Void()), lock, ranges[i], decodeBKMutationLogKey, true, true, true, nullptr)); + rc.push_back(readCommitted(taskBucket->src, results[i], Future(Void()), lock, ranges[i], decodeBKMutationLogKey, true, true, true)); dump.push_back(dumpData(cx, task, results[i], lock.getPtr(), taskBucket)); } diff --git a/fdbclient/ReadYourWrites.actor.cpp b/fdbclient/ReadYourWrites.actor.cpp index c1188d3ceda..5452215d941 100644 --- a/fdbclient/ReadYourWrites.actor.cpp +++ b/fdbclient/ReadYourWrites.actor.cpp @@ -1479,7 +1479,7 @@ void ReadYourWritesTransaction::atomicOp( const KeyRef& key, const ValueRef& ope if(key >= getMaxWriteKey()) throw key_outside_legal_range(); - if(!isValidMutationType(operationType) || !isAtomicOp((MutationRef::Type) operationType) || operationType == MutationRef::AppendIfFits) + if(!isValidMutationType(operationType) || !isAtomicOp((MutationRef::Type) operationType)) throw invalid_mutation_type(); if(key.size() > (key.startsWith(systemKeys.begin) ? CLIENT_KNOBS->SYSTEM_KEY_SIZE_LIMIT : CLIENT_KNOBS->KEY_SIZE_LIMIT)) @@ -1898,4 +1898,4 @@ void ReadYourWritesTransaction::debugLogRetries(Optional error) { transactionDebugInfo->lastRetryLogTime = now(); } } -} \ No newline at end of file +} diff --git a/fdbclient/vexillographer/fdb.options b/fdbclient/vexillographer/fdb.options index 17a5af781b9..9714bc4cf8a 100644 --- a/fdbclient/vexillographer/fdb.options +++ b/fdbclient/vexillographer/fdb.options @@ -217,6 +217,9 @@ description is not currently required but encouraged.