13
13
#include < util/folder/path.h>
14
14
#include < util/stream/file.h>
15
15
#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>
16
21
17
22
namespace NYql ::NDq {
18
23
@@ -159,6 +164,7 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
159
164
EvCloseFileResponse = TEvDqSpillingLocalFile::EEv::LastEvent + 1 ,
160
165
EvWriteFileResponse,
161
166
EvReadFileResponse,
167
+ EvRemoveOldTmp,
162
168
163
169
LastEvent
164
170
};
@@ -189,6 +195,15 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
189
195
bool Removed = false ;
190
196
TMaybe<TString> Error;
191
197
};
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
+ };
192
207
};
193
208
194
209
struct TFileDesc ;
@@ -206,8 +221,12 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
206
221
207
222
void Bootstrap () {
208
223
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 ();
210
227
228
+ Root_ /= (TStringBuilder () << " node_" << nodeId << " _" << sessionId);
229
+ // Cerr << "Root from config: " << Config_.Root << ", actual root: " << Root_ << "\n";
211
230
LOG_I (" Init DQ local file spilling service at " << Root_ << " , actor: " << SelfId ());
212
231
213
232
try {
@@ -221,6 +240,8 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
221
240
Become (&TDqLocalFileSpillingService::BrokenState);
222
241
return ;
223
242
}
243
+
244
+ Send (SelfId (), MakeHolder<TEvPrivate::TEvRemoveOldTmp>(Root_, nodeId, sessionId));
224
245
225
246
Become (&TDqLocalFileSpillingService::WorkState);
226
247
}
@@ -271,6 +292,7 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
271
292
hFunc(TEvPrivate::TEvWriteFileResponse, HandleWork)
272
293
hFunc(TEvDqSpilling::TEvRead, HandleWork)
273
294
hFunc(TEvPrivate::TEvReadFileResponse, HandleWork)
295
+ hFunc(TEvPrivate::TEvRemoveOldTmp, HandleWork)
274
296
hFunc(NMon::TEvHttpInfo, HandleWork)
275
297
cFunc(TEvents::TEvPoison::EventType, PassAway)
276
298
);
@@ -712,6 +734,55 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
712
734
Send (ev->Sender , new NMon::TEvHttpInfoRes (s.Str ()));
713
735
}
714
736
737
+ void HandleWork (TEvPrivate::TEvRemoveOldTmp::TPtr& ev) {
738
+ const auto & msg = *ev->Get ();
739
+ const auto & root = msg.TmpRoot ;
740
+ const auto nodeIdString = ToString (msg.NodeId );
741
+ const auto & sessionId = msg.SpillingSessionId ;
742
+
743
+ LOG_I (" [RemoveOldTmp] removing at root: " << root);
744
+
745
+ static const auto isDirOldTmp = [&nodeIdString, &sessionId](TString dirName) -> bool {
746
+ // dirName: node_<nodeId>_<sessionId>
747
+ static constexpr size_t NodeIdBegin = 5 ;
748
+ if (dirName.Size () < NodeIdBegin || dirName.substr (0 , NodeIdBegin) != " node_" ) {
749
+ return false ;
750
+ }
751
+ const auto nodeIdEnd = dirName.find (' _' , NodeIdBegin);
752
+ if (nodeIdEnd == TString::npos || dirName.substr (NodeIdBegin, nodeIdEnd - NodeIdBegin) != nodeIdString) {
753
+ return false ;
754
+ }
755
+ if (dirName.substr (nodeIdEnd + 1 ) == sessionId) {
756
+ return false ;
757
+ }
758
+ return true ;
759
+ };
760
+
761
+ try {
762
+ TDirIterator iter (root, TDirIterator::TOptions ().SetMaxLevel (1 ));
763
+
764
+ TVector<TString> oldTmps;
765
+ for (const auto &dirEntry : iter) {
766
+ if (dirEntry.fts_info == FTS_DP) {
767
+ // skip postorder visit
768
+ continue ;
769
+ }
770
+
771
+ const auto dirName = dirEntry.fts_name ;
772
+ if (isDirOldTmp (dirName)) {
773
+ LOG_D (" [RemoveOldTmp] found old temporary at " << (root / dirName));
774
+ oldTmps.emplace_back (std::move (dirName));
775
+ }
776
+ }
777
+
778
+ ForEach (oldTmps.begin (), oldTmps.end (), [&root](const auto & dirName) {
779
+ (root / dirName).ForceDelete ();
780
+ });
781
+ } catch (const yexception& e) {
782
+ LOG_E (" [RemoveOldTmp] removing failed due to: " << e.what ());
783
+ }
784
+ }
785
+
715
786
private:
716
787
void RunOp (TStringBuf opName, THolder<IObjectInQueue> op, TFileDesc& fd) {
717
788
if (fd.HasActiveOp ) {
@@ -952,6 +1023,13 @@ class TDqLocalFileSpillingService : public TActorBootstrapped<TDqLocalFileSpilli
952
1023
953
1024
} // anonymous namespace
954
1025
1026
+ TFsPath GetTmpSpillingRootForCurrentUser () {
1027
+ auto root = TFsPath{GetSystemTempDir ()};
1028
+ root /= " spilling-tmp-" + GetUsername ();
1029
+ MakeDirIfNotExist (root);
1030
+ return root;
1031
+ }
1032
+
955
1033
IActor* CreateDqLocalFileSpillingActor (TTxId txId, const TString& details, const TActorId& client,
956
1034
bool removeBlobsAfterRead)
957
1035
{
0 commit comments