ExternalMetaIdMgr.java
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.doris.datasource;
import org.apache.doris.catalog.Env;
import org.apache.doris.datasource.hive.HMSExternalCatalog;
import org.apache.doris.datasource.hive.event.MetastoreEventsProcessor;
import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Map;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
/**
* <pre>
* ExternalMetaIdMgr is responsible for managing external meta ids.
* Now it just manages the external meta ids of hms events,
* but it will be extended to manage other external meta ids in the future.
* </pre>
* TODO: remove InitCatalogLog and InitDatabaseLog, manage external meta ids at ExternalMetaIdMgr
*/
public class ExternalMetaIdMgr {
private static final Logger LOG = LogManager.getLogger(ExternalMetaIdMgr.class);
public static final long META_ID_FOR_NOT_EXISTS = -1L;
private final Map<Long, CtlMetaIdMgr> idToCtlMgr = Maps.newConcurrentMap();
public ExternalMetaIdMgr() {
}
// invoke this method only on master
public static long nextMetaId() {
return Env.getCurrentEnv().getNextId();
}
// return the db id of the specified db, -1 means not exists
public long getDbId(long catalogId, String dbName) {
DbMetaIdMgr dbMetaIdMgr = getDbMetaIdMgr(catalogId, dbName);
if (dbMetaIdMgr == null) {
return META_ID_FOR_NOT_EXISTS;
}
return dbMetaIdMgr.dbId;
}
// return the tbl id of the specified tbl, -1 means not exists
public long getTblId(long catalogId, String dbName, String tblName) {
TblMetaIdMgr tblMetaIdMgr = getTblMetaIdMgr(catalogId, dbName, tblName);
if (tblMetaIdMgr == null) {
return META_ID_FOR_NOT_EXISTS;
}
return tblMetaIdMgr.tblId;
}
// return the partition id of the specified partition, -1 means not exists
public long getPartitionId(long catalogId, String dbName,
String tblName, String partitionName) {
PartitionMetaIdMgr partitionMetaIdMgr = getPartitionMetaIdMgr(catalogId, dbName, tblName, partitionName);
if (partitionMetaIdMgr == null) {
return META_ID_FOR_NOT_EXISTS;
}
return partitionMetaIdMgr.partitionId;
}
private @Nullable DbMetaIdMgr getDbMetaIdMgr(long catalogId, String dbName) {
CtlMetaIdMgr ctlMetaIdMgr = idToCtlMgr.get(catalogId);
if (ctlMetaIdMgr == null) {
return null;
}
return ctlMetaIdMgr.dbNameToMgr.get(dbName);
}
private @Nullable TblMetaIdMgr getTblMetaIdMgr(long catalogId, String dbName, String tblName) {
DbMetaIdMgr dbMetaIdMgr = getDbMetaIdMgr(catalogId, dbName);
if (dbMetaIdMgr == null) {
return null;
}
return dbMetaIdMgr.tblNameToMgr.get(tblName);
}
private PartitionMetaIdMgr getPartitionMetaIdMgr(long catalogId, String dbName,
String tblName, String partitionName) {
TblMetaIdMgr tblMetaIdMgr = getTblMetaIdMgr(catalogId, dbName, tblName);
if (tblMetaIdMgr == null) {
return null;
}
return tblMetaIdMgr.partitionNameToMgr.get(partitionName);
}
public void replayMetaIdMappingsLog(@NotNull MetaIdMappingsLog log) {
Preconditions.checkNotNull(log);
long catalogId = log.getCatalogId();
CtlMetaIdMgr ctlMetaIdMgr = idToCtlMgr.computeIfAbsent(catalogId, CtlMetaIdMgr::new);
for (MetaIdMappingsLog.MetaIdMapping mapping : log.getMetaIdMappings()) {
handleMetaIdMapping(mapping, ctlMetaIdMgr);
}
if (log.isFromHmsEvent()) {
CatalogIf<?> catalogIf = Env.getCurrentEnv().getCatalogMgr().getCatalog(log.getCatalogId());
if (catalogIf != null) {
MetastoreEventsProcessor metastoreEventsProcessor = Env.getCurrentEnv().getMetastoreEventsProcessor();
metastoreEventsProcessor.updateMasterLastSyncedEventId(
(HMSExternalCatalog) catalogIf, log.getLastSyncedEventId());
}
}
}
// no lock because the operations is serialized currently
private void handleMetaIdMapping(MetaIdMappingsLog.MetaIdMapping mapping, CtlMetaIdMgr ctlMetaIdMgr) {
MetaIdMappingsLog.OperationType opType = MetaIdMappingsLog.getOperationType(mapping.getOpType());
MetaIdMappingsLog.MetaObjectType objType = MetaIdMappingsLog.getMetaObjectType(mapping.getMetaObjType());
switch (opType) {
case ADD:
handleAddMetaIdMapping(mapping, ctlMetaIdMgr, objType);
break;
case DELETE:
handleDelMetaIdMapping(mapping, ctlMetaIdMgr, objType);
break;
default:
break;
}
}
private static void handleDelMetaIdMapping(MetaIdMappingsLog.MetaIdMapping mapping,
CtlMetaIdMgr ctlMetaIdMgr,
MetaIdMappingsLog.MetaObjectType objType) {
TblMetaIdMgr tblMetaIdMgr;
DbMetaIdMgr dbMetaIdMgr;
switch (objType) {
case DATABASE:
ctlMetaIdMgr.dbNameToMgr.remove(mapping.getDbName());
break;
case TABLE:
dbMetaIdMgr = ctlMetaIdMgr.dbNameToMgr.get(mapping.getDbName());
if (dbMetaIdMgr != null) {
dbMetaIdMgr.tblNameToMgr.remove(mapping.getTblName());
}
break;
case PARTITION:
dbMetaIdMgr = ctlMetaIdMgr.dbNameToMgr.get(mapping.getDbName());
if (dbMetaIdMgr != null) {
tblMetaIdMgr = dbMetaIdMgr.tblNameToMgr.get(mapping.getTblName());
if (tblMetaIdMgr != null) {
tblMetaIdMgr.partitionNameToMgr.remove(mapping.getPartitionName());
}
}
break;
default:
break;
}
}
private static void handleAddMetaIdMapping(MetaIdMappingsLog.MetaIdMapping mapping,
CtlMetaIdMgr ctlMetaIdMgr,
MetaIdMappingsLog.MetaObjectType objType) {
DbMetaIdMgr dbMetaIdMgr;
TblMetaIdMgr tblMetaIdMgr;
switch (objType) {
case DATABASE:
ctlMetaIdMgr.dbNameToMgr.put(mapping.getDbName(),
new DbMetaIdMgr(mapping.getId(), mapping.getDbName()));
break;
case TABLE:
dbMetaIdMgr = ctlMetaIdMgr.dbNameToMgr
.computeIfAbsent(mapping.getDbName(), DbMetaIdMgr::new);
dbMetaIdMgr.tblNameToMgr.put(mapping.getTblName(),
new TblMetaIdMgr(mapping.getId(), mapping.getTblName()));
break;
case PARTITION:
dbMetaIdMgr = ctlMetaIdMgr.dbNameToMgr
.computeIfAbsent(mapping.getDbName(), DbMetaIdMgr::new);
tblMetaIdMgr = dbMetaIdMgr.tblNameToMgr
.computeIfAbsent(mapping.getTblName(), TblMetaIdMgr::new);
tblMetaIdMgr.partitionNameToMgr.put(mapping.getPartitionName(),
new PartitionMetaIdMgr(mapping.getId(), mapping.getPartitionName()));
break;
default:
break;
}
}
public static class CtlMetaIdMgr {
protected final long catalogId;
protected CtlMetaIdMgr(long catalogId) {
this.catalogId = catalogId;
}
protected Map<String, DbMetaIdMgr> dbNameToMgr = Maps.newConcurrentMap();
}
public static class DbMetaIdMgr {
protected volatile long dbId = META_ID_FOR_NOT_EXISTS;
protected final String dbName;
protected DbMetaIdMgr(long dbId, String dbName) {
this.dbId = dbId;
this.dbName = dbName;
}
protected DbMetaIdMgr(String dbName) {
this.dbName = dbName;
}
protected Map<String, TblMetaIdMgr> tblNameToMgr = Maps.newConcurrentMap();
}
public static class TblMetaIdMgr {
protected volatile long tblId = META_ID_FOR_NOT_EXISTS;
protected final String tblName;
protected TblMetaIdMgr(long tblId, String tblName) {
this.tblId = tblId;
this.tblName = tblName;
}
protected TblMetaIdMgr(String tblName) {
this.tblName = tblName;
}
protected Map<String, PartitionMetaIdMgr> partitionNameToMgr = Maps.newConcurrentMap();
}
public static class PartitionMetaIdMgr {
protected volatile long partitionId = META_ID_FOR_NOT_EXISTS;
protected final String partitionName;
protected PartitionMetaIdMgr(long partitionId, String partitionName) {
this.partitionId = partitionId;
this.partitionName = partitionName;
}
protected PartitionMetaIdMgr(String partitionName) {
this.partitionName = partitionName;
}
}
}