diff --git a/src/diskquota.c b/src/diskquota.c index 00faba4b..c715015c 100644 --- a/src/diskquota.c +++ b/src/diskquota.c @@ -91,7 +91,18 @@ static DiskQuotaWorkerEntry *volatile MyWorkerInfo = NULL; // how many database diskquota are monitoring on static int num_db = 0; -DiskquotaLauncherShmemStruct *DiskquotaLauncherShmem = NULL; +static DiskquotaLauncherShmemStruct *DiskquotaLauncherShmem; + +/* how many TableSizeEntry are maintained in all the table_size_map in shared memory */ +pg_atomic_uint32 *diskquota_table_size_entry_num; + +/* how many QuotaInfoEntry are maintained in all the quota_info_map in shared memory */ +pg_atomic_uint32 *diskquota_quota_info_entry_num; + +#ifdef USE_ASSERT_CHECKING +extern pg_atomic_flag *diskquota_table_size_flag; +extern pg_atomic_flag *diskquota_quota_info_flag; +#endif #define MIN_SLEEPTIME 100 /* milliseconds */ #define BGWORKER_LOG_TIME 3600000 /* milliseconds */ @@ -1772,6 +1783,25 @@ init_launcher_shmem() DiskquotaLauncherShmem->dbArray[i].workerId = INVALID_WORKER_ID; } } + /* init TableSizeEntry counter */ + diskquota_table_size_entry_num = + DiskquotaShmemInitStruct("diskquota TableSizeEntry counter", DISKQUOTA_TABLE_SIZE_ENTRY_NUM_SIZE, &found); + if (!found) pg_atomic_init_u32(diskquota_table_size_entry_num, 0); + + /* init QuotaInfoEntry counter */ + diskquota_quota_info_entry_num = + DiskquotaShmemInitStruct("diskquota QuotaInfoEntry counter", DISKQUOTA_QUOTA_INFO_ENTRY_NUM_SIZE, &found); + if (!found) pg_atomic_init_u32(diskquota_quota_info_entry_num, 0); + +#ifdef USE_ASSERT_CHECKING + diskquota_table_size_flag = + DiskquotaShmemInitStruct("diskquota TableSizeEntry flag", DISKQUOTA_TABLE_SIZE_FLAG_SIZE, &found); + if (!found) pg_atomic_init_flag(diskquota_table_size_flag); + + diskquota_quota_info_flag = + DiskquotaShmemInitStruct("diskquota QuotaInfoEntry flag", DISKQUOTA_QUOTA_INFO_FLAG_SIZE, &found); + if (!found) pg_atomic_init_flag(diskquota_quota_info_flag); +#endif } /* diff --git a/src/diskquota.h b/src/diskquota.h index a726d8cf..19262376 100644 --- a/src/diskquota.h +++ b/src/diskquota.h @@ -42,9 +42,10 @@ #define MAX_NUM_KEYS_QUOTA_MAP 8 /* init number of QuotaInfoEntry in quota_info_map */ #define INIT_QUOTA_MAP_ENTRIES 128 -#define AVG_QUOTA_MAP_ENTRIES (diskquota_max_quota_probes / diskquota_max_monitored_databases) /* max number of QuotaInfoEntry in quota_info_map */ -#define MAX_QUOTA_MAP_ENTRIES (AVG_QUOTA_MAP_ENTRIES < 1024 ? 1024 : AVG_QUOTA_MAP_ENTRIES) +#define MAX_QUOTA_MAP_ENTRIES \ + (diskquota_max_quota_probes < 1024 * diskquota_max_monitored_databases ? 1024 * diskquota_max_monitored_databases \ + : diskquota_max_quota_probes) typedef enum { @@ -81,6 +82,14 @@ extern int diskquota_worker_timeout; #define RELID_CACHE_ENTRY_SIZE sizeof(DiskQuotaRelidCacheEntry) #define ALTERED_RELOID_CACHE_ENTRY_SIZE sizeof(Oid) #define MONITORED_DBID_CACHE_ENTRY_SIZE sizeof(struct MonitorDBEntryStruct) +#define DISKQUOTA_TABLE_SIZE_ENTRY_NUM_SIZE sizeof(pg_atomic_uint32) +#define DISKQUOTA_QUOTA_INFO_ENTRY_NUM_SIZE sizeof(pg_atomic_uint32) + +#ifdef USE_ASSERT_CHECKING +#define DISKQUOTA_TABLE_SIZE_FLAG_SIZE sizeof(pg_atomic_flag) +#define LOCAL_DISK_QUOTA_REJECT_FLAG_SIZE sizeof(pg_atomic_flag) +#define DISKQUOTA_QUOTA_INFO_FLAG_SIZE sizeof(pg_atomic_flag) +#endif typedef enum { @@ -322,9 +331,11 @@ extern void update_monitordb_status(Oid dbid, uint32 status); extern HTAB *diskquota_hash_create(const char *tabname, long nelem, HASHCTL *info, int flags, DiskquotaHashFunction hashFunction); extern HTAB *DiskquotaShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags, - DiskquotaHashFunction hash_function); + DiskquotaHashFunction hash_function, pg_atomic_flag *foundPtr); extern void *DiskquotaShmemInitStruct(const char *name, Size size, bool *foundPtr); extern void refresh_monitored_dbid_cache(void); +extern HASHACTION check_hash_fullness_num(HTAB *hashp, int num_entries, int max_size, const char *warning_message, + TimestampTz *last_overflow_report); extern HASHACTION check_hash_fullness(HTAB *hashp, int max_size, const char *warning_message, TimestampTz *last_overflow_report); bool SPI_push_cond_and_connect(void); diff --git a/src/diskquota_utility.c b/src/diskquota_utility.c index 514bbfa0..3a00a185 100644 --- a/src/diskquota_utility.c +++ b/src/diskquota_utility.c @@ -115,8 +115,7 @@ static bool to_delete_quota(QuotaType type, int64 quota_limit_mb, float4 segra static void check_role(Oid roleoid, char *rolname, int64 quota_limit_mb); #ifdef USE_ASSERT_CHECKING -extern DiskquotaLauncherShmemStruct *DiskquotaLauncherShmem; -extern void diskquota_shmem_size_sub(Size size); +extern void diskquota_shmem_size_sub(Size size); #endif /* ---- Help Functions to set quota limit. ---- */ @@ -1645,12 +1644,9 @@ DiskquotaShmemInitHash(const char *name, /* table string name fo long max_size, /* max size of the table */ HASHCTL *infoP, /* info about key and bucket size */ int hash_flags, /* info about infoP */ - DiskquotaHashFunction hashFunction) + DiskquotaHashFunction hashFunction, pg_atomic_flag *foundPtr) { -#ifdef USE_ASSERT_CHECKING - if (!DiskquotaLauncherShmem || !DiskquotaLauncherShmem->isDynamicWorker) - diskquota_shmem_size_sub(hash_estimate_size(max_size, infoP->entrysize)); -#endif + HTAB *hashp; #if GP_VERSION_NUM < 70000 if (hashFunction == DISKQUOTA_TAG_HASH) @@ -1659,31 +1655,37 @@ DiskquotaShmemInitHash(const char *name, /* table string name fo infoP->hash = oid_hash; else infoP->hash = string_hash; - return ShmemInitHash(name, init_size, max_size, infoP, hash_flags | HASH_FUNCTION); + hashp = ShmemInitHash(name, init_size, max_size, infoP, hash_flags | HASH_FUNCTION); #else - return ShmemInitHash(name, init_size, max_size, infoP, hash_flags | HASH_BLOBS); + hashp = ShmemInitHash(name, init_size, max_size, infoP, hash_flags | HASH_BLOBS); #endif /* GP_VERSION_NUM */ + +#ifdef USE_ASSERT_CHECKING + AssertImply(IsBackgroundWorker, foundPtr != NULL); /* foundPtr only used in background worker */ + + if (foundPtr == NULL || pg_atomic_test_set_flag(foundPtr)) + diskquota_shmem_size_sub(hash_estimate_size(max_size, infoP->entrysize)); +#endif + + return hashp; } void * DiskquotaShmemInitStruct(const char *name, Size size, bool *foundPtr) { + void *structPtr = ShmemInitStruct(name, size, foundPtr); + #ifdef USE_ASSERT_CHECKING - if (!DiskquotaLauncherShmem || !DiskquotaLauncherShmem->isDynamicWorker) diskquota_shmem_size_sub(size); + if (!*foundPtr) diskquota_shmem_size_sub(size); #endif - return ShmemInitStruct(name, size, foundPtr); + return structPtr; } -/* - * Returns HASH_FIND if hash table is full and HASH_ENTER otherwise. - * It can be used only under lock. - */ HASHACTION -check_hash_fullness(HTAB *hashp, int max_size, const char *warning_message, TimestampTz *last_overflow_report) +check_hash_fullness_num(HTAB *hashp, int num_entries, int max_size, const char *warning_message, + TimestampTz *last_overflow_report) { - long num_entries = hash_get_num_entries(hashp); - if (num_entries < max_size) return HASH_ENTER; if (num_entries == max_size) @@ -1701,6 +1703,16 @@ check_hash_fullness(HTAB *hashp, int max_size, const char *warning_message, Time return HASH_FIND; } +/* + * Returns HASH_FIND if hash table is full and HASH_ENTER otherwise. + * It can be used only under lock. + */ +HASHACTION +check_hash_fullness(HTAB *hashp, int max_size, const char *warning_message, TimestampTz *last_overflow_report) +{ + return check_hash_fullness_num(hashp, hash_get_num_entries(hashp), max_size, warning_message, last_overflow_report); +} + bool SPI_push_cond_and_connect(void) { diff --git a/src/gp_activetable.c b/src/gp_activetable.c index dba31b30..f57f093f 100644 --- a/src/gp_activetable.c +++ b/src/gp_activetable.c @@ -112,13 +112,14 @@ init_shm_worker_active_tables(void) ctl.keysize = ACTIVE_TABLES_MAP_ENTRY_SIZE; ctl.entrysize = ACTIVE_TABLES_MAP_ENTRY_SIZE; active_tables_map = DiskquotaShmemInitHash("active_tables", diskquota_max_active_tables, - diskquota_max_active_tables, &ctl, HASH_ELEM, DISKQUOTA_TAG_HASH); + diskquota_max_active_tables, &ctl, HASH_ELEM, DISKQUOTA_TAG_HASH, NULL); memset(&ctl, 0, sizeof(ctl)); - ctl.keysize = ALTERED_RELOID_CACHE_ENTRY_SIZE; - ctl.entrysize = ALTERED_RELOID_CACHE_ENTRY_SIZE; - altered_reloid_cache = DiskquotaShmemInitHash("altered_reloid_cache", diskquota_max_active_tables, - diskquota_max_active_tables, &ctl, HASH_ELEM, DISKQUOTA_OID_HASH); + ctl.keysize = ALTERED_RELOID_CACHE_ENTRY_SIZE; + ctl.entrysize = ALTERED_RELOID_CACHE_ENTRY_SIZE; + altered_reloid_cache = + DiskquotaShmemInitHash("altered_reloid_cache", diskquota_max_active_tables, diskquota_max_active_tables, + &ctl, HASH_ELEM, DISKQUOTA_OID_HASH, NULL); } /* diff --git a/src/quotamodel.c b/src/quotamodel.c index 740e99c1..5989bde8 100644 --- a/src/quotamodel.c +++ b/src/quotamodel.c @@ -92,6 +92,20 @@ extern int diskquota_max_table_segments; extern int diskquota_max_monitored_databases; extern int diskquota_max_quota_probes; extern int diskquota_max_local_reject_entries; + +extern pg_atomic_uint32 *diskquota_table_size_entry_num; +extern pg_atomic_uint32 *diskquota_quota_info_entry_num; + +#ifdef USE_ASSERT_CHECKING +pg_atomic_flag *diskquota_table_size_flag; +pg_atomic_flag *local_disk_quota_reject_flag; +pg_atomic_flag *diskquota_quota_info_flag; +#else +#define diskquota_table_size_flag NULL +#define local_disk_quota_reject_flag NULL +#define diskquota_quota_info_flag NULL +#endif + /* * local cache of table disk size and corresponding schema and owner. * @@ -279,15 +293,17 @@ update_size_for_quota(int64 size, QuotaType type, Oid *keys, int16 segid) memcpy(key.keys, keys, quota_key_num[type] * sizeof(Oid)); key.type = type; key.segid = segid; - action = check_hash_fullness(quota_info_map, diskquota_max_quota_probes, quota_info_map_warning, - quota_info_map_last_overflow_report); - entry = hash_search(quota_info_map, &key, action, &found); + action = + check_hash_fullness_num(quota_info_map, pg_atomic_read_u32(diskquota_quota_info_entry_num), + MAX_QUOTA_MAP_ENTRIES, quota_info_map_warning, quota_info_map_last_overflow_report); + entry = hash_search(quota_info_map, &key, action, &found); /* If the number of quota exceeds the limit, entry will be NULL */ if (entry == NULL) return; if (!found) { entry->size = 0; entry->limit = -1; + pg_atomic_fetch_add_u32(diskquota_quota_info_entry_num, 1); } entry->size += size; } @@ -306,14 +322,16 @@ update_limit_for_quota(int64 limit, float segratio, QuotaType type, Oid *keys) memcpy(key.keys, keys, quota_key_num[type] * sizeof(Oid)); key.type = type; key.segid = i; - action = check_hash_fullness(quota_info_map, diskquota_max_quota_probes, quota_info_map_warning, - quota_info_map_last_overflow_report); + action = check_hash_fullness_num(quota_info_map, pg_atomic_read_u32(diskquota_quota_info_entry_num), + MAX_QUOTA_MAP_ENTRIES, quota_info_map_warning, + quota_info_map_last_overflow_report); entry = hash_search(quota_info_map, &key, action, &found); /* If the number of quota exceeds the limit, entry will be NULL */ if (entry == NULL) continue; if (!found) { entry->size = 0; + pg_atomic_fetch_add_u32(diskquota_quota_info_entry_num, 1); } if (key.segid == -1) entry->limit = limit; @@ -371,6 +389,7 @@ refresh_quota_info_map(void) if (!HeapTupleIsValid(tuple)) { hash_search(quota_info_map, &entry->key, HASH_REMOVE, NULL); + pg_atomic_fetch_sub_u32(diskquota_quota_info_entry_num, 1); removed = true; break; } @@ -482,7 +501,7 @@ disk_quota_shmem_startup(void) hash_ctl.entrysize = DISK_QUOTA_REJECT_MAP_ENTRY_SIZE; disk_quota_reject_map = DiskquotaShmemInitHash("rejectmap whose quota limitation is reached", diskquota_max_local_reject_entries, - MAX_DISK_QUOTA_REJECT_ENTRIES, &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH); + MAX_DISK_QUOTA_REJECT_ENTRIES, &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH, NULL); init_shm_worker_active_tables(); @@ -494,14 +513,23 @@ disk_quota_shmem_startup(void) monitored_dbid_cache = DiskquotaShmemInitHash("table oid cache which shoud tracking", diskquota_max_monitored_databases, - diskquota_max_monitored_databases, &hash_ctl, HASH_ELEM, DISKQUOTA_OID_HASH); + diskquota_max_monitored_databases, &hash_ctl, HASH_ELEM, DISKQUOTA_OID_HASH, NULL); if (IS_QUERY_DISPATCHER()) init_launcher_shmem(); LWLockRelease(AddinShmemInitLock); #ifdef USE_ASSERT_CHECKING if (IS_QUERY_DISPATCHER()) - Assert(pg_atomic_read_u64(diskquota_shmem_size) == - diskquota_worker_shmem_size() * diskquota_max_monitored_databases); + { + int table_size_map_size = + MAX_NUM_TABLE_SIZE_ENTRIES - INIT_NUM_TABLE_SIZE_ENTRIES * diskquota_max_monitored_databases; + int quota_info_map_size = MAX_QUOTA_MAP_ENTRIES - INIT_QUOTA_MAP_ENTRIES * diskquota_max_monitored_databases; + int rest_size = diskquota_worker_shmem_size() * diskquota_max_monitored_databases; + + if (table_size_map_size > 0) rest_size += hash_estimate_size(table_size_map_size, TABLE_SIZE_MAP_ENTRY_SIZE); + if (quota_info_map_size > 0) rest_size += hash_estimate_size(quota_info_map_size, QUOTA_INFO_MAP_ENTRY_SIZE); + + Assert(pg_atomic_read_u64(diskquota_shmem_size) == rest_size); + } else Assert(pg_atomic_read_u64(diskquota_shmem_size) == 0); #endif @@ -547,14 +575,28 @@ init_lwlocks(void) static Size diskquota_worker_shmem_size(void) { - Size size; - size = hash_estimate_size(MAX_NUM_TABLE_SIZE_ENTRIES, TABLE_SIZE_MAP_ENTRY_SIZE); + Size size = 0; + +#ifdef USE_ASSERT_CHECKING + /* request size for local_disk_quota_reject_flag in each coordinator worker */ + size = add_size(size, LOCAL_DISK_QUOTA_REJECT_FLAG_SIZE); +#endif + + /* request initial size for table_size_map in each coordinator worker */ + size = add_size(size, hash_estimate_size(INIT_NUM_TABLE_SIZE_ENTRIES, TABLE_SIZE_MAP_ENTRY_SIZE)); + /* request maximum size for local_disk_quota_reject_map in each coordinator worker */ size = add_size(size, hash_estimate_size(diskquota_max_local_reject_entries, LOCAL_DISK_QUOTA_REJECT_MAP_ENTRY_SIZE)); - size = add_size(size, hash_estimate_size(MAX_QUOTA_MAP_ENTRIES, QUOTA_INFO_MAP_ENTRY_SIZE)); + /* request initial size for quota_info_map in each coordinator worker */ + size = add_size(size, hash_estimate_size(INIT_QUOTA_MAP_ENTRIES, QUOTA_INFO_MAP_ENTRY_SIZE)); + + /* request size for table_size_map_last_overflow_report in each coordinator worker */ size = add_size(size, TABLE_SIZE_MAP_LAST_OVERFLOW_REPORT_SIZE); + /* request size for local_disk_quota_reject_map_last_overflow_report in each coordinator worker */ size = add_size(size, LOCAL_DISK_QUOTA_REJECT_MAP_LAST_OVERFLOW_REPORT_SIZE); + /* request size for quota_info_map_last_overflow_report in each coordinator worker */ size = add_size(size, QUOTA_INFO_MAP_LAST_OVERFLOW_REPORT_SIZE); + return size; } @@ -565,23 +607,54 @@ diskquota_worker_shmem_size(void) static Size DiskQuotaShmemSize(void) { - Size size; - size = EXTENSION_DDL_MESSAGE_SIZE; + Size size = 0; #ifdef USE_ASSERT_CHECKING - size = add_size(size, sizeof(pg_atomic_uint64)); // diskquota_shmem_size + /* request size for diskquota_shmem_size in entire coordinator or segment */ + size = add_size(size, sizeof(pg_atomic_uint64)); #endif + /* request size for extension_ddl_message in entire coordinator or segment */ + size = add_size(size, EXTENSION_DDL_MESSAGE_SIZE); + /* request maximum size for disk_quota_reject_map in entire coordinator or segment */ size = add_size(size, hash_estimate_size(MAX_DISK_QUOTA_REJECT_ENTRIES, DISK_QUOTA_REJECT_MAP_ENTRY_SIZE)); + /* request maximum size for active_tables_map in entire coordinator or segment */ size = add_size(size, hash_estimate_size(diskquota_max_active_tables, ACTIVE_TABLES_MAP_ENTRY_SIZE)); + /* request maximum size for relation_cache in entire coordinator or segment */ size = add_size(size, hash_estimate_size(diskquota_max_active_tables, RELATION_CACHE_ENTRY_SIZE)); + /* request maximum size for relid_cache in entire coordinator or segment */ size = add_size(size, hash_estimate_size(diskquota_max_active_tables, RELID_CACHE_ENTRY_SIZE)); + /* request maximum size for altered_reloid_cache in entire coordinator or segment */ size = add_size(size, hash_estimate_size(diskquota_max_active_tables, ALTERED_RELOID_CACHE_ENTRY_SIZE)); + /* request maximum size for monitored_dbid_cache in entire coordinator or segment */ size = add_size(size, hash_estimate_size(diskquota_max_monitored_databases, MONITORED_DBID_CACHE_ENTRY_SIZE)); if (IS_QUERY_DISPATCHER()) { - size = add_size(size, diskquota_launcher_shmem_size()); // DiskquotaLauncherShmem +#ifdef USE_ASSERT_CHECKING + /* request size for diskquota_table_size_flag in entire coordinator */ + size = add_size(size, DISKQUOTA_TABLE_SIZE_FLAG_SIZE); + /* request size for diskquota_quota_info_flag in entire coordinator */ + size = add_size(size, DISKQUOTA_QUOTA_INFO_FLAG_SIZE); +#endif + + /* request size for DiskquotaLauncherShmem in entire coordinator */ + size = add_size(size, diskquota_launcher_shmem_size()); + /* request size for diskquota_table_size_entry_num in entire coordinator */ + size = add_size(size, DISKQUOTA_TABLE_SIZE_ENTRY_NUM_SIZE); + /* request size for diskquota_quota_info_entry_num in entire coordinator */ + size = add_size(size, DISKQUOTA_QUOTA_INFO_ENTRY_NUM_SIZE); + + int table_size_map_size = + MAX_NUM_TABLE_SIZE_ENTRIES - INIT_NUM_TABLE_SIZE_ENTRIES * diskquota_max_monitored_databases; + int quota_info_map_size = MAX_QUOTA_MAP_ENTRIES - INIT_QUOTA_MAP_ENTRIES * diskquota_max_monitored_databases; + + if (table_size_map_size > 0) /* request maximum size for table_size_map in entire coordinator */ + size = add_size(size, hash_estimate_size(table_size_map_size, TABLE_SIZE_MAP_ENTRY_SIZE)); + if (quota_info_map_size > 0) /* request maximum size for quota_info_map in entire coordinator */ + size = add_size(size, hash_estimate_size(quota_info_map_size, QUOTA_INFO_MAP_ENTRY_SIZE)); + + /* request sizes in each coordinator worker */ size = add_size(size, diskquota_worker_shmem_size() * diskquota_max_monitored_databases); } @@ -605,12 +678,18 @@ init_disk_quota_model(uint32 id) hash_ctl.keysize = sizeof(TableSizeEntryKey); hash_ctl.entrysize = TABLE_SIZE_MAP_ENTRY_SIZE; table_size_map = DiskquotaShmemInitHash(str.data, INIT_NUM_TABLE_SIZE_ENTRIES, MAX_NUM_TABLE_SIZE_ENTRIES, - &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH); + &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH, diskquota_table_size_flag); format_name("TableSizeEntrymap_last_overflow_report", id, &str); table_size_map_last_overflow_report = DiskquotaShmemInitStruct(str.data, TABLE_SIZE_MAP_LAST_OVERFLOW_REPORT_SIZE, &found); if (!found) *table_size_map_last_overflow_report = 0; +#ifdef USE_ASSERT_CHECKING + format_name("diskquota LocalRejectMapEntry flag", id, &str); + local_disk_quota_reject_flag = DiskquotaShmemInitStruct(str.data, LOCAL_DISK_QUOTA_REJECT_FLAG_SIZE, &found); + if (!found) pg_atomic_init_flag(local_disk_quota_reject_flag); +#endif + /* for localrejectmap */ /* WARNNING: The max length of name of the map is 48 */ format_name("localrejectmap", id, &str); @@ -619,7 +698,7 @@ init_disk_quota_model(uint32 id) hash_ctl.entrysize = LOCAL_DISK_QUOTA_REJECT_MAP_ENTRY_SIZE; local_disk_quota_reject_map = DiskquotaShmemInitHash(str.data, diskquota_max_local_reject_entries, diskquota_max_local_reject_entries, - &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH); + &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH, local_disk_quota_reject_flag); format_name("localrejectmap_last_overflow_report", id, &str); local_disk_quota_reject_map_last_overflow_report = @@ -632,7 +711,7 @@ init_disk_quota_model(uint32 id) hash_ctl.entrysize = QUOTA_INFO_MAP_ENTRY_SIZE; hash_ctl.keysize = sizeof(QuotaInfoEntryKey); quota_info_map = DiskquotaShmemInitHash(str.data, INIT_QUOTA_MAP_ENTRIES, MAX_QUOTA_MAP_ENTRIES, &hash_ctl, - HASH_ELEM, DISKQUOTA_TAG_HASH); + HASH_ELEM, DISKQUOTA_TAG_HASH, diskquota_quota_info_flag); format_name("QuotaInfoMap_last_overflow_report", id, &str); quota_info_map_last_overflow_report = DiskquotaShmemInitStruct(str.data, QUOTA_INFO_MAP_LAST_OVERFLOW_REPORT_SIZE, &found); @@ -672,11 +751,12 @@ vacuum_disk_quota_model(uint32 id) hash_ctl.keysize = sizeof(TableSizeEntryKey); hash_ctl.entrysize = TABLE_SIZE_MAP_ENTRY_SIZE; table_size_map = DiskquotaShmemInitHash(str.data, INIT_NUM_TABLE_SIZE_ENTRIES, MAX_NUM_TABLE_SIZE_ENTRIES, - &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH); + &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH, diskquota_table_size_flag); hash_seq_init(&iter, table_size_map); while ((tsentry = hash_seq_search(&iter)) != NULL) { hash_search(table_size_map, &tsentry->key, HASH_REMOVE, NULL); + pg_atomic_fetch_sub_u32(diskquota_table_size_entry_num, 1); } format_name("TableSizeEntrymap_last_overflow_report", id, &str); @@ -684,6 +764,12 @@ vacuum_disk_quota_model(uint32 id) DiskquotaShmemInitStruct(str.data, TABLE_SIZE_MAP_LAST_OVERFLOW_REPORT_SIZE, &found); if (!found) *table_size_map_last_overflow_report = 0; +#ifdef USE_ASSERT_CHECKING + format_name("diskquota LocalRejectMapEntry flag", id, &str); + local_disk_quota_reject_flag = DiskquotaShmemInitStruct(str.data, LOCAL_DISK_QUOTA_REJECT_FLAG_SIZE, &found); + if (!found) pg_atomic_init_flag(local_disk_quota_reject_flag); +#endif + /* localrejectmap */ format_name("localrejectmap", id, &str); memset(&hash_ctl, 0, sizeof(hash_ctl)); @@ -691,7 +777,7 @@ vacuum_disk_quota_model(uint32 id) hash_ctl.entrysize = LOCAL_DISK_QUOTA_REJECT_MAP_ENTRY_SIZE; local_disk_quota_reject_map = DiskquotaShmemInitHash(str.data, diskquota_max_local_reject_entries, diskquota_max_local_reject_entries, - &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH); + &hash_ctl, HASH_ELEM, DISKQUOTA_TAG_HASH, local_disk_quota_reject_flag); hash_seq_init(&iter, local_disk_quota_reject_map); while ((localrejectentry = hash_seq_search(&iter)) != NULL) { @@ -708,11 +794,12 @@ vacuum_disk_quota_model(uint32 id) hash_ctl.entrysize = QUOTA_INFO_MAP_ENTRY_SIZE; hash_ctl.keysize = sizeof(QuotaInfoEntryKey); quota_info_map = DiskquotaShmemInitHash(str.data, INIT_QUOTA_MAP_ENTRIES, MAX_QUOTA_MAP_ENTRIES, &hash_ctl, - HASH_ELEM, DISKQUOTA_TAG_HASH); + HASH_ELEM, DISKQUOTA_TAG_HASH, diskquota_quota_info_flag); hash_seq_init(&iter, quota_info_map); while ((qentry = hash_seq_search(&iter)) != NULL) { hash_search(quota_info_map, &qentry->key, HASH_REMOVE, NULL); + pg_atomic_fetch_sub_u32(diskquota_quota_info_entry_num, 1); } format_name("QuotaInfoMap_last_overflow_report", id, &str); quota_info_map_last_overflow_report = @@ -946,10 +1033,11 @@ static TableSizeEntry * get_table_size_map_entry(Oid oid, int16 segid) { bool found; - TableSizeEntryKey key = {.reloid = oid, .id = TableSizeEntryId(segid)}; - HASHACTION action = check_hash_fullness(table_size_map, MAX_NUM_TABLE_SIZE_ENTRIES, table_size_map_warning, - table_size_map_last_overflow_report); - TableSizeEntry *tsentry = hash_search(table_size_map, &key, action, &found); + TableSizeEntryKey key = {.reloid = oid, .id = TableSizeEntryId(segid)}; + HASHACTION action = check_hash_fullness_num(table_size_map, pg_atomic_read_u32(diskquota_table_size_entry_num), + MAX_NUM_TABLE_SIZE_ENTRIES, table_size_map_warning, + table_size_map_last_overflow_report); + TableSizeEntry *tsentry = hash_search(table_size_map, &key, action, &found); if (!found && tsentry != NULL) { @@ -962,6 +1050,7 @@ get_table_size_map_entry(Oid oid, int16 segid) int seg_st = TableSizeEntrySegidStart(tsentry); int seg_ed = TableSizeEntrySegidEnd(tsentry); for (int j = seg_st; j < seg_ed; j++) TableSizeEntrySetFlushFlag(tsentry, j); + pg_atomic_fetch_add_u32(diskquota_table_size_entry_num, 1); } return tsentry; @@ -1286,6 +1375,7 @@ flush_to_table_size(void) if (!get_table_size_entry_flag(tsentry, TABLE_EXIST)) { hash_search(table_size_map, &tsentry->key, HASH_REMOVE, NULL); + pg_atomic_fetch_sub_u32(diskquota_table_size_entry_num, 1); } } diff --git a/src/relation_cache.c b/src/relation_cache.c index f8af8429..f9e32dc7 100644 --- a/src/relation_cache.c +++ b/src/relation_cache.c @@ -56,13 +56,13 @@ init_shm_worker_relation_cache(void) ctl.keysize = sizeof(Oid); ctl.entrysize = RELATION_CACHE_ENTRY_SIZE; relation_cache = DiskquotaShmemInitHash("relation_cache", diskquota_max_active_tables, diskquota_max_active_tables, - &ctl, HASH_ELEM, DISKQUOTA_OID_HASH); + &ctl, HASH_ELEM, DISKQUOTA_OID_HASH, NULL); memset(&ctl, 0, sizeof(ctl)); ctl.keysize = sizeof(Oid); ctl.entrysize = RELID_CACHE_ENTRY_SIZE; relid_cache = DiskquotaShmemInitHash("relid_cache", diskquota_max_active_tables, diskquota_max_active_tables, &ctl, - HASH_ELEM, DISKQUOTA_OID_HASH); + HASH_ELEM, DISKQUOTA_OID_HASH, NULL); } Oid