@@ -474,6 +474,12 @@ uint32 cfs_alloc_page(FileMap* map, uint32 oldSize, uint32 newSize)
474
474
return pg_atomic_fetch_add_u32 (& map -> hdr .physSize , newSize );
475
475
}
476
476
477
+ void cfs_undo_alloc_page (FileMap * map , uint32 oldSize , uint32 newSize )
478
+ {
479
+ pg_atomic_fetch_sub_u32 (& map -> hdr .usedSize , newSize - oldSize );
480
+ pg_atomic_fetch_sub_u32 (& map -> hdr .physSize , newSize );
481
+ }
482
+
477
483
/*
478
484
* Update logical file size
479
485
*/
@@ -643,12 +649,18 @@ static int cfs_cmp_page_offs(void const* p1, void const* p2)
643
649
return o1 < o2 ? -1 : o1 == o2 ? 0 : 1 ;
644
650
}
645
651
652
+ typedef enum {
653
+ CFS_BACKGROUND ,
654
+ CFS_EXPLICIT ,
655
+ CFS_IMPLICIT
656
+ } GC_CALL_KIND ;
657
+
646
658
/*
647
659
* Perform garbage collection (if required) on the file
648
660
* @param map_path - path to the map file (*.cfm).
649
661
* @param bacground - GC is performed in background by BGW: surpress error message and set CfsGcLock
650
662
*/
651
- static bool cfs_gc_file (char * map_path , bool background )
663
+ static bool cfs_gc_file (char * map_path , GC_CALL_KIND background )
652
664
{
653
665
int md ;
654
666
FileMap * map ;
@@ -662,25 +674,34 @@ static bool cfs_gc_file(char* map_path, bool background)
662
674
bool succeed = false;
663
675
int rc ;
664
676
665
-
666
677
pg_atomic_fetch_add_u32 (& cfs_state -> n_active_gc , 1 );
667
-
668
- while (!(background ? (cfs_state -> gc_enabled & cfs_state -> background_gc_enabled ) : cfs_state -> gc_enabled ))
678
+ if (background == CFS_IMPLICIT )
669
679
{
670
- pg_atomic_fetch_sub_u32 (& cfs_state -> n_active_gc , 1 );
680
+ if (!cfs_state -> gc_enabled )
681
+ {
682
+ pg_atomic_fetch_sub_u32 (& cfs_state -> n_active_gc , 1 );
683
+ return false;
684
+ }
685
+ }
686
+ else
687
+ {
688
+ while (!cfs_state -> gc_enabled || (background == CFS_BACKGROUND && !cfs_state -> background_gc_enabled ))
689
+ {
690
+ pg_atomic_fetch_sub_u32 (& cfs_state -> n_active_gc , 1 );
671
691
672
- rc = WaitLatch (MyLatch ,
673
- WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH ,
674
- CFS_DISABLE_TIMEOUT /* ms */ );
675
- if (cfs_gc_stop || (rc & WL_POSTMASTER_DEATH ))
676
- exit (1 );
692
+ rc = WaitLatch (MyLatch ,
693
+ WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH ,
694
+ CFS_DISABLE_TIMEOUT /* ms */ );
695
+ if (cfs_gc_stop || (rc & WL_POSTMASTER_DEATH ))
696
+ exit (1 );
677
697
678
- ResetLatch (MyLatch );
679
- CHECK_FOR_INTERRUPTS ();
698
+ ResetLatch (MyLatch );
699
+ CHECK_FOR_INTERRUPTS ();
680
700
681
- pg_atomic_fetch_add_u32 (& cfs_state -> n_active_gc , 1 );
701
+ pg_atomic_fetch_add_u32 (& cfs_state -> n_active_gc , 1 );
702
+ }
682
703
}
683
- if (background )
704
+ if (background == CFS_BACKGROUND )
684
705
{
685
706
LWLockAcquire (CfsGcLock , LW_SHARED ); /* avoid race condition with cfs_file_lock */
686
707
}
@@ -708,7 +729,7 @@ static bool cfs_gc_file(char* map_path, bool background)
708
729
cfs_state -> gc_stat .scannedFiles += 1 ;
709
730
710
731
/* do we need to perform defragmentation? */
711
- if ((uint64 )(physSize - usedSize )* 100 > (uint64 )physSize * cfs_gc_threshold )
732
+ if (physSize > CFS_IMPLICIT_GC_THRESHOLD || (uint64 )(physSize - usedSize )* 100 > (uint64 )physSize * cfs_gc_threshold )
712
733
{
713
734
long delay = CFS_LOCK_MIN_TIMEOUT ;
714
735
char * file_path = (char * )palloc (suf + 1 );
@@ -1030,7 +1051,7 @@ static bool cfs_gc_file(char* map_path, bool background)
1030
1051
pfree (inodes );
1031
1052
pfree (newMap );
1032
1053
1033
- if (cfs_gc_delay != 0 )
1054
+ if (cfs_gc_delay != 0 && background == CFS_BACKGROUND )
1034
1055
{
1035
1056
int rc = WaitLatch (MyLatch ,
1036
1057
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH ,
@@ -1058,7 +1079,7 @@ static bool cfs_gc_file(char* map_path, bool background)
1058
1079
}
1059
1080
1060
1081
FinishGC :
1061
- if (background )
1082
+ if (background == CFS_BACKGROUND )
1062
1083
{
1063
1084
LWLockRelease (CfsGcLock );
1064
1085
}
@@ -1097,7 +1118,7 @@ static bool cfs_gc_directory(int worker_id, char const* path)
1097
1118
strcmp (file_path + len - 4 , ".cfm" ) == 0 )
1098
1119
{
1099
1120
if (entry -> d_ino % cfs_state -> n_workers == worker_id
1100
- && !cfs_gc_file (file_path , true ))
1121
+ && !cfs_gc_file (file_path , CFS_BACKGROUND ))
1101
1122
{
1102
1123
success = false;
1103
1124
break ;
@@ -1195,6 +1216,7 @@ bool cfs_control_gc(bool enabled)
1195
1216
{
1196
1217
bool was_enabled = cfs_state -> gc_enabled ;
1197
1218
cfs_state -> gc_enabled = enabled ;
1219
+ pg_memory_barrier ();
1198
1220
if (was_enabled && !enabled )
1199
1221
{
1200
1222
/* Wait until there are no active GC workers */
@@ -1238,9 +1260,7 @@ Datum cfs_start_gc(PG_FUNCTION_ARGS)
1238
1260
int j ;
1239
1261
BackgroundWorkerHandle * * handles ;
1240
1262
1241
- cfs_gc_stop = true; /* do just one iteration */
1242
-
1243
- cfs_state -> max_iterations = 1 ;
1263
+ cfs_state -> max_iterations = 1 ; /* do just one iteration */
1244
1264
cfs_state -> n_workers = PG_GETARG_INT32 (0 );
1245
1265
handles = (BackgroundWorkerHandle * * )palloc (cfs_state -> n_workers * sizeof (BackgroundWorkerHandle * ));
1246
1266
@@ -1460,39 +1480,46 @@ Datum cfs_gc_relation(PG_FUNCTION_ARGS)
1460
1480
char * path ;
1461
1481
char * map_path ;
1462
1482
int i = 0 ;
1463
-
1464
- LWLockAcquire (CfsGcLock , LW_EXCLUSIVE ); /* Prevent interaction with background GC */
1483
+ bool stop = false;
1465
1484
1466
1485
processed_segments = cfs_gc_processed_segments ;
1467
1486
1468
1487
path = relpathbackend (rel -> rd_node , rel -> rd_backend , MAIN_FORKNUM );
1469
1488
map_path = (char * )palloc (strlen (path ) + 16 );
1470
1489
sprintf (map_path , "%s.cfm" , path );
1471
1490
1472
- while ( cfs_gc_file ( map_path , false))
1491
+ do
1473
1492
{
1493
+ LWLockAcquire (CfsGcLock , LW_EXCLUSIVE ); /* Prevent interaction with background GC */
1494
+ stop = !cfs_gc_file (map_path , CFS_EXPLICIT );
1495
+ LWLockRelease (CfsGcLock );
1474
1496
sprintf (map_path , "%s.%u.cfm" , path , ++ i );
1475
- }
1497
+ } while (! stop );
1476
1498
pfree (path );
1477
1499
pfree (map_path );
1478
1500
relation_close (rel , AccessShareLock );
1479
1501
1480
1502
processed_segments = cfs_gc_processed_segments - processed_segments ;
1481
-
1482
- LWLockRelease (CfsGcLock );
1483
1503
}
1484
1504
PG_RETURN_INT32 (processed_segments );
1485
1505
}
1486
1506
1487
1507
1488
- void cfs_gc_segment (char const * fileName )
1508
+ void cfs_gc_segment (char const * fileName , bool optional )
1489
1509
{
1490
- char * mapFileName = psprintf ( "%s.cfm" , fileName ) ;
1510
+ char * mapFileName ;
1491
1511
1492
- LWLockAcquire (CfsGcLock , LW_EXCLUSIVE ); /* Prevent interaction with background GC */
1512
+ if (optional )
1513
+ {
1514
+ if (!LWLockConditionalAcquire (CfsGcLock , LW_EXCLUSIVE )) /* Prevent interaction with background GC */
1515
+ return ;
1516
+ }
1517
+ else
1518
+ LWLockAcquire (CfsGcLock , LW_EXCLUSIVE ); /* Prevent interaction with background GC */
1493
1519
1494
- cfs_gc_file ( mapFileName , false );
1520
+ mapFileName = psprintf ( "%s.cfm" , fileName );
1495
1521
1522
+ cfs_gc_file (mapFileName , optional ? CFS_IMPLICIT : CFS_EXPLICIT );
1496
1523
LWLockRelease (CfsGcLock );
1497
1524
1498
1525
pfree (mapFileName );
0 commit comments