diff --git a/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJob.java b/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJob.java index dc92e9a07c3c1f..8a5043ebe7f61a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJob.java @@ -978,12 +978,18 @@ public synchronized Snapshot getSnapshot() { return null; } + // Avoid loading expired meta. + long expiredAt = createTime + timeoutMs; + if (System.currentTimeMillis() >= expiredAt) { + return new Snapshot(label, new byte[0], new byte[0], expiredAt); + } + try { File metaInfoFile = new File(localMetaInfoFilePath); File jobInfoFile = new File(localJobInfoFilePath); byte[] metaInfoBytes = Files.readAllBytes(metaInfoFile.toPath()); byte[] jobInfoBytes = Files.readAllBytes(jobInfoFile.toPath()); - return new Snapshot(label, metaInfoBytes, jobInfoBytes); + return new Snapshot(label, metaInfoBytes, jobInfoBytes, expiredAt); } catch (IOException e) { LOG.warn("failed to load meta info and job info file, meta info file {}, job info file {}: ", localMetaInfoFilePath, localJobInfoFilePath, e); diff --git a/fe/fe-core/src/main/java/org/apache/doris/backup/Snapshot.java b/fe/fe-core/src/main/java/org/apache/doris/backup/Snapshot.java index e31309b19a59ee..c4c93548177ca5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/backup/Snapshot.java +++ b/fe/fe-core/src/main/java/org/apache/doris/backup/Snapshot.java @@ -31,16 +31,19 @@ public class Snapshot { @SerializedName(value = "jobInfo") private byte[] jobInfo = null; + @SerializedName(value = "expired_at") + private long expiredAt = 0; + public Snapshot() { } - public Snapshot(String label, byte[] meta, byte[] jobInfo) { + public Snapshot(String label, byte[] meta, byte[] jobInfo, long expiredAt) { this.label = label; this.meta = meta; this.jobInfo = jobInfo; + this.expiredAt = expiredAt; } - public byte[] getMeta() { return meta; } @@ -49,17 +52,25 @@ public byte[] getJobInfo() { return jobInfo; } + public long getExpiredAt() { + return expiredAt; + } + + public boolean isExpired() { + return System.currentTimeMillis() > expiredAt; + } + public String toJson() { return GsonUtils.GSON.toJson(this); } @Override public String toString() { - // return toJson(); return "Snapshot{" + "label='" + label + '\'' + ", meta=" + meta + ", jobInfo=" + jobInfo + + ", expiredAt=" + expiredAt + '}'; } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java index d83ff7e08156d1..8c521cc73b0b52 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java +++ b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java @@ -2813,12 +2813,16 @@ private TGetSnapshotResult getSnapshotImpl(TGetSnapshotRequest request, String c if (snapshot == null) { result.getStatus().setStatusCode(TStatusCode.SNAPSHOT_NOT_EXIST); result.getStatus().addToErrorMsgs(String.format("snapshot %s not exist", label)); + } else if (snapshot.isExpired()) { + result.getStatus().setStatusCode(TStatusCode.SNAPSHOT_EXPIRED); + result.getStatus().addToErrorMsgs(String.format("snapshot %s is expired", label)); } else { byte[] meta = snapshot.getMeta(); byte[] jobInfo = snapshot.getJobInfo(); + long expiredAt = snapshot.getExpiredAt(); - LOG.info("get snapshot info, snapshot: {}, meta size: {}, job info size: {}", - label, meta.length, jobInfo.length); + LOG.info("get snapshot info, snapshot: {}, meta size: {}, job info size: {}, expired at: {}", + label, meta.length, jobInfo.length, expiredAt); if (request.isEnableCompress()) { meta = GZIPUtils.compress(meta); jobInfo = GZIPUtils.compress(jobInfo); @@ -2830,6 +2834,7 @@ private TGetSnapshotResult getSnapshotImpl(TGetSnapshotRequest request, String c } result.setMeta(meta); result.setJobInfo(jobInfo); + result.setExpiredAt(expiredAt); } return result; diff --git a/gensrc/thrift/FrontendService.thrift b/gensrc/thrift/FrontendService.thrift index 2739b1c209607c..6f9242cdd0efa4 100644 --- a/gensrc/thrift/FrontendService.thrift +++ b/gensrc/thrift/FrontendService.thrift @@ -1087,6 +1087,7 @@ struct TGetSnapshotResult { 3: optional binary job_info 4: optional Types.TNetworkAddress master_address 5: optional bool compressed; + 6: optional i64 expiredAt; // in millis } struct TTableRef { diff --git a/gensrc/thrift/Status.thrift b/gensrc/thrift/Status.thrift index 2cc9adb344a3f8..bb3450dd120c4e 100644 --- a/gensrc/thrift/Status.thrift +++ b/gensrc/thrift/Status.thrift @@ -103,6 +103,13 @@ enum TStatusCode { TABLET_MISSING = 72, NOT_MASTER = 73, + + OBTAIN_LOCK_FAILED = 74, + + SNAPSHOT_EXPIRED = 75, + + // Not be larger than 200, see status.h + // And all error code defined here, should also be defined in status.h } struct TStatus { diff --git a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Syncer.groovy b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Syncer.groovy index 20a4cf1ffd3815..398f1ec262485f 100644 --- a/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Syncer.groovy +++ b/regression-test/framework/src/main/groovy/org/apache/doris/regression/suite/Syncer.groovy @@ -459,6 +459,8 @@ class Syncer { logger.error("TGetSnapshotResult meta is unset.") } else if (!result.isSetJobInfo()) { logger.error("TGetSnapshotResult job info is unset.") + } else if (!result.isSetExpiredAt()) { + logger.error("TGetSnapshotResult expiredAt is unset.") } else { isCheckedOK = true }