in aios/storage/indexlib/framework/Tablet.cpp [636:778]
Status Tablet::Open(const IndexRoot& indexRoot, const std::shared_ptr<config::ITabletSchema>& tabletSchema,
const std::shared_ptr<config::TabletOptions>& options, const VersionCoord& versionCoord)
{
TABLET_LOG(INFO, "open tablet begin, indexRoot[%s], version[%s], leader[%d], flushlocal[%d], flushremote[%d]",
indexRoot.ToString().c_str(), versionCoord.DebugString().c_str(), options->IsLeader(),
options->FlushLocal(), options->FlushRemote());
autil::ScopedTime2 timer;
_tabletInfos->SetIndexRoot(indexRoot);
_tabletOptions = std::make_shared<config::TabletOptions>(*options);
_tabletOptions->SetTabletName(_tabletInfos->GetTabletName());
_tabletFactory = CreateTabletFactory(tabletSchema->GetTableType(), _tabletOptions);
if (_tabletFactory == nullptr) {
auto st = Status::ConfigError("create tablet factory failed");
TABLET_LOG(ERROR, "%s", st.ToString().c_str());
return st;
}
auto status = TabletSchemaLoader::ResolveSchema(_tabletOptions, indexRoot.GetRemoteRoot(), tabletSchema.get());
if (!status.IsOK()) {
TABLET_LOG(ERROR, "resolve schema failed: %s", status.ToString().c_str());
return status;
}
if (_idGenerator == nullptr) {
_idGenerator = std::make_shared<IdGenerator>(_tabletOptions->FlushRemote() ? IdMaskType::BUILD_PUBLIC
: IdMaskType::BUILD_PRIVATE);
TABLET_LOG(INFO, "use built-in id generator");
}
status = _tabletOptions->Check(_tabletInfos->GetIndexRoot().GetRemoteRoot(),
_tabletInfos->GetIndexRoot().GetLocalRoot());
if (!status.IsOK()) {
TABLET_LOG(ERROR, "check tablet options failed");
return status;
}
try {
auto status = PrepareIndexRoot(tabletSchema);
if (!status.IsOK()) {
TABLET_LOG(ERROR, "tablet prepare index root [%s] failed", indexRoot.ToString().c_str());
return status;
}
_tabletSchemaMgr = std::make_unique<TabletSchemaManager>(_tabletFactory, _tabletOptions, _fence.GetGlobalRoot(),
indexRoot.GetRemoteRoot(), _fence.GetFileSystem());
_tabletSchemaMgr->InsertSchemaToCache(tabletSchema);
_memSegmentCreator = std::make_unique<MemSegmentCreator>(_tabletInfos->GetTabletName(), _tabletOptions.get(),
_tabletFactory.get(), _idGenerator.get(),
GetRootDirectory()->GetIDirectory());
status = PrepareEmptyTabletData(tabletSchema);
if (!status.IsOK()) {
TABLET_LOG(ERROR, "tablet prepare empty tablet data failed");
return status;
}
status = PrepareResource();
if (!status.IsOK()) {
TABLET_LOG(ERROR, "tablet prepare resource failed");
return status;
}
versionid_t loadedLocalVersionId = INVALID_VERSIONID;
autil::ScopeGuard tabletPhaseGuard = _tabletMetrics->CreateTabletPhaseGuard(TabletPhase::OPEN);
if (NeedRecoverFromLocal()) {
std::string fenceName =
Fence::GenerateNewFenceName(_tabletOptions->FlushRemote(), _tabletInfos->GetTabletId());
std::string localFenceRoot = PathUtil::JoinPath(_tabletInfos->GetIndexRoot().GetLocalRoot(), fenceName);
auto [recoverStatus, localVersion] = RecoverLatestVersion(localFenceRoot);
if (!recoverStatus.IsOK()) {
auto cleanStatus = DropIndexCleaner::DropPrivateFence(_tabletInfos->GetIndexRoot().GetLocalRoot());
RETURN_IF_STATUS_ERROR(cleanStatus, "clean local index failed");
TABLET_LOG(WARN, "local index is cleaned [%s]", localFenceRoot.c_str());
return recoverStatus;
}
Version targetVersion;
std::string versionRoot;
status = LoadVersion(versionCoord, &targetVersion, &versionRoot);
if (!status.IsOK()) {
TABLET_LOG(WARN, "load version[%s] failed", versionCoord.DebugString().c_str());
return status;
}
if (!localVersion.IsValid() || localVersion.GetVersionId() == INVALID_VERSIONID ||
targetVersion.GetLocator().IsFasterThan(localVersion.GetLocator(), /*ignoreLegacyDiffSrc=*/true) ==
Locator::LocatorCompareResult::LCR_FULLY_FASTER) {
// do nothing
} else if (!targetVersion.CanFastFowardFrom(localVersion.GetVersionLine().GetHeadVersion(),
/*isDirty*/ false)) {
auto cleanStatus = DropIndexCleaner::DropPrivateFence(_tabletInfos->GetIndexRoot().GetLocalRoot());
RETURN_IF_STATUS_ERROR(cleanStatus, "clean local index failed");
TABLET_LOG(WARN, "local index is cleaned [%s]", localFenceRoot.c_str());
status = Status::Abort("local private version [%d] is not compatible with target version[%s]",
localVersion.GetVersionId(), versionCoord.DebugString().c_str());
TABLET_LOG(ERROR, "%s", status.ToString().c_str());
return status;
} else {
std::lock_guard<std::mutex> lockReopen(_reopenMutex);
status = DoReopenUnsafe(ReopenOptions(_openOptions), localVersion.GetVersionId());
if (!status.IsOK()) {
TABLET_LOG(ERROR, "recover from local version [%d] failed", localVersion.GetVersionId());
auto cleanStatus = DropIndexCleaner::DropPrivateFence(_tabletInfos->GetIndexRoot().GetLocalRoot());
RETURN_IF_STATUS_ERROR(cleanStatus, "clean local index failed");
TABLET_LOG(WARN, "local index is cleaned [%s]", localFenceRoot.c_str());
return status;
}
loadedLocalVersionId = localVersion.GetVersionId();
TABLET_LOG(INFO, "recover from local version[%d] succeed.", loadedLocalVersionId);
}
}
if (loadedLocalVersionId != INVALID_VERSIONID && versionCoord.GetVersionId() == INVALID_VERSIONID) {
// do nothing
} else {
std::lock_guard<std::mutex> lockReopen(_reopenMutex);
status = DoReopenUnsafe(ReopenOptions(_openOptions), versionCoord);
if (!status.IsOK()) {
TABLET_LOG(ERROR, "tablet load version [%s] failed", versionCoord.DebugString().c_str());
return status;
}
}
} catch (const indexlib::util::FileIOException& e) {
// TODO(hanyao): fill status message b exception
TABLET_LOG(ERROR, "open caught file io exception: %s", e.what());
return Status::IOError("open caught fail io exception: ", e.what());
} catch (const autil::legacy::ExceptionBase& e) {
TABLET_LOG(ERROR, "open caught exception, %s", e.what());
return Status::Unknown("open caught exception: ", e.what());
} catch (const std::exception& e) {
// TODO(hanyao): fill status message b exception
TABLET_LOG(ERROR, "open caught exception, %s", e.what());
return Status::Unknown("open caught exception: ", e.what());
} catch (...) {
TABLET_LOG(ERROR, "open caught exception");
return Status::Unknown("open caught exception");
}
if (!StartIntervalTask()) {
TABLET_LOG(ERROR, "start interval task failed");
return Status::Corruption("Start interval task failed.");
}
_tabletCommitter->Init(_versionMerger, _tabletData);
TABLET_LOG(INFO, "open tablet end, used [%.3f]s", timer.done_sec());
_isClosed = false;
_needSeek.store(false);
return Status::OK();
}