Status Tablet::Open()

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();
}