diff --git a/fdbcli/fdbcli.actor.cpp b/fdbcli/fdbcli.actor.cpp index 8e7988043b..8b40a2375e 100644 --- a/fdbcli/fdbcli.actor.cpp +++ b/fdbcli/fdbcli.actor.cpp @@ -2170,7 +2170,9 @@ ACTOR Future exclude( Database db, std::vector tokens, Referenc } ACTOR Future createSnapshot(Database db, StringRef snapCmd) { - wait(makeInterruptable(mgmtSnapCreate(db, snapCmd))); + // FIXME: default version for snapshots are still 1, once version 2 is stable - it will be made the default + // and version 1 may be deprecated + wait(makeInterruptable(mgmtSnapCreate(db, snapCmd, 1 /* version */))); return false; } diff --git a/fdbclient/ManagementAPI.actor.cpp b/fdbclient/ManagementAPI.actor.cpp index 69f582cfb8..909d141bc3 100644 --- a/fdbclient/ManagementAPI.actor.cpp +++ b/fdbclient/ManagementAPI.actor.cpp @@ -1482,14 +1482,18 @@ ACTOR Future> checkForExcludingServers(Database cx, vec return inProgressExclusion; } -ACTOR Future mgmtSnapCreate(Database cx, StringRef snapCmd) { +ACTOR Future mgmtSnapCreate(Database cx, StringRef snapCmd, int version) { state int retryCount = 0; loop { state UID snapUID = deterministicRandom()->randomUniqueID(); try { - wait(snapCreate(cx, snapCmd, snapUID)); - printf("Snapshots tagged with UID: %s, check logs for status\n", snapUID.toString().c_str()); + wait(snapCreate(cx, snapCmd, snapUID, version)); + if (version == 1) { + printf("Snapshots tagged with UID: %s, check logs for status\n", snapUID.toString().c_str()); + } else { + printf("Snapshots create succeeded with UID: %s\n", snapUID.toString().c_str()); + } TraceEvent("SnapCreateSucceeded").detail("snapUID", snapUID); break; } catch (Error& e) { diff --git a/fdbclient/ManagementAPI.actor.h b/fdbclient/ManagementAPI.actor.h index f0384082dd..2fe73bc3a2 100644 --- a/fdbclient/ManagementAPI.actor.h +++ b/fdbclient/ManagementAPI.actor.h @@ -195,7 +195,7 @@ bool schemaMatch( json_spirit::mValue const& schema, json_spirit::mValue const& // execute payload in 'snapCmd' on all the coordinators, TLogs and // storage nodes -ACTOR Future mgmtSnapCreate(Database cx, StringRef snapCmd); +ACTOR Future mgmtSnapCreate(Database cx, StringRef snapCmd, int version); #include "flow/unactorcompiler.h" #endif diff --git a/fdbclient/NativeAPI.actor.cpp b/fdbclient/NativeAPI.actor.cpp index 950f51653d..0db92a8aca 100644 --- a/fdbclient/NativeAPI.actor.cpp +++ b/fdbclient/NativeAPI.actor.cpp @@ -3439,7 +3439,7 @@ void enableClientInfoLogging() { TraceEvent(SevInfo, "ClientInfoLoggingEnabled"); } -ACTOR Future snapCreate(Database inputCx, StringRef snapCmd, UID snapUID) { +ACTOR Future snapCreateVersion1(Database inputCx, StringRef snapCmd, UID snapUID) { state Transaction tr(inputCx); state DatabaseContext* cx = inputCx.getPtr(); // remember the client ID before the snap operation @@ -3537,3 +3537,83 @@ ACTOR Future snapCreate(Database inputCx, StringRef snapCmd, UID snapUID) TraceEvent("SnapCreateComplete").detail("UID", snapUID); return Void(); } + +ACTOR Future snapshotDatabase(DatabaseContext* cx, StringRef snapPayload, UID snapUID, Optional debugID) { + TraceEvent("NativeAPI.SnapshotDatabaseEnter") + .detail("SnapPayload", snapPayload) + .detail("SnapUID", snapUID); + try { + if (debugID.present()) { + g_traceBatch.addEvent("TransactionDebug", debugID.get().first(), "NativeAPI.snapshotDatabase.Before"); + } + + state ProxySnapRequest req(snapPayload, snapUID, debugID); + wait(loadBalance(cx->getMasterProxies(false), &MasterProxyInterface::proxySnapReq, req, cx->taskID, true /*atmostOnce*/ )); + if (debugID.present()) + g_traceBatch.addEvent("TransactionDebug", debugID.get().first(), + "NativeAPI.SnapshotDatabase.After"); + } catch (Error& e) { + TraceEvent("NativeAPI.SnapshotDatabaseError") + .detail("SnapPayload", snapPayload) + .detail("SnapUID", snapUID) + .error(e, true /* includeCancelled */); + throw; + } + return Void(); +} + +ACTOR Future snapCreateVersion2(Database inputCx, StringRef snapCmd, UID snapUID) { + state DatabaseContext* cx = inputCx.getPtr(); + // remember the client ID before the snap operation + state UID preSnapClientUID = cx->clientInfo->get().id; + + TraceEvent("SnapCreateEnterVersion2") + .detail("SnapCmd", snapCmd.toString()) + .detail("UID", snapUID) + .detail("PreSnapClientUID", preSnapClientUID); + + StringRef snapCmdArgs = snapCmd; + StringRef snapCmdPart = snapCmdArgs.eat(":"); + state Standalone snapUIDRef(snapUID.toString()); + state Standalone snapPayloadRef = snapCmdPart + .withSuffix(LiteralStringRef(":uid=")) + .withSuffix(snapUIDRef) + .withSuffix(LiteralStringRef(",")) + .withSuffix(snapCmdArgs); + + try { + Future exec = snapshotDatabase(cx, snapPayloadRef, snapUID, snapUID); + wait(timeoutError(exec, g_network->isSimulated() ? 80 : 600)); // dependent on SERVER_KNOBS->SNAP_CRATE_MAX_TIMEOUT + // FIXME: remove the timeoutError and hard-coded time limits + } catch (Error& e) { + TraceEvent("SnapshotDatabaseErrorVersion2") + .detail("SnapCmd", snapCmd.toString()) + .detail("UID", snapUID) + .error(e); + throw; + } + + UID postSnapClientUID = cx->clientInfo->get().id; + if (preSnapClientUID != postSnapClientUID) { + // if the client IDs changed then we fail the snapshot + TraceEvent("UIDMismatchVersion2") + .detail("SnapPreSnapClientUID", preSnapClientUID) + .detail("SnapPostSnapClientUID", postSnapClientUID); + throw coordinators_changed(); + } + + TraceEvent("SnapCreateExitVersion2") + .detail("SnapCmd", snapCmd.toString()) + .detail("UID", snapUID) + .detail("PreSnapClientUID", preSnapClientUID); + return Void(); +} + +ACTOR Future snapCreate(Database inputCx, StringRef snapCmd, UID snapUID, int version) { + if (version == 1) { + wait(snapCreateVersion1(inputCx, snapCmd, snapUID)); + return Void(); + } + wait(snapCreateVersion2(inputCx, snapCmd, snapUID)); + return Void(); +} diff --git a/fdbclient/NativeAPI.actor.h b/fdbclient/NativeAPI.actor.h index d5b83e3c4a..e0b3eb437e 100644 --- a/fdbclient/NativeAPI.actor.h +++ b/fdbclient/NativeAPI.actor.h @@ -344,7 +344,7 @@ int64_t extractIntOption( Optional value, int64_t minValue = std::num // Takes a snapshot of the cluster, specifically the following persistent // states: coordinator, TLog and storage state -ACTOR Future snapCreate(Database cx, StringRef snapCmd, UID snapUID); +ACTOR Future snapCreate(Database cx, StringRef snapCmd, UID snapUID, int version); #include "flow/unactorcompiler.h" #endif