nooneuse commented on code in PR #66307:
URL: https://github.com/apache/doris/pull/66307#discussion_r3849972555
##########
fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java:
##########
@@ -2586,154 +2651,184 @@ protected void cleanMetaObjects(boolean isReplay) {
}
private Status atomicReplaceOlapTables(Database db, boolean isReplay) {
+ Preconditions.checkState(db.isWriteLockHeldByCurrentThread(),
+ "atomic replacement must hold the database write lock");
+ Status validationStatus = prevalidateAtomicRestoreTargets(db);
+ if (!validationStatus.ok()) {
+ return validationStatus;
+ }
+ try {
+
Env.getCurrentEnv().getConstraintManager().checkAndDropTableConstraints(
+ getAtomicRestoreConstraintDropTargets(db),
!isForceReplace);
+ } catch (DdlException e) {
+ return new Status(ErrCode.COMMON_ERROR,
+ "replace table failed, reason=" + e.getMessage());
+ }
for (String tableName : jobInfo.backupOlapTableObjects.keySet()) {
- String originName = jobInfo.getAliasByOriginNameIfSet(tableName);
- if (GlobalVariable.isStoredTableNamesLowerCase()) {
- originName = originName.toLowerCase();
- }
+ String originName = restoreTargetName(tableName);
String aliasName = tableAliasWithAtomicRestore(originName);
- if (!db.writeLockIfExist()) {
- return Status.OK;
- }
+ Table newTbl = db.getTableNullable(aliasName);
+ Preconditions.checkNotNull(newTbl);
+ Preconditions.checkState(newTbl.getType() == TableType.OLAP);
+ Table originTbl = db.getTableNullable(originName);
+ Preconditions.checkState(originTbl == null
+ || originTbl.getType() == TableType.OLAP);
+ OlapTable originOlapTbl = (OlapTable) originTbl;
+
+ // replace the table.
+ OlapTable newOlapTbl = (OlapTable) newTbl;
+ newOlapTbl.writeLock();
try {
- Table newTbl = db.getTableNullable(aliasName);
- if (newTbl == null) {
- LOG.warn("replace table from {} to {}, but the temp table
is not found" + " isAtomicRestore: {}",
- aliasName, originName, isAtomicRestore);
- return new Status(ErrCode.COMMON_ERROR, "replace table
failed, the temp table "
- + aliasName + " is not found");
- }
- if (newTbl.getType() != TableType.OLAP) {
- LOG.warn(
- "replace table from {} to {}, but the temp table
is not OLAP, it type is {}"
- + " isAtomicRestore: {}",
- aliasName, originName, newTbl.getType(),
isAtomicRestore);
- return new Status(ErrCode.COMMON_ERROR, "replace table
failed, the temp table " + aliasName
- + " is not OLAP table, it is " + newTbl.getType());
- }
-
- OlapTable originOlapTbl = null;
- Table originTbl = db.getTableNullable(originName);
- if (originTbl != null) {
- if (originTbl.getType() != TableType.OLAP) {
- LOG.warn(
- "replace table from {} to {}, but the origin
table is not OLAP, it type is {}"
- + " isAtomicRestore: {}",
- aliasName, originName, originTbl.getType(),
isAtomicRestore);
- return new Status(ErrCode.COMMON_ERROR, "replace table
failed, the origin table "
- + originName + " is not OLAP table, it is " +
originTbl.getType());
- }
- originOlapTbl = (OlapTable) originTbl; // save the origin
olap table, then drop it.
- }
+ TableNameInfo originTableInfo = new TableNameInfo(
+ InternalCatalog.INTERNAL_CATALOG_NAME,
db.getFullName(), originName);
+ // rename new table name to origin table name and add the new
table to database.
+ db.unregisterTable(aliasName);
+ newOlapTbl.setName(originName);
+ db.unregisterTable(originName);
+ db.registerTable(newOlapTbl);
+
Env.getCurrentEnv().getConstraintManager().restoreTableConstraints(
+ originTableInfo, newOlapTbl);
+ Env.getCurrentEnv().getSqlCacheManager()
+
.invalidateAboutTableAndFencePublication(originTableInfo);
+
+ // set the olap table state to normal immediately for querying
+ newOlapTbl.setState(OlapTableState.NORMAL);
+ LOG.info(
+ "restore with replace table {} name to {}, and set
state to normal, origin table={}"
+ + " isAtomicRestore: {}",
+ newOlapTbl.getId(), originName,
+ originOlapTbl == null ? -1L : originOlapTbl.getId(),
+ isAtomicRestore);
+ } finally {
+ newOlapTbl.writeUnlock();
+ }
- // replace the table.
- OlapTable newOlapTbl = (OlapTable) newTbl;
- newOlapTbl.writeLock();
+ if (originOlapTbl != null) {
+ // The origin table is not used anymore, need to drop all its
tablets.
+ originOlapTbl.writeLock();
try {
- // rename new table name to origin table name and add the
new table to database.
- db.unregisterTable(aliasName);
- newOlapTbl.checkAndSetName(originName, false);
- db.unregisterTable(originName);
- db.registerTable(newOlapTbl);
-
- // set the olap table state to normal immediately for
querying
- newOlapTbl.setState(OlapTableState.NORMAL);
- LOG.info(
- "restore with replace table {} name to {}, and set
state to normal, origin table={}"
- + " isAtomicRestore: {}",
- newOlapTbl.getId(), originName, originOlapTbl ==
null ? -1L : originOlapTbl.getId(),
- isAtomicRestore);
- } catch (DdlException e) {
- LOG.warn("restore with replace table {} name from {} to
{}, isAtomicRestore: {}",
- newOlapTbl.getId(), aliasName, originName,
isAtomicRestore, e);
- return new Status(ErrCode.COMMON_ERROR, "replace table
from " + aliasName + " to " + originName
- + " failed, reason=" + e.getMessage());
+ LOG.info("drop the origin olap table {}. table={}" + "
isAtomicRestore: {}",
+ originOlapTbl.getName(), originOlapTbl.getId(),
isAtomicRestore);
+ Env.getCurrentEnv().onEraseOlapTable(db.getId(),
originOlapTbl, isReplay);
} finally {
- newOlapTbl.writeUnlock();
+ originOlapTbl.writeUnlock();
}
-
- if (originOlapTbl != null) {
- // The origin table is not used anymore, need to drop all
its tablets.
- originOlapTbl.writeLock();
- try {
- LOG.info("drop the origin olap table {}. table={}" + "
isAtomicRestore: {}",
- originOlapTbl.getName(),
originOlapTbl.getId(), isAtomicRestore);
- Env.getCurrentEnv().onEraseOlapTable(db.getId(),
originOlapTbl, isReplay);
- } finally {
- originOlapTbl.writeUnlock();
- }
- }
- } finally {
- db.writeUnlock();
}
}
for (BackupJobInfo.BackupViewInfo backupViewInfo :
jobInfo.newBackupObjects.views) {
- String originName =
jobInfo.getAliasByOriginNameIfSet(backupViewInfo.name);
- if (GlobalVariable.isStoredTableNamesLowerCase()) {
- originName = originName.toLowerCase();
- }
+ String originName = restoreTargetName(backupViewInfo.name);
String aliasName = tableAliasWithAtomicRestore(originName);
- if (!db.writeLockIfExist()) {
- return Status.OK;
- }
+ Table newTbl = db.getTableNullable(aliasName);
+ Preconditions.checkNotNull(newTbl);
+ Preconditions.checkState(newTbl.getType() == TableType.VIEW);
+ Table originTbl = db.getTableNullable(originName);
+ Preconditions.checkState(originTbl == null
+ || originTbl.getType() == TableType.VIEW);
+ View originViewTbl = (View) originTbl;
+
+ // replace the view.
+ View newViewTbl = (View) newTbl;
+ newViewTbl.writeLock();
try {
- Table newTbl = db.getTableNullable(aliasName);
- if (newTbl == null) {
- LOG.warn("replace view from {} to {}, but the temp view is
not found" + " isAtomicRestore: {}",
- aliasName, originName, isAtomicRestore);
- return new Status(ErrCode.COMMON_ERROR, "replace view
failed, the temp view "
- + aliasName + " is not found");
- }
- if (newTbl.getType() != TableType.VIEW) {
- LOG.warn(
- "replace view from {} to {}, but the temp view is
not VIEW, it type is {}"
- + " isAtomicRestore: {}",
- aliasName, originName, newTbl.getType(),
isAtomicRestore);
- return new Status(ErrCode.COMMON_ERROR, "replace view
failed, the temp view " + aliasName
- + " is not OLAP, it is " + newTbl.getType());
- }
+ // rename new view name to origin view name and add the new
view to database.
+ db.unregisterTable(aliasName);
+ db.unregisterTable(originName);
+ newViewTbl.setName(originName);
+ db.registerTable(newViewTbl);
+
+ LOG.info(
+ "restore with replace view {} name to {}, origin
view={}"
+ + " isAtomicRestore: {}",
+ newViewTbl.getId(), originName,
+ originViewTbl == null ? -1L : originViewTbl.getId(),
+ isAtomicRestore);
+ } finally {
+ newViewTbl.writeUnlock();
+ }
+ }
- View originViewTbl = null;
- Table originTbl = db.getTableNullable(originName);
- if (originTbl != null) {
- if (originTbl.getType() != TableType.VIEW) {
- LOG.warn(
- "replace view from {} to {}, but the origin
view is not VIEW, it type is {}"
- + " isAtomicRestore: {}",
- aliasName, originName, originTbl.getType(),
isAtomicRestore);
- return new Status(ErrCode.COMMON_ERROR, "replace view
failed, the origin view "
- + originName + " is not VIEW, it is " +
originTbl.getType());
- }
- originViewTbl = (View) originTbl; // save the origin view,
then drop it.
- }
+ return Status.OK;
+ }
- // replace the view.
- View newViewTbl = (View) newTbl;
- newViewTbl.writeLock();
- try {
- // rename new view name to origin view name and add the
new view to database.
- db.unregisterTable(aliasName);
- db.unregisterTable(originName);
- newViewTbl.setName(originName);
- db.registerTable(newViewTbl);
-
- LOG.info(
- "restore with replace view {} name to {}, origin
view={}"
- + " isAtomicRestore: {}",
- newViewTbl.getId(), originName,
- originViewTbl == null ? -1L :
originViewTbl.getId(),
- isAtomicRestore);
- } finally {
- newViewTbl.writeUnlock();
+ private Status prevalidateAtomicRestoreTargets(Database db) {
+ for (String tableName : jobInfo.backupOlapTableObjects.keySet()) {
+ String originName = restoreTargetName(tableName);
+ String aliasName = tableAliasWithAtomicRestore(originName);
+ Table newTable = db.getTableNullable(aliasName);
+ if (newTable == null) {
+ return new Status(ErrCode.COMMON_ERROR,
+ "replace table failed, the temp table " + aliasName +
" is not found");
+ }
+ if (newTable.getType() != TableType.OLAP) {
+ return new Status(ErrCode.COMMON_ERROR, "replace table failed,
the temp table "
+ + aliasName + " is not OLAP table, it is " +
newTable.getType());
+ }
+ try {
+ ((OlapTable) newTable).checkAndSetName(originName, true);
+ } catch (DdlException e) {
+ return new Status(ErrCode.COMMON_ERROR, "replace table failed,
the temp table "
+ + aliasName + " cannot be renamed to " + originName
+ + ", reason=" + e.getMessage());
+ }
+ Table originTable = db.getTableNullable(originName);
+ if (originTable != null && originTable.getType() !=
TableType.OLAP) {
+ return new Status(ErrCode.COMMON_ERROR, "replace table failed,
the origin table "
+ + originName + " is not OLAP table, it is " +
originTable.getType());
+ }
+ }
+ for (BackupJobInfo.BackupViewInfo backupViewInfo :
jobInfo.newBackupObjects.views) {
+ String originName = restoreTargetName(backupViewInfo.name);
+ String aliasName = tableAliasWithAtomicRestore(originName);
+ Table newView = db.getTableNullable(aliasName);
+ if (newView == null) {
+ return new Status(ErrCode.COMMON_ERROR,
+ "replace view failed, the temp view " + aliasName + "
is not found");
+ }
+ if (newView.getType() != TableType.VIEW) {
+ return new Status(ErrCode.COMMON_ERROR, "replace view failed,
the temp view "
+ + aliasName + " is not VIEW, it is " +
newView.getType());
+ }
+ Table originView = db.getTableNullable(originName);
+ if (originView != null && originView.getType() != TableType.VIEW) {
+ return new Status(ErrCode.COMMON_ERROR, "replace view failed,
the origin view "
+ + originName + " is not VIEW, it is " +
originView.getType());
+ }
+ }
+ return Status.OK;
+ }
+
+ private List<TableNameInfo> getAtomicRestoreConstraintDropTargets(Database
db) {
+ Set<String> tableNames = Sets.newLinkedHashSet();
+ for (String tableName : jobInfo.backupOlapTableObjects.keySet()) {
+ String originName = restoreTargetName(tableName);
+ tableNames.add(originName);
+ tableNames.add(tableAliasWithAtomicRestore(originName));
+ }
+ for (BackupJobInfo.BackupViewInfo view :
jobInfo.newBackupObjects.views) {
+ String originName = restoreTargetName(view.name);
+ tableNames.add(originName);
+ tableNames.add(tableAliasWithAtomicRestore(originName));
+ }
+ if (isCleanTables) {
Review Comment:
alright.
##########
fe/fe-core/src/main/java/org/apache/doris/datasource/MetastoreEventSyncDriver.java:
##########
@@ -276,6 +293,8 @@ private void applyOne(PluginDrivenExternalCatalog catalog,
Connector connector,
case UNREGISTER_TABLE:
catalogMgr.unregisterExternalTableFromEvent(
before.localDbName, before.localTableName,
catalogName);
+
Env.getCurrentEnv().getConstraintManager().dropTableConstraints(
Review Comment:
alright. And I found a catalog-level drop/rename issue, also fixed.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]