@@ -1345,6 +1345,155 @@ static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts
1345
1345
return 0 ;
1346
1346
}
1347
1347
1348
+
1349
+ static void copy_file (const char * srcdir , const char * dstdir , const char * name )
1350
+ {
1351
+ int ret = 0 ;
1352
+ struct strbuf src = STRBUF_INIT , dst = STRBUF_INIT ;
1353
+ int srcfd = -1 , dstfd = -1 ;
1354
+ char buf [1024 ];
1355
+ ssize_t nr ;
1356
+
1357
+ strbuf_addf (& src , "%s/%s" , srcdir , name );
1358
+ strbuf_addf (& dst , "%s/%s" , dstdir , name );
1359
+
1360
+ srcfd = open (src .buf , O_RDONLY );
1361
+ if (srcfd < 0 ) {
1362
+ error ("failed to open source file" );
1363
+ ret = 1 ;
1364
+ goto cleanup ;
1365
+ }
1366
+
1367
+ dstfd = open (dst .buf , O_WRONLY | O_CREAT | O_TRUNC , 0644 );
1368
+ if (dstfd < 0 ) {
1369
+ error ("failed to open destination file" );
1370
+ ret = 1 ;
1371
+ goto cleanup ;
1372
+ }
1373
+
1374
+ while ((nr = read (srcfd , buf , sizeof (buf ))) > 0 ) {
1375
+ if (write (dstfd , buf , nr ) < 0 ) {
1376
+ error ("failed to write to destination file" );
1377
+ ret = 1 ;
1378
+ }
1379
+ }
1380
+
1381
+ cleanup :
1382
+ if (srcfd >= 0 ) close (srcfd );
1383
+ if (dstfd >= 0 ) close (dstfd );
1384
+
1385
+ if (ret )
1386
+ die_errno (_ ("failed to copy '%s' to '%s'" ), src .buf , dst .buf );
1387
+
1388
+ strbuf_release (& src );
1389
+ strbuf_release (& dst );
1390
+ }
1391
+
1392
+ static void move_file (const char * srcdir , const char * dstdir , const char * name )
1393
+ {
1394
+ struct strbuf src = STRBUF_INIT , dst = STRBUF_INIT ;
1395
+
1396
+ strbuf_addf (& src , "%s/%s" , srcdir , name );
1397
+ strbuf_addf (& dst , "%s/%s" , dstdir , name );
1398
+
1399
+ if (rename (src .buf , dst .buf ))
1400
+ die_errno (_ ("failed to move '%s' to '%s'" ), src .buf , dst .buf );
1401
+
1402
+ strbuf_release (& src );
1403
+ strbuf_release (& dst );
1404
+ }
1405
+
1406
+ static void delete_file (const char * dir , const char * name )
1407
+ {
1408
+ struct strbuf path = STRBUF_INIT ;
1409
+
1410
+ strbuf_addf (& path , "%s/%s" , dir , name );
1411
+
1412
+ if (unlink (path .buf ))
1413
+ warning_errno (_ ("failed to delete '%s'" ), path .buf );
1414
+
1415
+ strbuf_release (& path );
1416
+ }
1417
+
1418
+ static void migrate_pack (const char * srcdir , const char * dstdir ,
1419
+ const char * pack_filename )
1420
+ {
1421
+ struct strbuf path = STRBUF_INIT ;
1422
+ struct stat st ;
1423
+ char * basename , * keep_filename , * rev_filename , * idx_filename ;
1424
+ int has_keep , has_rev ;
1425
+
1426
+ basename = xstrndup (pack_filename , strlen (pack_filename ) - 5 /*.pack*/ );
1427
+ keep_filename = xstrfmt ("%s.keep" , basename );
1428
+ rev_filename = xstrfmt ("%s.rev" , basename );
1429
+ idx_filename = xstrfmt ("%s.idx" , basename );
1430
+
1431
+ strbuf_addf (& path , "%s/%s" , srcdir , keep_filename );
1432
+ has_keep = !stat (path .buf , & st );
1433
+ strbuf_reset (& path );
1434
+ strbuf_addf (& path , "%s/%s" , srcdir , rev_filename );
1435
+ has_rev = !stat (path .buf , & st );
1436
+ strbuf_release (& path );
1437
+
1438
+ /* Copy all but the index file, which we will *move* atomically */
1439
+ copy_file (srcdir , dstdir , pack_filename );
1440
+ if (has_keep ) copy_file (srcdir , dstdir , keep_filename );
1441
+ if (has_rev ) copy_file (srcdir , dstdir , rev_filename );
1442
+ move_file (srcdir , dstdir , idx_filename );
1443
+
1444
+ /*
1445
+ * Now the pack and associated files exist at the destination we
1446
+ * we can now clean up files in the source directory.
1447
+ */
1448
+ delete_file (srcdir , pack_filename );
1449
+ if (has_keep ) delete_file (srcdir , keep_filename );
1450
+ if (has_rev ) delete_file (srcdir , rev_filename );
1451
+
1452
+ free (idx_filename );
1453
+ free (keep_filename );
1454
+ free (rev_filename );
1455
+ }
1456
+
1457
+ static void move_pack_to_vfs_cache (const char * full_path , size_t full_path_len ,
1458
+ const char * file_name , UNUSED void * data )
1459
+ {
1460
+ char * srcdir ;
1461
+ struct strbuf dstdir = STRBUF_INIT ;
1462
+
1463
+ /* We only care about the actual pack files here.
1464
+ * The associated .idx, .keep, .rev files will be copied in tandem
1465
+ * with the pack file, with the index file being moved last.
1466
+ * The original locations of the non-index files will only deleted
1467
+ * once all other files have been copied/moved.
1468
+ */
1469
+ if (!ends_with (file_name , ".pack" ))
1470
+ return ;
1471
+
1472
+ srcdir = xstrndup (full_path , full_path_len - strlen (file_name ) - 1 );
1473
+
1474
+ /* No cache or same source + desintation means there's no work to do. */
1475
+ if (!object_dir || !fspathcmp (srcdir , object_dir ))
1476
+ return ;
1477
+
1478
+ strbuf_addf (& dstdir , "%s/pack" , object_dir );
1479
+
1480
+ migrate_pack (srcdir , dstdir .buf , file_name );
1481
+
1482
+ free (srcdir );
1483
+ strbuf_release (& dstdir );
1484
+ }
1485
+
1486
+ static int maintenance_task_vfs_cache_move (UNUSED struct maintenance_run_opts * opts ,
1487
+ UNUSED struct gc_config * cfg )
1488
+ {
1489
+ struct repository * r = the_repository ;
1490
+
1491
+ for_each_file_in_pack_dir (r -> objects -> odb -> path , move_pack_to_vfs_cache ,
1492
+ NULL );
1493
+
1494
+ return 0 ;
1495
+ }
1496
+
1348
1497
typedef int maintenance_task_fn (struct maintenance_run_opts * opts ,
1349
1498
struct gc_config * cfg );
1350
1499
@@ -1374,6 +1523,7 @@ enum maintenance_task_label {
1374
1523
TASK_GC ,
1375
1524
TASK_COMMIT_GRAPH ,
1376
1525
TASK_PACK_REFS ,
1526
+ TASK_VFS_CACHE_MOVE ,
1377
1527
1378
1528
/* Leave as final value */
1379
1529
TASK__COUNT
@@ -1410,6 +1560,10 @@ static struct maintenance_task tasks[] = {
1410
1560
maintenance_task_pack_refs ,
1411
1561
pack_refs_condition ,
1412
1562
},
1563
+ [TASK_VFS_CACHE_MOVE ] = {
1564
+ "vfs-cache-move" ,
1565
+ maintenance_task_vfs_cache_move ,
1566
+ },
1413
1567
};
1414
1568
1415
1569
static int compare_tasks_by_selection (const void * a_ , const void * b_ )
@@ -1504,6 +1658,8 @@ static void initialize_maintenance_strategy(void)
1504
1658
tasks [TASK_LOOSE_OBJECTS ].schedule = SCHEDULE_DAILY ;
1505
1659
tasks [TASK_PACK_REFS ].enabled = 1 ;
1506
1660
tasks [TASK_PACK_REFS ].schedule = SCHEDULE_WEEKLY ;
1661
+ tasks [TASK_VFS_CACHE_MOVE ].enabled = 1 ;
1662
+ tasks [TASK_VFS_CACHE_MOVE ].schedule = SCHEDULE_WEEKLY ;
1507
1663
}
1508
1664
}
1509
1665
0 commit comments