@@ -115,39 +115,82 @@ void TDirectoryHandlesStorage::ResetHandle(ui64 handleId)
115115
116116void TDirectoryHandlesStorage::LoadHandles (TDirectoryHandleMap& handles)
117117{
118- TGuard guard (TableLock);
118+ struct TUpdateVersionInfo
119+ {
120+ ui64 LargestUpdateVersion = 0 ;
121+ ui64 ChunksCount = 0 ;
122+ bool IsFirstChunkPresented = false ;
123+ };
124+
125+ TMap<ui64, TUpdateVersionInfo> updateVersionInfo;
126+
127+ {
128+ TGuard guard (TableLock);
129+
130+ for (auto it = Table->begin (); it != Table->end (); ++it) {
131+ TStringBuf record = *it;
132+ if (record.empty ()) {
133+ STORAGE_TRACE (
134+ " bad record from storage during load directory handles" );
135+ continue ;
136+ }
119137
120- for (auto it = Table->begin (); it != Table->end (); ++it) {
121- TStringBuf record = *it;
122- if (record.empty ()) {
123- STORAGE_TRACE (
124- " bad record from storage during load directory handles" );
125- continue ;
126- }
138+ auto [handleId, chunk] = DeserializeHandleChunk (record);
139+
140+ if (!handleId) {
141+ STORAGE_DEBUG (
142+ " bad deserialize for record %lu from storage during load "
143+ " directory handles" ,
144+ it.GetIndex ());
145+ continue ;
146+ }
127147
128- auto [handleId, chunk] = DeserializeHandleChunk (record);
148+ if (!handles.contains (handleId)) {
149+ handles[handleId] =
150+ std::make_shared<TDirectoryHandle>(chunk->Index );
151+ }
129152
130- if (!handleId) {
131- STORAGE_DEBUG (
132- " bad deserialize for record %lu from storage during load "
133- " directory handles" ,
134- it.GetIndex ());
135- continue ;
136- }
153+ handles[handleId]->ConsumeChunk (*chunk);
137154
138- if (!handles.contains (handleId)) {
139- handles[handleId] =
140- std::make_shared<TDirectoryHandle>(chunk->Index );
155+ updateVersionInfo[handleId].ChunksCount ++;
156+ if (chunk->UpdateVersion >
157+ updateVersionInfo[handleId].LargestUpdateVersion )
158+ {
159+ updateVersionInfo[handleId].LargestUpdateVersion =
160+ chunk->UpdateVersion ;
161+ }
162+
163+ if (chunk->UpdateVersion == 0 ) {
164+ updateVersionInfo[handleId].IsFirstChunkPresented = true ;
165+ HandleIdToIndices[handleId].insert (
166+ HandleIdToIndices[handleId].begin (),
167+ it.GetIndex ());
168+ } else {
169+ HandleIdToIndices[handleId].push_back (it.GetIndex ());
170+ }
141171 }
172+ }
142173
143- handles[handleId]->ConsumeChunk (*chunk);
174+ for (auto [handleId, updateVersionInfo]: updateVersionInfo) {
175+ if (!updateVersionInfo.IsFirstChunkPresented ) {
176+ ReportDirectoryHandlesStorageError (
177+ TStringBuilder ()
178+ << " First chunk for handle " << handleId << " is missing" );
144179
145- if (chunk->UpdateVersion == 0 ) {
146- HandleIdToIndices[handleId].insert (
147- HandleIdToIndices[handleId].begin (),
148- it.GetIndex ());
149- } else {
150- HandleIdToIndices[handleId].push_back (it.GetIndex ());
180+ RemoveHandle (handleId);
181+ continue ;
182+ }
183+
184+ if (updateVersionInfo.ChunksCount !=
185+ updateVersionInfo.LargestUpdateVersion + 1 )
186+ {
187+ ReportDirectoryHandlesStorageError (
188+ TStringBuilder ()
189+ << " Total chunks count " << updateVersionInfo.ChunksCount
190+ << " is not equal to largest update version "
191+ << updateVersionInfo.LargestUpdateVersion << " + 1" );
192+ ResetHandle (handleId);
193+ continue ;
151194 }
152195 }
153196}
0 commit comments