RAMCloud bug fix: atomic increment
- This is backport of patch I've submitted to RAMCloud master to 1.0 code base we use.
- NOTE: You will need to rebuild RAMCloud in order to use atomic increment APIs.
(Currently only used in SharedLog experiment.)
Change-Id: I5f0abd1da6014cbf1edb315fe556aec8cc8407d3
diff --git a/ramcloud-build-scripts/increment_fix.patch b/ramcloud-build-scripts/increment_fix.patch
new file mode 100644
index 0000000..a764b63
--- /dev/null
+++ b/ramcloud-build-scripts/increment_fix.patch
@@ -0,0 +1,57 @@
+diff --git a/src/MasterService.cc b/src/MasterService.cc
+index 93cfb5d..38d250f 100644
+--- a/src/MasterService.cc
++++ b/src/MasterService.cc
+@@ -1750,25 +1750,38 @@ MasterService::increment(const WireFormat::Increment::Request* reqHdr,
+ Status *status = &respHdr->common.status;
+
+ Buffer value;
++ uint64_t version;
++ int64_t newValue;
+ RejectRules rejectRules = reqHdr->rejectRules;
+- *status = objectManager.readObject(key, &value, &rejectRules, NULL);
+- if (*status != STATUS_OK)
+- return;
++ RejectRules updateRejectRules;
++ memset(&updateRejectRules, 0, sizeof(updateRejectRules));
+
+- if (value.getTotalLength() != sizeof(int64_t)) {
+- *status = STATUS_INVALID_OBJECT;
+- return;
+- }
++ do {
++ value.reset();
++ *status = objectManager.readObject(key, &value, &rejectRules, &version);
++ if (*status != STATUS_OK)
++ return;
++
++ if (value.getTotalLength() != sizeof(int64_t)) {
++ *status = STATUS_INVALID_OBJECT;
++ return;
++ }
++
++ const int64_t oldValue = *value.getOffset<int64_t>(0);
++ newValue = oldValue + reqHdr->incrementValue;
++
++ // Write the new value back
++ Buffer newValueBuffer;
++ newValueBuffer.append(&newValue, sizeof(int64_t));
+
+- const int64_t oldValue = *value.getOffset<int64_t>(0);
+- int64_t newValue = oldValue + reqHdr->incrementValue;
++ // reject rule to check atomic update
++ updateRejectRules.givenVersion = version;
++ updateRejectRules.versionNeGiven = true;
+
+- // Write the new value back
+- Buffer newValueBuffer;
+- newValueBuffer.append(&newValue, sizeof(int64_t));
++ *status = objectManager.writeObject(key, newValueBuffer,
++ &updateRejectRules, &respHdr->version);
++ } while (*status == STATUS_WRONG_VERSION);
+
+- *status = objectManager.writeObject(key, newValueBuffer,
+- &rejectRules, &respHdr->version);
+ if (*status != STATUS_OK)
+ return;
+ objectManager.syncChanges();