55 */
66
77#include "ts_stats_record.h"
8+ #include "ts_stats/ts_stats_defs.h"
89#include "ts_stats_segment.h"
910
1011#include <postgres.h>
1112#include <miscadmin.h>
1213#include <storage/lwlock.h>
14+ #include <utils/dsa.h>
1315#include <utils/timestamp.h>
1416
1517static inline uint64
@@ -36,10 +38,10 @@ slot_touch_timestamps(TsStatsChunk *slot, uint64 now_us)
3638}
3739
3840void
39- ts_stats_chunk_record_compression (Oid compressed_relid , Oid uncompressed_relid ,
40- const CompressionStatsAccumulator * a )
41+ ts_stats_chunk_record_compression (TsStatsRelids relids , const CompressionStatsAccumulator * a )
4142{
42- if (!OidIsValid (compressed_relid ) || !OidIsValid (uncompressed_relid ) || a -> batch_count == 0 )
43+ if (!OidIsValid (relids .compressed_relid ) || !OidIsValid (relids .uncompressed_relid ) ||
44+ a -> batch_count == 0 )
4345 {
4446 return ;
4547 }
@@ -53,8 +55,7 @@ ts_stats_chunk_record_compression(Oid compressed_relid, Oid uncompressed_relid,
5355 /* get the slot_index for the upsert. this sets the in-progress flag and updates the bucket's
5456 * metadata if successful.
5557 */
56- int32 slot_idx =
57- ts_stats_chunk_segment_prepare_upsert (seg , compressed_relid , uncompressed_relid );
58+ int32 slot_idx = ts_stats_chunk_segment_prepare_upsert (seg , relids );
5859 if (slot_idx == TS_STATS_INVALID_IDX )
5960 {
6061 /* if we failed to find or insert a slot for this compressed_relid, we just give up this
@@ -85,14 +86,13 @@ ts_stats_chunk_record_compression(Oid compressed_relid, Oid uncompressed_relid,
8586 slot_touch_timestamps (slot , now_us );
8687
8788 /* clear the in-progress flag */
88- ts_stats_chunk_segment_finish_upsert (seg , slot_idx , compressed_relid );
89+ ts_stats_chunk_segment_finish_upsert (seg , slot_idx , relids . compressed_relid );
8990}
9091
9192void
92- ts_stats_chunk_record_cmd (Oid compressed_relid , Oid uncompressed_relid , CmdType cmd ,
93- const SharedCounters * c )
93+ ts_stats_chunk_record_cmd (TsStatsRelids relids , CmdType cmd , const SharedCounters * c )
9494{
95- if (!OidIsValid (compressed_relid ) || !OidIsValid (uncompressed_relid ) || c == NULL )
95+ if (!OidIsValid (relids . compressed_relid ) || !OidIsValid (relids . uncompressed_relid ) || c == NULL )
9696 {
9797 return ;
9898 }
@@ -110,8 +110,7 @@ ts_stats_chunk_record_cmd(Oid compressed_relid, Oid uncompressed_relid, CmdType
110110 /* get the slot_index for the upsert. this sets the in-progress flag and updates the bucket's
111111 * metadata if successful.
112112 */
113- int32 slot_idx =
114- ts_stats_chunk_segment_prepare_upsert (seg , compressed_relid , uncompressed_relid );
113+ int32 slot_idx = ts_stats_chunk_segment_prepare_upsert (seg , relids );
115114 if (slot_idx == TS_STATS_INVALID_IDX )
116115 {
117116 /* if we failed to find or insert a slot for this compressed_relid, we just give up this
@@ -185,14 +184,13 @@ ts_stats_chunk_record_cmd(Oid compressed_relid, Oid uncompressed_relid, CmdType
185184 slot_touch_timestamps (slot , now_us );
186185
187186 /* clear the in-progress flag */
188- ts_stats_chunk_segment_finish_upsert (seg , slot_idx , compressed_relid );
187+ ts_stats_chunk_segment_finish_upsert (seg , slot_idx , relids . compressed_relid );
189188}
190189
191190void
192- ts_stats_chunk_record_decompression (Oid compressed_relid , Oid uncompressed_relid ,
193- const CompressionStatsAccumulator * a )
191+ ts_stats_chunk_record_decompression (TsStatsRelids relids , const CompressionStatsAccumulator * a )
194192{
195- if (!OidIsValid (compressed_relid ) || !OidIsValid (uncompressed_relid ))
193+ if (!OidIsValid (relids . compressed_relid ) || !OidIsValid (relids . uncompressed_relid ))
196194 {
197195 return ;
198196 }
@@ -210,8 +208,7 @@ ts_stats_chunk_record_decompression(Oid compressed_relid, Oid uncompressed_relid
210208 /* get the slot_index for the upsert. this sets the in-progress flag and updates the bucket's
211209 * metadata if successful.
212210 */
213- int32 slot_idx =
214- ts_stats_chunk_segment_prepare_upsert (seg , compressed_relid , uncompressed_relid );
211+ int32 slot_idx = ts_stats_chunk_segment_prepare_upsert (seg , relids );
215212 if (slot_idx == TS_STATS_INVALID_IDX )
216213 {
217214 /* if we failed to find or insert a slot for this compressed_relid, we just give up this
@@ -257,7 +254,7 @@ ts_stats_chunk_record_decompression(Oid compressed_relid, Oid uncompressed_relid
257254 slot_touch_timestamps (slot , now_us );
258255
259256 /* clear the in-progress flag */
260- ts_stats_chunk_segment_finish_upsert (seg , slot_idx , compressed_relid );
257+ ts_stats_chunk_segment_finish_upsert (seg , slot_idx , relids . compressed_relid );
261258}
262259
263260bool
@@ -290,3 +287,52 @@ ts_stats_chunk_lookup(Oid compressed_relid, TsStatsChunk *out)
290287 memcpy (out , slot , sizeof (TsStatsChunk ));
291288 return true;
292289}
290+
291+ void
292+ ts_stats_chunk_evict (Oid compressed_relid )
293+ {
294+ if (!OidIsValid (compressed_relid ))
295+ {
296+ return ;
297+ }
298+ TsStatsChunkSegment * seg = ts_get_stats_chunk_segment ();
299+ if (seg == NULL )
300+ {
301+ return ;
302+ }
303+
304+ int32 slot_idx = ts_stats_chunk_segment_lookup (seg , compressed_relid );
305+
306+ if (slot_idx == TS_STATS_INVALID_IDX )
307+ {
308+ return ;
309+ }
310+ Assert (slot_idx >= 0 && slot_idx < (int32 ) seg -> num_slots );
311+
312+ TsStatsChunkMetadata * meta_base = ts_stats_chunk_metadata (seg );
313+ TsStatsChunkMetadata * meta = & meta_base [slot_idx ];
314+
315+ /* limited CAS loop to ensure we don't evict a chunk that is currently being updated, the danger
316+ * is that the one that we are evicting is already being overwritten by a newer/other chunk.
317+ */
318+ uint64 state = pg_atomic_read_u64 (& meta -> state );
319+ uint64 new_seqno = pg_atomic_add_fetch_u64 (& seg -> update_seqno , 1 );
320+ uint64 new_state = (new_seqno << TS_STATS_CHUNK_METADATA_SEQNO_SHIFT );
321+ for (int i = 0 ;
322+ i < 5 &&
323+ /* the slot still matches the compressed_relid */
324+ meta -> relids .compressed_relid == compressed_relid &&
325+ /* the slot is still valid and not in progress */
326+ TS_STATS_CHUNK_METADATA_IS_VALID (state ) &&
327+ !(TS_STATS_CHUNK_METADATA_IS_IN_PROGRESS (state )) & &
328+ /* the slot being updated is older than the sequence number of the current update */
329+ TS_STATS_CHUNK_METADATA_GET_SEQNO (state ) < new_seqno ;
330+ ++ i )
331+ {
332+ if (pg_atomic_compare_exchange_u64 (& meta -> state , & state , new_state ))
333+ {
334+ meta -> relids .compressed_relid = InvalidOid ;
335+ break ;
336+ }
337+ }
338+ }
0 commit comments