| 163 | } |
| 164 | |
| 165 | ACTOR Future<Void> cycleClient(Database cx, MiniCycleWorkload* self, double delay) { |
| 166 | state double lastTime = now(); |
| 167 | try { |
| 168 | loop { |
| 169 | wait(poisson(&lastTime, delay)); |
| 170 | |
| 171 | state double tstart = now(); |
| 172 | state int r = |
| 173 | deterministicRandom()->randomInt(self->beginKey(self->clientId), self->endKey(self->clientId) - 1); |
| 174 | state Transaction tr(cx); |
| 175 | if (deterministicRandom()->random01() >= self->traceParentProbability) { |
| 176 | state Span span("MiniCycleClient"_loc); |
| 177 | TraceEvent("MiniCycleTracingTransaction", span.context.traceID).log(); |
| 178 | tr.setOption(FDBTransactionOptions::SPAN_PARENT, |
| 179 | BinaryWriter::toValue(span.context, Unversioned())); |
| 180 | } |
| 181 | while (true) { |
| 182 | try { |
| 183 | // Reverse next and next^2 node |
| 184 | Optional<Value> v = wait(tr.get(self->key(r))); |
| 185 | if (!v.present()) |
| 186 | self->badRead("KeyR", r, tr); |
| 187 | state int r2 = self->fromValue(v.get()); |
| 188 | Optional<Value> v2 = wait(tr.get(self->key(r2))); |
| 189 | if (!v2.present()) |
| 190 | self->badRead("KeyR2", r2, tr); |
| 191 | state int r3 = self->fromValue(v2.get()); |
| 192 | Optional<Value> v3 = wait(tr.get(self->key(r3))); |
| 193 | if (!v3.present()) |
| 194 | self->badRead("KeyR3", r3, tr); |
| 195 | int r4 = self->fromValue(v3.get()); |
| 196 | |
| 197 | tr.clear(self->key(r)); //< Shouldn't have an effect, but will break with wrong ordering |
| 198 | tr.set(self->key(r), self->value(r3)); |
| 199 | tr.set(self->key(r2), self->value(r4)); |
| 200 | tr.set(self->key(r3), self->value(r2)); |
| 201 | // TraceEvent("CyclicTest").detail("Key", self->key(r).toString()).detail("Value", self->value(r3).toString()); |
| 202 | // TraceEvent("CyclicTest").detail("Key", self->key(r2).toString()).detail("Value", self->value(r4).toString()); |
| 203 | // TraceEvent("CyclicTest").detail("Key", self->key(r3).toString()).detail("Value", self->value(r2).toString()); |
| 204 | |
| 205 | wait(tr.commit()); |
| 206 | // TraceEvent("MiniCycleCommit"); |
| 207 | break; |
| 208 | } catch (Error& e) { |
| 209 | if (e.code() == error_code_transaction_too_old) |
| 210 | ++self->tooOldRetries; |
| 211 | else if (e.code() == error_code_not_committed) |
| 212 | ++self->commitFailedRetries; |
| 213 | wait(tr.onError(e)); |
| 214 | } |
| 215 | ++self->retries; |
| 216 | } |
| 217 | ++self->transactions; |
| 218 | self->totalLatency += now() - tstart; |
| 219 | } |
| 220 | } catch (Error& e) { |
| 221 | TraceEvent(SevError, "MiniCycleClient").error(e); |
| 222 | throw; |
no test coverage detected