Skip to content

Commit c0f743d

Browse files
vladl2802Vladislav Lukachik
and
Vladislav Lukachik
authored
Remove old spilling tmp files (#7108)
Co-authored-by: Vladislav Lukachik <[email protected]>
1 parent ee419db commit c0f743d

File tree

5 files changed

+94
-11
lines changed

5 files changed

+94
-11
lines changed

ydb/core/kqp/proxy_service/kqp_proxy_service.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
#include <library/cpp/lwtrace/mon/mon_lwtrace.h>
4545
#include <library/cpp/monlib/service/pages/templates.h>
4646
#include <library/cpp/resource/resource.h>
47-
#include <util/generic/guid.h>
47+
48+
#include <util/folder/dirut.h>
4849

4950
namespace NKikimr::NKqp {
5051

@@ -236,7 +237,8 @@ class TKqpProxyService : public TActorBootstrapped<TKqpProxyService> {
236237
if (auto& cfg = TableServiceConfig.GetSpillingServiceConfig().GetLocalFileConfig(); cfg.GetEnable()) {
237238
TString spillingRoot = cfg.GetRoot();
238239
if (spillingRoot.empty()) {
239-
spillingRoot = TStringBuilder() << "/tmp/ydb_spilling_" << CreateGuidAsString() << "/";
240+
spillingRoot = NYql::NDq::GetTmpSpillingRootForCurrentUser();
241+
MakeDirIfNotExist(spillingRoot);
240242
}
241243

242244
SpillingService = TlsActivationContext->ExecutorThread.RegisterActor(NYql::NDq::CreateDqLocalFileSpillingService(

ydb/library/yql/dq/actors/spilling/spilling_file.cpp

+73-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
#include <util/folder/path.h>
1414
#include <util/stream/file.h>
1515
#include <util/thread/pool.h>
16+
#include <util/generic/guid.h>
17+
#include <util/folder/iterator.h>
18+
#include <util/generic/vector.h>
19+
#include <util/folder/dirut.h>
20+
#include <util/system/user.h>
1621

1722
namespace NYql::NDq {
1823

@@ -159,6 +164,7 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
159164
EvCloseFileResponse = TEvDqSpillingLocalFile::EEv::LastEvent + 1,
160165
EvWriteFileResponse,
161166
EvReadFileResponse,
167+
EvRemoveOldTmp,
162168

163169
LastEvent
164170
};
@@ -189,6 +195,15 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
189195
bool Removed = false;
190196
TMaybe<TString> Error;
191197
};
198+
199+
struct TEvRemoveOldTmp : public TEventLocal<TEvRemoveOldTmp, EvRemoveOldTmp> {
200+
TFsPath TmpRoot;
201+
ui32 NodeId;
202+
TString SpillingSessionId;
203+
204+
TEvRemoveOldTmp(TFsPath tmpRoot, ui32 nodeId, TString spillingSessionId)
205+
: TmpRoot(std::move(tmpRoot)), NodeId(nodeId), SpillingSessionId(std::move(spillingSessionId)) {}
206+
};
192207
};
193208

194209
struct TFileDesc;
@@ -206,8 +221,11 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
206221

207222
void Bootstrap() {
208223
Root_ = Config_.Root;
209-
Root_ /= (TStringBuilder() << "node_" << SelfId().NodeId());
224+
const auto rootToRemoveOldTmp = Root_;
225+
const auto sessionId = Config_.SpillingSessionId;
226+
const auto nodeId = SelfId().NodeId();
210227

228+
Root_ /= (TStringBuilder() << NodePrefix_ << "_" << nodeId << "_" << sessionId);
211229
LOG_I("Init DQ local file spilling service at " << Root_ << ", actor: " << SelfId());
212230

213231
try {
@@ -221,6 +239,8 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
221239
Become(&TDqLocalFileSpillingService::BrokenState);
222240
return;
223241
}
242+
243+
Send(SelfId(), MakeHolder<TEvPrivate::TEvRemoveOldTmp>(rootToRemoveOldTmp, nodeId, sessionId));
224244

225245
Become(&TDqLocalFileSpillingService::WorkState);
226246
}
@@ -271,6 +291,7 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
271291
hFunc(TEvPrivate::TEvWriteFileResponse, HandleWork)
272292
hFunc(TEvDqSpilling::TEvRead, HandleWork)
273293
hFunc(TEvPrivate::TEvReadFileResponse, HandleWork)
294+
hFunc(TEvPrivate::TEvRemoveOldTmp, HandleWork)
274295
hFunc(NMon::TEvHttpInfo, HandleWork)
275296
cFunc(TEvents::TEvPoison::EventType, PassAway)
276297
);
@@ -712,6 +733,50 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
712733
Send(ev->Sender, new NMon::TEvHttpInfoRes(s.Str()));
713734
}
714735

736+
void HandleWork(TEvPrivate::TEvRemoveOldTmp::TPtr& ev) {
737+
const auto& msg = *ev->Get();
738+
const auto& root = msg.TmpRoot;
739+
const auto nodeIdString = ToString(msg.NodeId);
740+
const auto& sessionId = msg.SpillingSessionId;
741+
const auto& nodePrefix = this->NodePrefix_;
742+
743+
LOG_I("[RemoveOldTmp] removing at root: " << root);
744+
745+
const auto isDirOldTmp = [&nodePrefix, &nodeIdString, &sessionId](const TString& dirName) -> bool {
746+
// dirName: node_<nodeId>_<sessionId>
747+
TVector<TString> parts;
748+
StringSplitter(dirName).Split('_').Limit(3).Collect(&parts);
749+
750+
if (parts.size() < 3) {
751+
return false;
752+
}
753+
return parts[0] == nodePrefix && parts[1] == nodeIdString && parts[2] != sessionId;
754+
};
755+
756+
try {
757+
TDirIterator iter(root, TDirIterator::TOptions().SetMaxLevel(1));
758+
759+
TVector<TString> oldTmps;
760+
for (const auto& dirEntry : iter) {
761+
if (dirEntry.fts_info == FTS_DP) {
762+
continue;
763+
}
764+
765+
const auto dirName = dirEntry.fts_name;
766+
if (isDirOldTmp(dirName)) {
767+
LOG_D("[RemoveOldTmp] found old temporary at " << (root / dirName));
768+
oldTmps.emplace_back(std::move(dirName));
769+
}
770+
}
771+
772+
for (const auto& dirName : oldTmps) {
773+
(root / dirName).ForceDelete();
774+
}
775+
} catch (const yexception& e) {
776+
LOG_E("[RemoveOldTmp] removing failed due to: " << e.what());
777+
}
778+
}
779+
715780
private:
716781
void RunOp(TStringBuf opName, THolder<IObjectInQueue> op, TFileDesc& fd) {
717782
if (fd.HasActiveOp) {
@@ -941,6 +1006,7 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
9411006

9421007
private:
9431008
const TFileSpillingServiceConfig Config_;
1009+
const TString NodePrefix_ = "node";
9441010
TFsPath Root_;
9451011
TIntrusivePtr<TSpillingCounters> Counters_;
9461012

@@ -952,6 +1018,12 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
9521018

9531019
} // anonymous namespace
9541020

1021+
TFsPath GetTmpSpillingRootForCurrentUser() {
1022+
auto root = TFsPath{GetSystemTempDir()};
1023+
root /= "spilling-tmp-" + GetUsername();
1024+
return root;
1025+
}
1026+
9551027
IActor* CreateDqLocalFileSpillingActor(TTxId txId, const TString& details, const TActorId& client,
9561028
bool removeBlobsAfterRead)
9571029
{

ydb/library/yql/dq/actors/spilling/spilling_file.h

+5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,14 @@
77

88
#include <util/system/types.h>
99
#include <util/generic/strbuf.h>
10+
#include <util/folder/path.h>
11+
#include <util/generic/guid.h>
1012

1113
namespace NYql::NDq {
1214

1315
struct TFileSpillingServiceConfig {
1416
TString Root;
17+
TString SpillingSessionId = CreateGuidAsString();
1518
ui64 MaxTotalSize = 0;
1619
ui64 MaxFileSize = 0;
1720
ui64 MaxFilePartSize = 0;
@@ -26,6 +29,8 @@ inline NActors::TActorId MakeDqLocalFileSpillingServiceID(ui32 nodeId) {
2629
return NActors::TActorId(nodeId, TStringBuf(name, 12));
2730
}
2831

32+
TFsPath GetTmpSpillingRootForCurrentUser();
33+
2934
NActors::IActor* CreateDqLocalFileSpillingActor(TTxId txId, const TString& details, const NActors::TActorId& client, bool removeBlobsAfterRead);
3035

3136
NActors::IActor* CreateDqLocalFileSpillingService(const TFileSpillingServiceConfig& config, TIntrusivePtr<TSpillingCounters> counters);

ydb/library/yql/dq/actors/spilling/spilling_file_ut.cpp

+10-5
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,19 @@ class TTestActorRuntime: public TTestActorRuntimeBase {
4848
return str;
4949
}
5050

51+
const TString& GetSpillingSessionId() const {
52+
return SpillingSessionId_;
53+
}
54+
5155
TActorId StartSpillingService(ui64 maxTotalSize = 1000, ui64 maxFileSize = 500,
5256
ui64 maxFilePartSize = 100, const TFsPath& root = TFsPath::Cwd() / GetSpillingPrefix())
5357
{
5458
SpillingRoot_ = root;
59+
SpillingSessionId_ = CreateGuidAsString();
5560

5661
auto config = TFileSpillingServiceConfig{
5762
.Root = root.GetPath(),
63+
.SpillingSessionId = SpillingSessionId_,
5864
.MaxTotalSize = maxTotalSize,
5965
.MaxFileSize = maxFileSize,
6066
.MaxFilePartSize = maxFilePartSize
@@ -91,6 +97,7 @@ class TTestActorRuntime: public TTestActorRuntimeBase {
9197

9298
private:
9399
TFsPath SpillingRoot_;
100+
TString SpillingSessionId_;
94101
};
95102

96103
TBuffer CreateBlob(ui32 size, char symbol) {
@@ -303,8 +310,7 @@ Y_UNIT_TEST_SUITE(DqSpillingFileTests) {
303310
auto spillingActor = runtime.StartSpillingActor(tester);
304311

305312
runtime.WaitBootstrap();
306-
307-
const TString filePrefix = TStringBuilder() << runtime.GetSpillingRoot().GetPath() << "/node_" << runtime.GetNodeId() << "/1_test_";
313+
const TString filePrefix = TStringBuilder() << runtime.GetSpillingRoot().GetPath() << "/node_" << runtime.GetNodeId() << "_" << runtime.GetSpillingSessionId() << "/1_test_";
308314

309315
for (ui32 i = 0; i < 5; ++i) {
310316
// Cerr << "---- store blob #" << i << Endl;
@@ -346,7 +352,7 @@ Y_UNIT_TEST_SUITE(DqSpillingFileTests) {
346352

347353
runtime.WaitBootstrap();
348354

349-
const TString filePrefix = TStringBuilder() << runtime.GetSpillingRoot().GetPath() << "/node_" << runtime.GetNodeId() << "/1_test_";
355+
const TString filePrefix = TStringBuilder() << runtime.GetSpillingRoot().GetPath() << "/node_" << runtime.GetNodeId() << "_" << runtime.GetSpillingSessionId() << "/1_test_";
350356

351357
for (ui32 i = 0; i < 5; ++i) {
352358
// Cerr << "---- store blob #" << i << Endl;
@@ -393,8 +399,7 @@ Y_UNIT_TEST_SUITE(DqSpillingFileTests) {
393399
auto resp = runtime.GrabEdgeEvent<TEvDqSpilling::TEvWriteResult>(tester);
394400
UNIT_ASSERT_VALUES_EQUAL(0, resp->Get()->BlobId);
395401
}
396-
397-
auto nodePath = TFsPath("node_" + std::to_string(spillingSvc.NodeId()));
402+
auto nodePath = TFsPath("node_" + std::to_string(spillingSvc.NodeId()) + "_" + runtime.GetSpillingSessionId());
398403
(runtime.GetSpillingRoot() / nodePath / "1_test_0").ForceDelete();
399404

400405
{

ydb/library/yql/providers/dq/local_gateway/yql_dq_gateway_local.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,8 @@ class TLocalServiceHolder {
8080
TActorSetupCmd(resman, TMailboxType::Simple, 0));
8181

8282
if (withSpilling) {
83-
char tempDir[MAX_PATH];
84-
if (MakeTempDir(tempDir, nullptr) != 0)
85-
ythrow yexception() << "LocalServiceHolder: Can't create temporary directory " << tempDir;
83+
auto tempDir = NDq::GetTmpSpillingRootForCurrentUser();
84+
MakeDirIfNotExist(tempDir);
8685

8786
auto spillingActor = NDq::CreateDqLocalFileSpillingService(NDq::TFileSpillingServiceConfig{.Root = tempDir, .CleanupOnShutdown = true}, MakeIntrusive<NDq::TSpillingCounters>(lwmGroup));
8887

0 commit comments

Comments
 (0)