diff options
Diffstat (limited to 'src/zenserver/storage/zenstorageserver.cpp')
| -rw-r--r-- | src/zenserver/storage/zenstorageserver.cpp | 140 |
1 files changed, 122 insertions, 18 deletions
diff --git a/src/zenserver/storage/zenstorageserver.cpp b/src/zenserver/storage/zenstorageserver.cpp index 3d81db656..44291395a 100644 --- a/src/zenserver/storage/zenstorageserver.cpp +++ b/src/zenserver/storage/zenstorageserver.cpp @@ -13,6 +13,8 @@ #include <zencore/iobuffer.h> #include <zencore/jobqueue.h> #include <zencore/logging.h> +#include <zencore/logging/broadcastsink.h> +#include <zencore/logging/registry.h> #include <zencore/scopeguard.h> #include <zencore/sentryintegration.h> #include <zencore/session.h> @@ -30,7 +32,9 @@ #include <zenstore/vfsimpl.h> #include <zenstore/workspaces.h> #include <zentelemetry/otlptrace.h> +#include <zenutil/logging.h> #include <zenutil/service.h> +#include <zenutil/sessionsclient.h> #include <zenutil/workerpools.h> #include <zenutil/zenserverprocess.h> @@ -133,7 +137,6 @@ void ZenStorageServer::RegisterServices() { m_Http->RegisterService(*m_AuthService); - m_Http->RegisterService(m_StatsService); m_Http->RegisterService(m_TestService); // NOTE: this is intentionally not limited to test mode as it's useful for diagnostics #if ZEN_WITH_TESTS @@ -160,7 +163,7 @@ ZenStorageServer::RegisterServices() m_Http->RegisterService(*m_HttpWorkspacesService); } - m_FrontendService = std::make_unique<HttpFrontendService>(m_ContentRoot, m_StatusService); + m_FrontendService = std::make_unique<HttpFrontendService>(m_ContentRoot, m_StatsService, m_StatusService); if (m_FrontendService) { @@ -183,10 +186,15 @@ ZenStorageServer::RegisterServices() m_Http->RegisterService(*m_AdminService); + if (m_ApiService) + { + m_Http->RegisterService(*m_ApiService); + } + #if ZEN_WITH_COMPUTE_SERVICES - if (m_HttpFunctionService) + if (m_HttpComputeService) { - m_Http->RegisterService(*m_HttpFunctionService); + m_Http->RegisterService(*m_HttpComputeService); } #endif } @@ -208,12 +216,22 @@ ZenStorageServer::InitializeServices(const ZenStorageServerConfig& ServerOptions ZEN_INFO("instantiating project service"); + m_LocalRefPolicy = std::make_unique<DataRootLocalRefPolicy>(m_DataRoot); m_JobQueue = MakeJobQueue(8, "bgjobs"); m_OpenProcessCache = std::make_unique<OpenProcessCache>(); m_ProjectStore = new ProjectStore(*m_CidStore, m_DataRoot / "projects", m_GcManager, ProjectStore::Configuration{}); - m_HttpProjectService.reset( - new HttpProjectService{*m_CidStore, m_ProjectStore, m_StatusService, m_StatsService, *m_AuthMgr, *m_OpenProcessCache, *m_JobQueue}); + m_HttpProjectService.reset(new HttpProjectService{*m_CidStore, + m_ProjectStore.Get(), + m_StatusService, + m_StatsService, + *m_AuthMgr, + *m_OpenProcessCache, + *m_JobQueue, + ServerOptions.RestrictContentTypes, + ServerOptions.OidcTokenExecutable, + ServerOptions.AllowExternalOidcTokenExe, + m_LocalRefPolicy.get()}); if (ServerOptions.WorksSpacesConfig.Enabled) { @@ -228,6 +246,16 @@ ZenStorageServer::InitializeServices(const ZenStorageServerConfig& ServerOptions *m_Workspaces)); } + if (!ServerOptions.SessionsTargetUrl.empty()) + { + m_SessionsClient = std::make_unique<SessionsServiceClient>(SessionsServiceClient::Options{ + .TargetUrl = ServerOptions.SessionsTargetUrl, + .AppName = "zenserver", + .Mode = GetServerMode(), + .SessionId = GetSessionId(), + }); + } + if (ServerOptions.BuildStoreConfig.Enabled) { CidStoreConfiguration BuildCidConfig; @@ -238,7 +266,31 @@ ZenStorageServer::InitializeServices(const ZenStorageServerConfig& ServerOptions BuildStoreConfig BuildsCfg; BuildsCfg.RootDirectory = m_DataRoot / "builds"; BuildsCfg.MaxDiskSpaceLimit = ServerOptions.BuildStoreConfig.MaxDiskSpaceLimit; - m_BuildStore = std::make_unique<BuildStore>(std::move(BuildsCfg), m_GcManager, *m_BuildCidStore); + + if (ServerOptions.BuildStoreConfig.MaxDiskSpaceLimitPercent > 0) + { + DiskSpace Space; + if (DiskSpaceInfo(m_DataRoot, Space) && Space.Total > 0) + { + uint64_t PercentLimit = Space.Total * ServerOptions.BuildStoreConfig.MaxDiskSpaceLimitPercent / 100; + BuildsCfg.MaxDiskSpaceLimit = ServerOptions.BuildStoreConfig.MaxDiskSpaceLimit > 0 + ? std::min(ServerOptions.BuildStoreConfig.MaxDiskSpaceLimit, PercentLimit) + : PercentLimit; + ZEN_INFO("buildstore disk limit: {}% of {} = {} (effective limit: {})", + ServerOptions.BuildStoreConfig.MaxDiskSpaceLimitPercent, + NiceBytes(Space.Total), + NiceBytes(PercentLimit), + NiceBytes(BuildsCfg.MaxDiskSpaceLimit)); + } + else + { + ZEN_WARN("buildstore-disksizelimit-percent: failed to query disk space for {}, using absolute limit {}", + m_DataRoot.string(), + NiceBytes(BuildsCfg.MaxDiskSpaceLimit)); + } + } + + m_BuildStore = std::make_unique<BuildStore>(std::move(BuildsCfg), m_GcManager, *m_BuildCidStore); } if (ServerOptions.StructuredCacheConfig.Enabled) @@ -264,7 +316,7 @@ ZenStorageServer::InitializeServices(const ZenStorageServerConfig& ServerOptions ObjCfg.Buckets.push_back(std::move(NewBucket)); } - m_ObjStoreService = std::make_unique<HttpObjectStoreService>(m_StatusService, std::move(ObjCfg)); + m_ObjStoreService = std::make_unique<HttpObjectStoreService>(m_StatsService, m_StatusService, std::move(ObjCfg)); } if (ServerOptions.BuildStoreConfig.Enabled) @@ -279,14 +331,14 @@ ZenStorageServer::InitializeServices(const ZenStorageServerConfig& ServerOptions { ZEN_OTEL_SPAN("InitializeComputeService"); - m_HttpFunctionService = - std::make_unique<compute::HttpFunctionService>(*m_CidStore, m_StatsService, ServerOptions.DataDir / "functions"); + m_HttpComputeService = + std::make_unique<compute::HttpComputeService>(*m_CidStore, *m_CidStore, m_StatsService, ServerOptions.DataDir / "functions"); } #endif #if ZEN_WITH_VFS m_VfsServiceImpl = std::make_unique<VfsServiceImpl>(); - m_VfsServiceImpl->AddService(Ref<ProjectStore>(m_ProjectStore)); + m_VfsServiceImpl->AddService(Ref<ProjectStore>(m_ProjectStore.Get())); m_VfsServiceImpl->AddService(Ref<ZenCacheStore>(m_CacheStore)); m_VfsService = std::make_unique<VfsService>(m_StatusService, m_VfsServiceImpl.get()); @@ -316,6 +368,8 @@ ZenStorageServer::InitializeServices(const ZenStorageServerConfig& ServerOptions .AttachmentPassCount = ServerOptions.GcConfig.AttachmentPassCount}; m_GcScheduler.Initialize(GcConfig); + m_ApiService = std::make_unique<HttpApiService>(*m_Http); + // Create and register admin interface last to make sure all is properly initialized m_AdminService = std::make_unique<HttpAdminService>( m_GcScheduler, @@ -485,7 +539,7 @@ ZenStorageServer::InitializeState(const ZenStorageServerConfig& ServerOptions) std::error_code Ec; for (const std::filesystem::directory_entry& DirEntry : std::filesystem::directory_iterator{m_DataRoot, Ec}) { - if (DirEntry.is_directory() && (DirEntry.path().filename() != "logs")) + if (DirEntry.is_directory() && DirEntry.path().filename() != "logs" && DirEntry.path().filename() != ".sentry-native") { ZEN_INFO("Deleting '{}'", DirEntry.path()); @@ -668,11 +722,15 @@ ZenStorageServer::InitializeStructuredCache(const ZenStorageServerConfig& Server m_StatusService, *m_UpstreamCache, m_GcManager.GetDiskWriteBlocker(), - *m_OpenProcessCache); + *m_OpenProcessCache, + m_LocalRefPolicy.get()); m_StatsReporter.AddProvider(m_CacheStore.Get()); m_StatsReporter.AddProvider(m_CidStore.get()); - m_StatsReporter.AddProvider(m_BuildCidStore.get()); + if (m_BuildCidStore) + { + m_StatsReporter.AddProvider(m_BuildCidStore.get()); + } } void @@ -695,16 +753,16 @@ ZenStorageServer::Run() ExtendableStringBuilder<256> BuildOptions; GetBuildOptions(BuildOptions, '\n'); - ZEN_INFO("Build options ({}/{}):\n{}", GetOperatingSystemName(), GetCpuName(), BuildOptions); + ZEN_INFO("Build options ({}/{}, {}):\n{}", GetOperatingSystemName(), GetCpuName(), GetCompilerName(), BuildOptions); } ZEN_INFO(ZEN_APP_NAME " now running (pid: {})", GetCurrentProcessId()); - if (m_FrontendService) + if (m_FrontendService && !m_NoNetwork) { ZEN_INFO("frontend link: {}", m_Http->GetServiceUri(m_FrontendService.get())); } - else + else if (!m_FrontendService) { ZEN_INFO("frontend service disabled"); } @@ -790,6 +848,17 @@ ZenStorageServer::Run() OnReady(); + StartSelfSession("zenserver"); + + if (m_SessionsClient) + { + m_SessionsClient->Announce(); + EnqueueSessionAnnounceTimer(); + + m_SessionLogSink = m_SessionsClient->CreateLogSink(); + GetDefaultBroadcastSink()->AddSink(m_SessionLogSink); + } + if (m_IsPowerCycle) { ZEN_INFO("Power cycle mode enabled -- shutting down"); @@ -810,17 +879,37 @@ ZenStorageServer::Cleanup() ZEN_INFO(ZEN_APP_NAME " cleaning up"); try { + m_SessionAnnounceTimer.cancel(); + + // Stop the IO context and join its thread first, before removing sinks. + // This ensures no async operations are trying to log through the + // broadcast sink while we modify its sink list. m_IoContext.stop(); if (m_IoRunner.joinable()) { m_IoRunner.join(); } + // Close the HTTP server before removing sinks. HTTP worker threads + // continuously log messages and hold the BroadcastSink shared lock, + // which would starve the exclusive lock needed by RemoveSink(). if (m_Http) { m_Http->Close(); } + if (m_SessionLogSink) + { + GetDefaultBroadcastSink()->RemoveSink(m_SessionLogSink); + m_SessionLogSink = {}; + } + if (m_SessionsClient) + { + m_SessionsClient.reset(); + } + + ShutdownServices(); + if (m_JobQueue) { m_JobQueue->Stop(); @@ -832,7 +921,7 @@ ZenStorageServer::Cleanup() Flush(); #if ZEN_WITH_COMPUTE_SERVICES - m_HttpFunctionService.reset(); + m_HttpComputeService.reset(); #endif m_AdminService.reset(); @@ -903,6 +992,20 @@ ZenStorageServer::CheckStateMarker() } void +ZenStorageServer::EnqueueSessionAnnounceTimer() +{ + m_SessionAnnounceTimer.expires_after(std::chrono::seconds(15)); + m_SessionAnnounceTimer.async_wait([this](const asio::error_code& Ec) { + if (!Ec && m_SessionsClient) + { + m_SessionsClient->Announce(); + EnqueueSessionAnnounceTimer(); + } + }); + EnsureIoRunner(); +} + +void ZenStorageServer::Flush() { ZEN_TRACE_CPU("ZenStorageServer::Flush"); @@ -946,6 +1049,7 @@ ZenStorageServerMain::DoRun(ZenServerState::ZenServerEntry* Entry) Server.SetContentRoot(m_ServerOptions.ContentDir); Server.SetTestMode(m_ServerOptions.IsTest); Server.SetDedicatedMode(m_ServerOptions.IsDedicated); + Server.SetAllowPortProbing(!m_ServerOptions.IsDedicated && m_ServerOptions.AllowPortProbing); int EffectiveBasePort = Server.Initialize(m_ServerOptions, Entry); if (EffectiveBasePort == -1) |