Renamed backup state enums for clarity, added backup state names. Changed Epochs to EpochSeconds in backup JSON along with some other renaming/moving of fields, and added information about snapshot dispatch. Changed timestamp format for input/output in all backup/restore contexts to be a fully qualified time with timezone offset. Added information about the last snapshot dispatch to backup config and status (not yet populated).
This commit is contained in:
parent
8bdb21a04e
commit
023bbb566f
|
@ -840,7 +840,7 @@ static void printBackupUsage(bool devhelp) {
|
|||
" File containing blob credentials in JSON format. Can be specified multiple times for multiple files. See below for more details.\n");
|
||||
printf(" --expire_before_timestamp DATETIME\n"
|
||||
" Datetime cutoff for expire operations. Requires a cluster file and will use version/timestamp metadata\n"
|
||||
" in the database to obtain a cutoff version very close to the timestamp given in YYYY-MM-DD.HH:MI:SS format (UTC).\n");
|
||||
" in the database to obtain a cutoff version very close to the timestamp given in %s.\n", BackupAgentBase::timeFormat().c_str());
|
||||
printf(" --expire_before_version VERSION\n"
|
||||
" Version cutoff for expire operations. Deletes data files containing no data at or after VERSION.\n");
|
||||
printf(" --delete_before_days NUM_DAYS\n"
|
||||
|
@ -913,7 +913,7 @@ static void printRestoreUsage(bool devhelp ) {
|
|||
printf(TLS_HELP);
|
||||
#endif
|
||||
printf(" -v DBVERSION The version at which the database will be restored.\n");
|
||||
printf(" --timestamp Instead of a numeric version, use this to specify a timestamp in YYYY-MM-DD.HH:MI:SS format (UTC)\n");
|
||||
printf(" --timestamp Instead of a numeric version, use this to specify a timestamp in %s\n", BackupAgentBase::timeFormat().c_str());
|
||||
printf(" and it will be converted to a version from that time using metadata in orig_cluster_file.\n");
|
||||
printf(" --orig_cluster_file CONNFILE\n");
|
||||
printf(" The cluster file for the original database from which the backup was created. The original database\n");
|
||||
|
@ -1252,8 +1252,8 @@ ACTOR Future<std::string> getLayerStatus(Reference<ReadYourWritesTransaction> tr
|
|||
tagRoot.create("current_status") = statusText;
|
||||
tagRoot.create("last_restorable_version") = tagLastRestorableVersions[j].get();
|
||||
tagRoot.create("last_restorable_seconds_behind") = last_restorable_seconds_behind;
|
||||
tagRoot.create("running_backup") = (status == BackupAgentBase::STATE_DIFFERENTIAL || status == BackupAgentBase::STATE_BACKUP);
|
||||
tagRoot.create("running_backup_is_restorable") = (status == BackupAgentBase::STATE_DIFFERENTIAL);
|
||||
tagRoot.create("running_backup") = (status == BackupAgentBase::STATE_RUNNING_DIFFERENTIAL || status == BackupAgentBase::STATE_RUNNING);
|
||||
tagRoot.create("running_backup_is_restorable") = (status == BackupAgentBase::STATE_RUNNING_DIFFERENTIAL);
|
||||
tagRoot.create("range_bytes_written") = tagRangeBytes[j].get();
|
||||
tagRoot.create("mutation_log_bytes_written") = tagLogBytes[j].get();
|
||||
tagRoot.create("mutation_stream_id") = backupTagUids[j].toString();
|
||||
|
@ -1296,8 +1296,8 @@ ACTOR Future<std::string> getLayerStatus(Reference<ReadYourWritesTransaction> tr
|
|||
BackupAgentBase::enumState status = (BackupAgentBase::enumState)backupStatus[i].get();
|
||||
|
||||
JSONDoc tagRoot = tagsRoot.create(tagName);
|
||||
tagRoot.create("running_backup") = (status == BackupAgentBase::STATE_DIFFERENTIAL || status == BackupAgentBase::STATE_BACKUP);
|
||||
tagRoot.create("running_backup_is_restorable") = (status == BackupAgentBase::STATE_DIFFERENTIAL);
|
||||
tagRoot.create("running_backup") = (status == BackupAgentBase::STATE_RUNNING_DIFFERENTIAL || status == BackupAgentBase::STATE_RUNNING);
|
||||
tagRoot.create("running_backup_is_restorable") = (status == BackupAgentBase::STATE_RUNNING_DIFFERENTIAL);
|
||||
tagRoot.create("range_bytes_written") = tagRangeBytesDR[i].get();
|
||||
tagRoot.create("mutation_log_bytes_written") = tagLogBytesDR[i].get();
|
||||
tagRoot.create("mutation_stream_id") = drTagUids[i].toString();
|
||||
|
|
|
@ -44,17 +44,29 @@ public:
|
|||
char buffer[128];
|
||||
struct tm timeinfo;
|
||||
getLocalTime(&curTime, &timeinfo);
|
||||
strftime(buffer, 128, "%Y/%m/%d %H:%M:%S", &timeinfo);
|
||||
strftime(buffer, 128, "%Y/%m/%d.%H:%M:%S%z", &timeinfo);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static std::string timeFormat() {
|
||||
return "YYYY/MM/DD.HH:MI:SS[+/-]HHMM";
|
||||
}
|
||||
|
||||
static int64_t parseTime(std::string timestamp) {
|
||||
struct tm out;
|
||||
if (strptime(timestamp.c_str(), "%Y/%m/%d.%H:%M:%S%z", &out) == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
return (int64_t) mktime(&out);
|
||||
}
|
||||
|
||||
// Type of program being executed
|
||||
enum enumActionResult {
|
||||
RESULT_SUCCESSFUL = 0, RESULT_ERRORED = 1, RESULT_DUPLICATE = 2, RESULT_UNNEEDED = 3
|
||||
};
|
||||
|
||||
enum enumState {
|
||||
STATE_ERRORED = 0, STATE_SUBMITTED = 1, STATE_BACKUP = 2, STATE_DIFFERENTIAL = 3, STATE_COMPLETED = 4, STATE_NEVERRAN = 5, STATE_ABORTED = 6, STATE_PARTIALLY_ABORTED = 7
|
||||
STATE_ERRORED = 0, STATE_SUBMITTED = 1, STATE_RUNNING = 2, STATE_RUNNING_DIFFERENTIAL = 3, STATE_COMPLETED = 4, STATE_NEVERRAN = 5, STATE_ABORTED = 6, STATE_PARTIALLY_ABORTED = 7
|
||||
};
|
||||
|
||||
static const Key keyFolderId;
|
||||
|
@ -100,11 +112,11 @@ public:
|
|||
}
|
||||
|
||||
else if (!stateText.compare("has been started")) {
|
||||
enState = STATE_BACKUP;
|
||||
enState = STATE_RUNNING;
|
||||
}
|
||||
|
||||
else if (!stateText.compare("is differential")) {
|
||||
enState = STATE_DIFFERENTIAL;
|
||||
enState = STATE_RUNNING_DIFFERENTIAL;
|
||||
}
|
||||
|
||||
else if (!stateText.compare("has been completed")) {
|
||||
|
@ -122,7 +134,7 @@ public:
|
|||
return enState;
|
||||
}
|
||||
|
||||
// Convert the status text to an enumerated value
|
||||
// Convert the status enum to a text description
|
||||
static const char* getStateText(enumState enState)
|
||||
{
|
||||
const char* stateText;
|
||||
|
@ -138,10 +150,10 @@ public:
|
|||
case STATE_SUBMITTED:
|
||||
stateText = "has been submitted";
|
||||
break;
|
||||
case STATE_BACKUP:
|
||||
case STATE_RUNNING:
|
||||
stateText = "has been started";
|
||||
break;
|
||||
case STATE_DIFFERENTIAL:
|
||||
case STATE_RUNNING_DIFFERENTIAL:
|
||||
stateText = "is differential";
|
||||
break;
|
||||
case STATE_COMPLETED:
|
||||
|
@ -161,6 +173,45 @@ public:
|
|||
return stateText;
|
||||
}
|
||||
|
||||
// Convert the status enum to a name
|
||||
static const char* getStateName(enumState enState)
|
||||
{
|
||||
const char* s;
|
||||
|
||||
switch (enState)
|
||||
{
|
||||
case STATE_ERRORED:
|
||||
s = "Errored";
|
||||
break;
|
||||
case STATE_NEVERRAN:
|
||||
s = "NeverRan";
|
||||
break;
|
||||
case STATE_SUBMITTED:
|
||||
s = "Submitted";
|
||||
break;
|
||||
case STATE_RUNNING:
|
||||
s = "Running";
|
||||
break;
|
||||
case STATE_RUNNING_DIFFERENTIAL:
|
||||
s = "RunningDifferentially";
|
||||
break;
|
||||
case STATE_COMPLETED:
|
||||
s = "Completed";
|
||||
break;
|
||||
case STATE_ABORTED:
|
||||
s = "Aborted";
|
||||
break;
|
||||
case STATE_PARTIALLY_ABORTED:
|
||||
s = "Aborting";
|
||||
break;
|
||||
default:
|
||||
s = "<undefined>";
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// Determine if the specified state is runnable
|
||||
static bool isRunnable(enumState enState)
|
||||
{
|
||||
|
@ -169,8 +220,8 @@ public:
|
|||
switch (enState)
|
||||
{
|
||||
case STATE_SUBMITTED:
|
||||
case STATE_BACKUP:
|
||||
case STATE_DIFFERENTIAL:
|
||||
case STATE_RUNNING:
|
||||
case STATE_RUNNING_DIFFERENTIAL:
|
||||
case STATE_PARTIALLY_ABORTED:
|
||||
isRunnable = true;
|
||||
break;
|
||||
|
@ -691,6 +742,14 @@ public:
|
|||
return configSpace.pack(LiteralStringRef(__FUNCTION__));
|
||||
}
|
||||
|
||||
KeyBackedBinaryValue<int64_t> snapshotDispatchLastShardsBehind() {
|
||||
return configSpace.pack(LiteralStringRef(__FUNCTION__));
|
||||
}
|
||||
|
||||
KeyBackedProperty<Version> snapshotDispatchLastVersion() {
|
||||
return configSpace.pack(LiteralStringRef(__FUNCTION__));
|
||||
}
|
||||
|
||||
Future<Void> initNewSnapshot(Reference<ReadYourWritesTransaction> tr, int64_t intervalSeconds = -1) {
|
||||
BackupConfig © = *this; // Capture this by value instead of this ptr
|
||||
|
||||
|
@ -714,6 +773,8 @@ public:
|
|||
copy.snapshotBeginVersion().set(tr, beginVersion.get());
|
||||
copy.snapshotTargetEndVersion().set(tr, endVersion);
|
||||
copy.snapshotRangeFileCount().set(tr, 0);
|
||||
copy.snapshotDispatchLastVersion().clear(tr);
|
||||
copy.snapshotDispatchLastShardsBehind().clear(tr);
|
||||
|
||||
return Void();
|
||||
});
|
||||
|
|
|
@ -175,7 +175,7 @@ std::string BackupDescription::toJSON() const {
|
|||
auto i = versionTimeMap.find(v);
|
||||
if(i != versionTimeMap.end()) {
|
||||
doc.setKey("Timestamp", BackupAgentBase::formatTime(i->second));
|
||||
doc.setKey("Epochs", i->second);
|
||||
doc.setKey("EpochSeconds", i->second);
|
||||
}
|
||||
}
|
||||
else if(maxLogEnd.present()) {
|
||||
|
@ -1628,20 +1628,11 @@ ACTOR Future<Version> timeKeeperVersionFromDatetime(std::string datetime, Databa
|
|||
state KeyBackedMap<int64_t, Version> versionMap(timeKeeperPrefixRange.begin);
|
||||
state Reference<ReadYourWritesTransaction> tr = Reference<ReadYourWritesTransaction>(new ReadYourWritesTransaction(db));
|
||||
|
||||
int year, month, day, hour, minute, second;
|
||||
if (sscanf(datetime.c_str(), "%d-%d-%d.%d:%d:%d", &year, &month, &day, &hour, &minute, &second) != 6) {
|
||||
fprintf(stderr, "ERROR: Incorrect date/time format.\n");
|
||||
state int64_t time = BackupAgentBase::parseTime(datetime);
|
||||
if(time < 0) {
|
||||
fprintf(stderr, "ERROR: Incorrect date/time or format. Format is %s.\n", BackupAgentBase::timeFormat().c_str());
|
||||
throw backup_error();
|
||||
}
|
||||
struct tm expDateTime = {0};
|
||||
expDateTime.tm_year = year - 1900;
|
||||
expDateTime.tm_mon = month - 1;
|
||||
expDateTime.tm_mday = day;
|
||||
expDateTime.tm_hour = hour;
|
||||
expDateTime.tm_min = minute;
|
||||
expDateTime.tm_sec = second;
|
||||
expDateTime.tm_isdst = -1;
|
||||
state int64_t time = (int64_t) mktime(&expDateTime);
|
||||
|
||||
loop {
|
||||
try {
|
||||
|
|
|
@ -1376,7 +1376,7 @@ namespace dbBackup {
|
|||
try {
|
||||
tr.setOption(FDBTransactionOptions::LOCK_AWARE);
|
||||
tr.addReadConflictRange(singleKeyRange(sourceStates.pack(DatabaseBackupAgent::keyStateStatus)));
|
||||
tr.set(sourceStates.pack(DatabaseBackupAgent::keyStateStatus), StringRef(BackupAgentBase::getStateText(BackupAgentBase::STATE_DIFFERENTIAL)));
|
||||
tr.set(sourceStates.pack(DatabaseBackupAgent::keyStateStatus), StringRef(BackupAgentBase::getStateText(BackupAgentBase::STATE_RUNNING_DIFFERENTIAL)));
|
||||
|
||||
Key versionKey = task->params[DatabaseBackupAgent::keyConfigLogUid].withPrefix(task->params[BackupAgentBase::destUid]).withPrefix(backupLatestVersionsPrefix);
|
||||
Optional<Key> prevBeginVersion = wait(tr.get(versionKey));
|
||||
|
@ -1418,7 +1418,7 @@ namespace dbBackup {
|
|||
wait(success(FinishedFullBackupTaskFunc::addTask(tr, taskBucket, task, TaskCompletionKey::noSignal())));
|
||||
}
|
||||
else { // Start the writing of logs, if differential
|
||||
tr->set(states.pack(DatabaseBackupAgent::keyStateStatus), StringRef(BackupAgentBase::getStateText(BackupAgentBase::STATE_DIFFERENTIAL)));
|
||||
tr->set(states.pack(DatabaseBackupAgent::keyStateStatus), StringRef(BackupAgentBase::getStateText(BackupAgentBase::STATE_RUNNING_DIFFERENTIAL)));
|
||||
|
||||
allPartsDone = futureBucket->future(tr);
|
||||
|
||||
|
@ -1544,7 +1544,7 @@ namespace dbBackup {
|
|||
|
||||
srcTr2->set( Subspace(databaseBackupPrefixRange.begin).get(BackupAgentBase::keySourceTagName).pack(task->params[BackupAgentBase::keyTagName]), logUidValue );
|
||||
srcTr2->set( sourceStates.pack(DatabaseBackupAgent::keyFolderId), task->params[DatabaseBackupAgent::keyFolderId] );
|
||||
srcTr2->set( sourceStates.pack(DatabaseBackupAgent::keyStateStatus), StringRef(BackupAgentBase::getStateText(BackupAgentBase::STATE_BACKUP)));
|
||||
srcTr2->set( sourceStates.pack(DatabaseBackupAgent::keyStateStatus), StringRef(BackupAgentBase::getStateText(BackupAgentBase::STATE_RUNNING)));
|
||||
|
||||
state Key destPath = destUidValue.withPrefix(backupLogKeys.begin);
|
||||
// Start logging the mutations for the specified ranges of the tag
|
||||
|
@ -1572,7 +1572,7 @@ namespace dbBackup {
|
|||
|
||||
tr->set(logUidValue.withPrefix(applyMutationsBeginRange.begin), BinaryWriter::toValue(beginVersion, Unversioned()));
|
||||
tr->set(logUidValue.withPrefix(applyMutationsEndRange.begin), BinaryWriter::toValue(beginVersion, Unversioned()));
|
||||
tr->set(states.pack(DatabaseBackupAgent::keyStateStatus), StringRef(BackupAgentBase::getStateText(BackupAgentBase::STATE_BACKUP)));
|
||||
tr->set(states.pack(DatabaseBackupAgent::keyStateStatus), StringRef(BackupAgentBase::getStateText(BackupAgentBase::STATE_RUNNING)));
|
||||
|
||||
state Reference<TaskFuture> kvBackupRangeComplete = futureBucket->future(tr);
|
||||
state Reference<TaskFuture> kvBackupComplete = futureBucket->future(tr);
|
||||
|
@ -1776,7 +1776,7 @@ public:
|
|||
}
|
||||
|
||||
// Break, if in differential mode (restorable) and stopWhenDone is not enabled
|
||||
if ((!stopWhenDone) && (BackupAgentBase::STATE_DIFFERENTIAL == status)) {
|
||||
if ((!stopWhenDone) && (BackupAgentBase::STATE_RUNNING_DIFFERENTIAL == status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1939,7 +1939,7 @@ public:
|
|||
state int status = wait(backupAgent->getStateValue(dest, destlogUid));
|
||||
|
||||
TraceEvent("DBA_SwitchoverStart").detail("Status", status);
|
||||
if (status != BackupAgentBase::STATE_DIFFERENTIAL && status != BackupAgentBase::STATE_COMPLETED) {
|
||||
if (status != BackupAgentBase::STATE_RUNNING_DIFFERENTIAL && status != BackupAgentBase::STATE_COMPLETED) {
|
||||
throw backup_duplicate();
|
||||
}
|
||||
|
||||
|
@ -2296,10 +2296,10 @@ public:
|
|||
case BackupAgentBase::STATE_SUBMITTED:
|
||||
statusText += "The DR on tag `" + tagNameDisplay + "' is NOT a complete copy of the primary database (just started).\n";
|
||||
break;
|
||||
case BackupAgentBase::STATE_BACKUP:
|
||||
case BackupAgentBase::STATE_RUNNING:
|
||||
statusText += "The DR on tag `" + tagNameDisplay + "' is NOT a complete copy of the primary database.\n";
|
||||
break;
|
||||
case BackupAgentBase::STATE_DIFFERENTIAL:
|
||||
case BackupAgentBase::STATE_RUNNING_DIFFERENTIAL:
|
||||
statusText += "The DR on tag `" + tagNameDisplay + "' is a complete copy of the primary database.\n";
|
||||
break;
|
||||
case BackupAgentBase::STATE_COMPLETED:
|
||||
|
|
|
@ -2059,8 +2059,8 @@ namespace fileBackup {
|
|||
}
|
||||
|
||||
// If the backup is restorable but the state is not differential then set state to differential
|
||||
if(restorableVersion.present() && backupState != BackupAgentBase::STATE_DIFFERENTIAL)
|
||||
config.stateEnum().set(tr, BackupAgentBase::STATE_DIFFERENTIAL);
|
||||
if(restorableVersion.present() && backupState != BackupAgentBase::STATE_RUNNING_DIFFERENTIAL)
|
||||
config.stateEnum().set(tr, BackupAgentBase::STATE_RUNNING_DIFFERENTIAL);
|
||||
|
||||
// If stopWhenDone is set and there is a restorable version, set the done future and do not create further tasks.
|
||||
if(stopWhenDone && restorableVersion.present()) {
|
||||
|
@ -2295,8 +2295,8 @@ namespace fileBackup {
|
|||
}
|
||||
|
||||
// If the backup is restorable and the state isn't differential the set state to differential
|
||||
if(restorableVersion.present() && backupState != BackupAgentBase::STATE_DIFFERENTIAL)
|
||||
config.stateEnum().set(tr, BackupAgentBase::STATE_DIFFERENTIAL);
|
||||
if(restorableVersion.present() && backupState != BackupAgentBase::STATE_RUNNING_DIFFERENTIAL)
|
||||
config.stateEnum().set(tr, BackupAgentBase::STATE_RUNNING_DIFFERENTIAL);
|
||||
|
||||
// Unless we are to stop, start the next snapshot using the default interval
|
||||
Reference<TaskFuture> snapshotDoneFuture = task->getDoneFuture(futureBucket);
|
||||
|
@ -2376,7 +2376,7 @@ namespace fileBackup {
|
|||
config.startMutationLogs(tr, backupRange, destUidValue);
|
||||
}
|
||||
|
||||
config.stateEnum().set(tr, EBackupState::STATE_BACKUP);
|
||||
config.stateEnum().set(tr, EBackupState::STATE_RUNNING);
|
||||
|
||||
state Reference<TaskFuture> backupFinished = futureBucket->future(tr);
|
||||
|
||||
|
@ -3474,7 +3474,7 @@ public:
|
|||
// Break, if one of the following is true
|
||||
// - no longer runnable
|
||||
// - in differential mode (restorable) and stopWhenDone is not enabled
|
||||
if( !FileBackupAgent::isRunnable(status) || ((!stopWhenDone) && (BackupAgentBase::STATE_DIFFERENTIAL == status) )) {
|
||||
if( !FileBackupAgent::isRunnable(status) || ((!stopWhenDone) && (BackupAgentBase::STATE_RUNNING_DIFFERENTIAL == status) )) {
|
||||
|
||||
if(pContainer != nullptr) {
|
||||
Reference<IBackupContainer> c = wait(config.backupContainer().getOrThrow(tr, false, backup_invalid_info()));
|
||||
|
@ -3822,7 +3822,7 @@ public:
|
|||
if(version.present()) {
|
||||
doc.setKey("Version", version.get());
|
||||
if(epochs.present()) {
|
||||
doc.setKey("Epochs", epochs.get());
|
||||
doc.setKey("EpochSeconds", epochs.get());
|
||||
doc.setKey("Timestamp", timeStampToString(epochs));
|
||||
}
|
||||
}
|
||||
|
@ -3865,8 +3865,10 @@ public:
|
|||
|
||||
state EBackupState backupState = wait(config.stateEnum().getD(tr, false, EBackupState::STATE_NEVERRAN));
|
||||
JsonBuilderObject statusDoc;
|
||||
statusDoc.setKey("Enum", (int)backupState);
|
||||
statusDoc.setKey("Name", BackupAgentBase::getStateName(backupState));
|
||||
statusDoc.setKey("Description", BackupAgentBase::getStateText(backupState));
|
||||
statusDoc.setKey("Completed", backupState == BackupAgentBase::STATE_COMPLETED);
|
||||
statusDoc.setKey("Running", BackupAgentBase::isRunnable(backupState));
|
||||
doc.setKey("Status", statusDoc);
|
||||
|
||||
state Future<Void> done = Void();
|
||||
|
@ -3881,19 +3883,17 @@ public:
|
|||
|
||||
doc.setKey("Restorable", latestRestorable.present());
|
||||
|
||||
if(latestRestorable.present() && backupState != BackupAgentBase::STATE_COMPLETED) {
|
||||
if(latestRestorable.present()) {
|
||||
JsonBuilderObject o = latestRestorable.toJSON();
|
||||
o.setKey("LagSeconds", (recentReadVersion - latestRestorable.version.get()) / CLIENT_KNOBS->CORE_VERSIONSPERSECOND);
|
||||
if(backupState != BackupAgentBase::STATE_COMPLETED) {
|
||||
o.setKey("LagSeconds", (recentReadVersion - latestRestorable.version.get()) / CLIENT_KNOBS->CORE_VERSIONSPERSECOND);
|
||||
}
|
||||
doc.setKey("LatestRestorablePoint", o);
|
||||
}
|
||||
doc.setKey("DestinationURL", bc->getURL());
|
||||
|
||||
if(backupState == BackupAgentBase::STATE_COMPLETED) {
|
||||
doc.setKey("Completed", latestRestorable.toJSON());
|
||||
}
|
||||
}
|
||||
|
||||
if(backupState == BackupAgentBase::STATE_DIFFERENTIAL || backupState == BackupAgentBase::STATE_BACKUP) {
|
||||
if(backupState == BackupAgentBase::STATE_RUNNING_DIFFERENTIAL || backupState == BackupAgentBase::STATE_RUNNING) {
|
||||
state int64_t snapshotInterval;
|
||||
state int64_t logBytesWritten;
|
||||
state int64_t rangeBytesWritten;
|
||||
|
@ -3902,6 +3902,8 @@ public:
|
|||
state TimestampedVersion snapshotTargetEnd;
|
||||
state TimestampedVersion latestLogEnd;
|
||||
state TimestampedVersion latestSnapshotEnd;
|
||||
state TimestampedVersion snapshotLastDispatch;
|
||||
state Optional<int64_t> snapshotLastDispatchShardsBehind;
|
||||
|
||||
wait( store(snapshotInterval, config.snapshotIntervalSeconds().getOrThrow(tr))
|
||||
&& store(logBytesWritten, config.logBytesWritten().getD(tr))
|
||||
|
@ -3911,6 +3913,8 @@ public:
|
|||
&& store(snapshotTargetEnd, getTimestampedVersion(tr, config.snapshotTargetEndVersion().get(tr)))
|
||||
&& store(latestLogEnd, getTimestampedVersion(tr, config.latestLogEndVersion().get(tr)))
|
||||
&& store(latestSnapshotEnd, getTimestampedVersion(tr, config.latestSnapshotEndVersion().get(tr)))
|
||||
&& store(snapshotLastDispatch, getTimestampedVersion(tr, config.snapshotDispatchLastVersion().get(tr)))
|
||||
&& store(snapshotLastDispatchShardsBehind, config.snapshotDispatchLastShardsBehind().get(tr))
|
||||
);
|
||||
|
||||
doc.setKey("StopAfterSnapshot", stopWhenDone);
|
||||
|
@ -3941,6 +3945,12 @@ public:
|
|||
double progress = (interval > 0) ? (100.0 * elapsed / interval) : 100;
|
||||
snapshot.setKey("ExpectedProgress", progress);
|
||||
}
|
||||
|
||||
JsonBuilderObject dispatchDoc = snapshotLastDispatch.toJSON();
|
||||
if(snapshotLastDispatchShardsBehind.present()) {
|
||||
dispatchDoc.setKey("ShardsBehind", snapshotLastDispatchShardsBehind.get());
|
||||
}
|
||||
snapshot.setKey("LastDispatch", dispatchDoc);
|
||||
}
|
||||
|
||||
doc.setKey("CurrentSnapshot", snapshot);
|
||||
|
@ -4010,11 +4020,11 @@ public:
|
|||
case BackupAgentBase::STATE_SUBMITTED:
|
||||
statusText += "The backup on tag `" + tagName + "' is in progress (just started) to " + bc->getURL() + ".\n";
|
||||
break;
|
||||
case BackupAgentBase::STATE_BACKUP:
|
||||
case BackupAgentBase::STATE_RUNNING:
|
||||
statusText += "The backup on tag `" + tagName + "' is in progress to " + bc->getURL() + ".\n";
|
||||
snapshotProgress = true;
|
||||
break;
|
||||
case BackupAgentBase::STATE_DIFFERENTIAL:
|
||||
case BackupAgentBase::STATE_RUNNING_DIFFERENTIAL:
|
||||
statusText += "The backup on tag `" + tagName + "' is restorable but continuing to " + bc->getURL() + ".\n";
|
||||
snapshotProgress = true;
|
||||
break;
|
||||
|
@ -4057,7 +4067,7 @@ public:
|
|||
);
|
||||
|
||||
statusText += format("Snapshot interval is %lld seconds. ", snapshotInterval);
|
||||
if(backupState == BackupAgentBase::STATE_DIFFERENTIAL)
|
||||
if(backupState == BackupAgentBase::STATE_RUNNING_DIFFERENTIAL)
|
||||
statusText += format("Current snapshot progress target is %3.2f%% (>100%% means the snapshot is supposed to be done)\n", 100.0 * (recentReadVersion - snapshotBeginVersion) / (snapshotTargetEndVersion - snapshotBeginVersion)) ;
|
||||
else
|
||||
statusText += "The initial snapshot is still running.\n";
|
||||
|
@ -4202,7 +4212,7 @@ public:
|
|||
backupConfig = BackupConfig(uidFlag.first);
|
||||
state EBackupState status = wait(backupConfig.stateEnum().getOrThrow(ryw_tr));
|
||||
|
||||
if (status != BackupAgentBase::STATE_DIFFERENTIAL ) {
|
||||
if (status != BackupAgentBase::STATE_RUNNING_DIFFERENTIAL ) {
|
||||
throw backup_duplicate();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue