in aios/storage/indexlib/framework/Tablet.cpp [885:1093]
Status Tablet::DoReopenUnsafe(const ReopenOptions& reopenOptions, const VersionCoord& versionCoord)
{
// do not clean in-memory index while reopen
// otherwise mounted version may be erased by mistake.
std::lock_guard<std::mutex> lockCleaner(_cleanerMutex);
BuildResource buildResource = GenerateBuildResource(COUNTER_PREFIX);
indexlib::util::ScopeLatencyReporter reopenLatency(_tabletMetrics->GetreopenIncLatencyMetric().get());
auto statusOrDpDesc = CreateVersionDeployDescription(versionCoord.GetVersionId());
RETURN_IF_STATUS_ERROR(statusOrDpDesc, "create version deploy description failed for version [%d]",
versionCoord.GetVersionId());
auto versionDpDesc = std::move(statusOrDpDesc.steal_value());
auto [mountStatus, version] = MountOnDiskVersion(versionCoord, versionDpDesc);
if (!mountStatus.IsOK()) {
TABLET_LOG(ERROR, "mount version [%s] failed: %s", versionCoord.DebugString().c_str(),
mountStatus.ToString().c_str());
return mountStatus;
}
std::shared_ptr<TabletData> currentTabletData;
{
std::lock_guard<std::mutex> lock(_dataMutex);
currentTabletData = _tabletData;
}
TABLET_LOG(INFO, "do reopen, version [%d => %d]", currentTabletData->GetOnDiskVersion().GetVersionId(),
version.GetVersionId());
bool hasBuildingSegment;
auto headVersionCoord = CalculateHead(currentTabletData, _fence, &hasBuildingSegment);
bool isPrivateVersion = (versionCoord.GetVersionId() & Version::PRIVATE_VERSION_ID_MASK) > 0;
if (_tabletOptions->IsOnline() && !isPrivateVersion &&
!version.CanFastFowardFrom(headVersionCoord, hasBuildingSegment)) {
TABLET_LOG(ERROR,
"do reopen failed, version can't fast from onDiskVersion, head version [%s], version line [%s]",
autil::legacy::ToJsonString(headVersionCoord, true).c_str(),
autil::legacy::ToJsonString(version.GetVersionLine()).c_str());
return Status::Corruption("reopen fastford failed");
}
_idGenerator->UpdateBaseVersion(version);
auto loadSchemaStatus = _tabletSchemaMgr->LoadAllSchema(version);
if (!loadSchemaStatus.IsOK()) {
TABLET_LOG(ERROR, "do reopen failed, load all schema failed");
return loadSchemaStatus;
}
TABLET_LOG(INFO, "begin load segments, force[%d], segments [%s]", reopenOptions.IsForceReopen(),
GetDiffSegmentDebugString(version, currentTabletData).c_str());
auto readSchema = _tabletSchemaMgr->GetSchema(version.GetReadSchemaId());
if (currentTabletData) {
auto status =
DropIndexCleaner::CleanIndexInLogical(currentTabletData, readSchema, GetRootDirectory()->GetIDirectory());
if (!status.IsOK()) {
TABLET_LOG(ERROR, "do reopen failed, clean drop index failed");
return status;
}
}
auto currentLifecycleTable = LifecycleTableCreator::CreateLifecycleTable(
version, _tabletOptions->GetOnlineConfig().GetLifecycleConfig(),
{{indexlib::file_system::LifecyclePatternBase::CURRENT_TIME,
std::to_string(indexlib::file_system::LifecycleConfig::CurrentTimeInSeconds())}});
if (currentLifecycleTable == nullptr) {
TABLET_LOG(ERROR, "do reopen failed, create LifecycleTable failed for version[%d]", version.GetVersionId());
return Status::Corruption("reopen failed due to null lifecycleTable");
}
std::vector<std::pair<std::shared_ptr<Segment>, bool>> segmentPairs;
std::shared_ptr<indexlib::file_system::Directory> root = GetRootDirectory();
for (auto [segmentId, schemaId] : version) {
auto seg = currentTabletData->GetSegment(segmentId);
auto segmentDirName = version.GetSegmentDirName(segmentId);
auto currentLifecycle = currentLifecycleTable->GetLifecycle(segmentDirName + "/");
bool needLoadDiskSegment = true;
if (seg != nullptr && seg->GetSegmentStatus() == Segment::SegmentStatus::ST_BUILT) {
seg->GetSegmentDirectory()->SetLifecycle(currentLifecycle);
auto segmentSchemaId = seg->GetSegmentSchema()->GetSchemaId();
auto preLifecycle = seg->GetSegmentLifecycle();
if (segmentSchemaId != schemaId) {
auto diskSegment = std::dynamic_pointer_cast<DiskSegment>(seg);
assert(diskSegment != nullptr);
std::vector<std::shared_ptr<config::ITabletSchema>> tabletSchemas;
auto status = _tabletSchemaMgr->GetSchemaList(segmentSchemaId, schemaId, version, tabletSchemas);
RETURN_IF_STATUS_ERROR(status, "get schema list failed, segmentSchemaId[%d], segmentId[%d]",
segmentSchemaId, segmentId);
if (preLifecycle != currentLifecycle) {
RETURN_IF_STATUS_ERROR(
status, "config conficts, segmentId[%d] schemaId updated [%d->%d], lifecycle updated[%s -> %s]",
segmentId, segmentSchemaId, schemaId, preLifecycle.c_str(), currentLifecycle.c_str());
}
status = diskSegment->Reopen(tabletSchemas);
RETURN_IF_STATUS_ERROR(status, "disk segment open failed, segmentId[%d]", segmentId);
needLoadDiskSegment = false;
} else {
if (preLifecycle != currentLifecycle) {
TABLET_LOG(INFO, "built segmentId[%d] lifecycle updated [%s] -> [%s]", segmentId,
preLifecycle.c_str(), currentLifecycle.c_str());
} else {
needLoadDiskSegment = false;
}
}
}
if (!needLoadDiskSegment) {
segmentPairs.emplace_back(std::make_pair(seg, /*needOpen=*/false));
} else {
auto segDir = root->GetDirectory(segmentDirName,
/*throwExceptionIfNotExist=*/false);
if (!segDir) {
auto st = Status::IOError("get segment[%d] dir failed", segmentId);
TABLET_LOG(ERROR, "do reopen failed, %s", st.ToString().c_str());
return st;
}
segDir->SetLifecycle(currentLifecycle);
SegmentMeta segmentMeta;
segmentMeta.segmentId = segmentId;
segmentMeta.lifecycle = currentLifecycle;
auto schema = _tabletSchemaMgr->GetSchema(schemaId);
segmentMeta.schema = schema;
segmentMeta.segmentDir = segDir;
auto readerOption = indexlib::file_system::ReaderOption::PutIntoCache(indexlib::file_system::FSOT_MEM);
if (!segmentMeta.segmentInfo->Load(segDir->GetIDirectory(), readerOption).IsOK()) {
auto st = Status::Corruption("load segment info[%s] failed", segDir->GetLogicalPath().c_str());
TABLET_LOG(ERROR, "do reopen failed, %s", st.ToString().c_str());
return st;
}
auto diskSegment =
std::shared_ptr<Segment>(_tabletFactory->CreateDiskSegment(segmentMeta, buildResource).release());
assert(diskSegment);
segmentPairs.emplace_back(std::make_pair(diskSegment, /*needOpen=*/true));
}
}
TABLET_LOG(INFO, "end load segments, segment count [%lu]", segmentPairs.size());
TABLET_LOG(INFO, "begin load tablet data, fence name[%s]", _fence.GetFenceName().c_str());
const indexlib::util::MemoryReserverPtr memReserver = _fence.GetFileSystem()->CreateMemoryReserver("load_segments");
auto tabletLoader = _tabletFactory->CreateTabletLoader(_fence.GetFenceName());
assert(tabletLoader);
auto versionSchema = _tabletSchemaMgr->GetSchema(version.GetSchemaId());
tabletLoader->Init(_tabletMemoryQuotaController, versionSchema, memReserver, _tabletOptions->IsOnline());
{
indexlib::util::ScopeLatencyReporter preloadLatency(_tabletMetrics->GetpreloadLatencyMetric().get());
auto status = tabletLoader->PreLoad(*currentTabletData, std::move(segmentPairs), version);
if (!status.IsOK()) {
TABLET_LOG(ERROR, "do reopen failed, tablet preload version [%s] failed", version.DebugString().c_str());
return status;
}
}
indexlib::util::ScopeLatencyReporter finalLoadLatency(_tabletMetrics->GetfinalLoadLatencyMetric().get());
std::lock_guard lock(_dataMutex);
if (version.GetSchemaId() > GetTabletSchema()->GetSchemaId()) {
auto status = DoAlterTable(versionSchema);
if (!status.IsOK()) {
TABLET_LOG(ERROR, "do reopen failed, do alter table on schema[%u] failed: %s", version.GetSchemaId(),
status.ToString().c_str());
return status;
}
}
auto [status, newTabletData] = tabletLoader->FinalLoad(*_tabletData);
if (!status.IsOK()) {
TABLET_LOG(ERROR, "do reopen failed, tablet final load failed");
return status;
}
status = FinalizeTabletData(newTabletData.get(), GetTabletSchema());
if (!status.IsOK()) {
TABLET_LOG(ERROR, "do reopen failed, finalize tablet data failed: %s", status.ToString().c_str());
return status;
}
assert(newTabletData->GetResourceMap());
newTabletData->ReclaimSegmentResource();
TABLET_LOG(INFO, "end load tablet data");
_tabletDumper->TrimDumpingQueue(*newTabletData);
if (version.GetVersionId() & Version::PRIVATE_VERSION_ID_MASK) {
versionDpDesc = _tabletInfos->GetLoadedVersionDeployDescription();
}
status = OpenWriterAndReader(std::move(newTabletData), reopenOptions.GetOpenOptions(), versionDpDesc);
if (status.IsOK()) {
if (!(version.GetVersionId() & Version::PRIVATE_VERSION_ID_MASK)) {
_tabletInfos->SetLoadedPublishVersion(version);
_tabletInfos->SetLoadedVersionDeployDescription(versionDpDesc);
} else {
_tabletInfos->SetLoadedPrivateVersion(version);
}
if (_versionMerger) {
_versionMerger->UpdateVersion(version);
}
} else {
TABLET_LOG(ERROR, "do reopen failed, tablet open writer and reader failed");
}
if (!GetMemSegmentLocator().IsValid()) {
if (_tabletInfos->GetLoadedPublishVersion().IsSealed()) {
_sealedSourceLocator = _tabletInfos->GetLoadedPublishVersion().GetLocator();
if (_sealedSourceLocator) {
_tabletCommitter->SetSealed(true);
}
} else {
if (_sealedSourceLocator) {
_sealedSourceLocator.reset();
_tabletCommitter->SetSealed(false);
}
}
}
_tabletCommitter->SetLastPublicVersion(version);
RETURN_IF_STATUS_ERROR(status, "open writer and reader failed");
return Status::OK();
}