5353import java .util .List ;
5454import java .util .Map ;
5555import java .util .Set ;
56+ import java .util .UUID ;
5657import java .util .concurrent .atomic .AtomicLong ;
58+ import java .util .stream .Collectors ;
5759import java .util .stream .Stream ;
5860import javax .servlet .ServletException ;
5961import javax .servlet .http .HttpServletRequest ;
7072import org .apache .hadoop .ozone .OzoneConsts ;
7173import org .apache .hadoop .ozone .lock .BootstrapStateHandler ;
7274import org .apache .hadoop .ozone .om .helpers .SnapshotInfo ;
75+ import org .apache .hadoop .ozone .om .lock .HierarchicalResourceLockManager .HierarchicalResourceLock ;
7376import org .apache .hadoop .ozone .om .lock .OMLockDetails ;
7477import org .apache .hadoop .ozone .om .snapshot .OmSnapshotLocalDataManager ;
7578import org .apache .hadoop .ozone .om .snapshot .OmSnapshotUtils ;
@@ -208,7 +211,6 @@ Path getCompactionLogDir() {
208211 * @param tmpdir Temporary directory for staging files during archiving.
209212 * @throws IOException if an I/O error occurs during processing or streaming.
210213 */
211-
212214 public void writeDbDataToStream (HttpServletRequest request , OutputStream destination ,
213215 Set <String > sstFilesToExclude , Path tmpdir ) throws IOException {
214216 DBCheckpoint checkpoint = null ;
@@ -219,12 +221,12 @@ public void writeDbDataToStream(HttpServletRequest request, OutputStream destina
219221 AtomicLong maxTotalSstSize = new AtomicLong (getConf ().getLong (OZONE_OM_RATIS_SNAPSHOT_MAX_TOTAL_SST_SIZE_KEY ,
220222 OZONE_OM_RATIS_SNAPSHOT_MAX_TOTAL_SST_SIZE_DEFAULT ));
221223
222- Set <Path > snapshotPaths = Collections .emptySet ();
224+ Collection <Path > snapshotPaths = Collections .emptySet ();
223225
224226 if (!includeSnapshotData ) {
225227 maxTotalSstSize .set (Long .MAX_VALUE );
226228 } else {
227- snapshotPaths = getSnapshotDirsFromDB (omMetadataManager , omMetadataManager , snapshotLocalDataManager );
229+ snapshotPaths = getSnapshotDirsFromDB (omMetadataManager , omMetadataManager , snapshotLocalDataManager ). values () ;
228230 }
229231
230232 if (sstFilesToExclude .isEmpty ()) {
@@ -260,6 +262,7 @@ public void writeDbDataToStream(HttpServletRequest request, OutputStream destina
260262 // this is the last step where we transfer the active om.db contents
261263 Map <String , String > hardLinkFileMap = new HashMap <>();
262264 SnapshotCache snapshotCache = om .getOmSnapshotManager ().getSnapshotCache ();
265+ OmSnapshotLocalDataManager localDataManager = om .getOmSnapshotManager ().getSnapshotLocalDataManager ();
263266 /*
264267 * Acquire snapshot cache lock when includeSnapshotData is true to prevent race conditions
265268 * between checkpoint operations and snapshot purge operations. Without this lock, a purge
@@ -272,7 +275,9 @@ public void writeDbDataToStream(HttpServletRequest request, OutputStream destina
272275 * In this case, the try-with-resources block does not call close() on any resource,
273276 * which is intentional because snapshot consistency is not required.
274277 */
275- try (UncheckedAutoCloseableSupplier <OMLockDetails > lock = includeSnapshotData ? snapshotCache .lock () : null ) {
278+ try (UncheckedAutoCloseableSupplier <OMLockDetails > snapshotDBLock =
279+ includeSnapshotData ? snapshotCache .lock () : null ;
280+ HierarchicalResourceLock snapshotLocalDataLock = includeSnapshotData ? localDataManager .lock () : null ) {
276281 // get the list of sst files of the checkpoint.
277282 checkpoint = createAndPrepareCheckpoint (true );
278283 // unlimited files as we want the Active DB contents to be transferred in a single batch
@@ -283,18 +288,21 @@ public void writeDbDataToStream(HttpServletRequest request, OutputStream destina
283288 if (includeSnapshotData ) {
284289 List <Path > sstBackupFiles = extractSSTFilesFromCompactionLog (checkpoint );
285290 // get the list of snapshots from the checkpoint
291+ Map <UUID , Path > snapshotInCheckpoint ;
286292 try (OmMetadataManagerImpl checkpointMetadataManager = OmMetadataManagerImpl
287293 .createCheckpointMetadataManager (om .getConfiguration (), checkpoint )) {
288- snapshotPaths = getSnapshotDirsFromDB (omMetadataManager , checkpointMetadataManager ,
294+ snapshotInCheckpoint = getSnapshotDirsFromDB (omMetadataManager , checkpointMetadataManager ,
289295 snapshotLocalDataManager );
290296 }
291297 writeDBToArchive (sstFilesToExclude , getCompactionLogDir (), maxTotalSstSize , archiveOutputStream , tmpdir ,
292298 hardLinkFileMap , false );
293299 writeDBToArchive (sstFilesToExclude , sstBackupFiles .stream (), maxTotalSstSize , archiveOutputStream , tmpdir ,
294300 hardLinkFileMap , false );
301+ Collection <Path > snapshotLocalPropertyFiles = getSnapshotLocalDataPaths (localDataManager ,
302+ snapshotInCheckpoint .keySet ());
295303 // This is done to ensure all data to be copied correctly is flushed in the snapshot DB
296- transferSnapshotData (sstFilesToExclude , tmpdir , snapshotPaths , maxTotalSstSize , archiveOutputStream ,
297- hardLinkFileMap );
304+ transferSnapshotData (sstFilesToExclude , tmpdir , snapshotInCheckpoint . values (), snapshotLocalPropertyFiles ,
305+ maxTotalSstSize , archiveOutputStream , hardLinkFileMap );
298306 }
299307 }
300308 writeHardlinkFile (getConf (), hardLinkFileMap , archiveOutputStream );
@@ -309,6 +317,36 @@ public void writeDbDataToStream(HttpServletRequest request, OutputStream destina
309317 }
310318 }
311319
320+ /**
321+ * Retrieves the paths to the local property YAML files for the specified snapshot IDs.
322+ * This method resolves the chain of previous snapshot references for each snapshot ID
323+ * and gathers their corresponding local property YAML file paths.
324+ *
325+ * @param localDataManager The OmSnapshotLocalDataManager instance responsible for managing
326+ * snapshot data and metadata.
327+ * @param snapshotIds A set of snapshot IDs for which the local property YAML file
328+ * paths should be resolved.
329+ * @return A collection of paths to the local property YAML files for the specified
330+ * snapshot IDs.
331+ */
332+ private Collection <Path > getSnapshotLocalDataPaths (OmSnapshotLocalDataManager localDataManager ,
333+ Set <UUID > snapshotIds ) {
334+ Set <UUID > snapshotLocalDataIds = new HashSet <>();
335+ Map <UUID , OmSnapshotLocalDataManager .SnapshotVersionsMeta > versionNodeMap =
336+ localDataManager .getVersionNodeMapUnmodifiable ();
337+ for (UUID snapshot : snapshotIds ) {
338+ UUID id = snapshot ;
339+ // Get the previous snapshot id for the current snapshot id until we reach null or the first snapshot id which
340+ // is already in the snapshotLocalDataIds set.
341+ while (id != null && !snapshotLocalDataIds .contains (id )) {
342+ snapshotLocalDataIds .add (id );
343+ id = versionNodeMap .get (id ).getPreviousSnapshotId ();
344+ }
345+ }
346+ return snapshotLocalDataIds .stream ().map (localDataManager ::getSnapshotLocalPropertyYamlPath )
347+ .map (Paths ::get ).collect (Collectors .toList ());
348+ }
349+
312350 /**
313351 * Transfers the snapshot data from the specified snapshot directories into the archive output stream,
314352 * handling deduplication and managing resource locking.
@@ -321,19 +359,18 @@ public void writeDbDataToStream(HttpServletRequest request, OutputStream destina
321359 * @param hardLinkFileMap Map of hardlink file paths to their unique identifiers for deduplication.
322360 * @throws IOException if an I/O error occurs during processing.
323361 */
324- void transferSnapshotData (Set <String > sstFilesToExclude , Path tmpdir , Set <Path > snapshotPaths ,
325- AtomicLong maxTotalSstSize , ArchiveOutputStream <TarArchiveEntry > archiveOutputStream ,
326- Map <String , String > hardLinkFileMap ) throws IOException {
362+ void transferSnapshotData (Set <String > sstFilesToExclude , Path tmpdir , Collection <Path > snapshotPaths ,
363+ Collection <Path > snapshotLocalPropertyFiles , AtomicLong maxTotalSstSize ,
364+ ArchiveOutputStream <TarArchiveEntry > archiveOutputStream , Map <String , String > hardLinkFileMap )
365+ throws IOException {
327366 for (Path snapshotDir : snapshotPaths ) {
328367 writeDBToArchive (sstFilesToExclude , snapshotDir , maxTotalSstSize , archiveOutputStream , tmpdir , hardLinkFileMap ,
329368 false );
330- Path snapshotLocalPropertyYaml = Paths .get (
331- OmSnapshotLocalDataManager .getSnapshotLocalPropertyYamlPath (snapshotDir ));
332- if (Files .exists (snapshotLocalPropertyYaml )) {
333- File yamlFile = snapshotLocalPropertyYaml .toFile ();
334- hardLinkFileMap .put (yamlFile .getAbsolutePath (), yamlFile .getName ());
335- linkAndIncludeFile (yamlFile , yamlFile .getName (), archiveOutputStream , tmpdir );
336- }
369+ }
370+ for (Path snapshotLocalPropertyYaml : snapshotLocalPropertyFiles ) {
371+ File yamlFile = snapshotLocalPropertyYaml .toFile ();
372+ hardLinkFileMap .put (yamlFile .getAbsolutePath (), yamlFile .getName ());
373+ linkAndIncludeFile (yamlFile , yamlFile .getName (), archiveOutputStream , tmpdir );
337374 }
338375 }
339376
@@ -399,12 +436,12 @@ private OzoneConfiguration getConf() {
399436 * Collects paths to all snapshot databases from the OM DB.
400437 *
401438 * @param activeOMMetadataManager OMMetadataManager instance
402- * @return Set of paths to snapshot databases
439+ * @return Map of paths to snapshot databases with snapshot IDs as keys.
403440 * @throws IOException if an I/O error occurs
404441 */
405- Set < Path > getSnapshotDirsFromDB (OMMetadataManager activeOMMetadataManager , OMMetadataManager omMetadataManager ,
442+ Map < UUID , Path > getSnapshotDirsFromDB (OMMetadataManager activeOMMetadataManager , OMMetadataManager omMetadataManager ,
406443 OmSnapshotLocalDataManager localDataManager ) throws IOException {
407- Set < Path > snapshotPaths = new HashSet <>();
444+ Map < UUID , Path > snapshotPaths = new HashMap <>();
408445 try (TableIterator <String , ? extends Table .KeyValue <String , SnapshotInfo >> iter =
409446 omMetadataManager .getSnapshotInfoTable ().iterator ()) {
410447 while (iter .hasNext ()) {
@@ -414,7 +451,7 @@ Set<Path> getSnapshotDirsFromDB(OMMetadataManager activeOMMetadataManager, OMMet
414451 localDataManager .getOmSnapshotLocalDataMeta (snapshotInfo .getSnapshotId ())) {
415452 Path snapshotDir = getSnapshotPath (activeOMMetadataManager , snapshotInfo .getSnapshotId (),
416453 snapLocalMeta .getMeta ().getVersion ());
417- snapshotPaths .add ( snapshotDir );
454+ snapshotPaths .put ( snapshotInfo . getSnapshotId (), snapshotDir );
418455 }
419456 }
420457 }
0 commit comments