Merged in enordstr/backend-database/enordstr/no-storage-for-negative-cache-entries (pull request #119)

Avoid allocating hypertable cache storage for negative entries.

Approved-by: Olof Rensfelt
Approved-by: ci-vast
This commit is contained in:
enordstr NA 2017-03-14 12:37:29 +00:00
commit 5f4b158c83
2 changed files with 39 additions and 46 deletions

View File

@ -17,18 +17,18 @@
#include "scanner.h" #include "scanner.h"
#include "partitioning.h" #include "partitioning.h"
static void *hypertable_cache_create_entry(Cache *cache, CacheQueryCtx *ctx); static void *hypertable_cache_create_entry(Cache * cache, CacheQueryCtx * ctx);
typedef struct HypertableCacheQueryCtx typedef struct HypertableCacheQueryCtx
{ {
CacheQueryCtx cctx; CacheQueryCtx cctx;
Oid main_table_relid; Oid main_table_relid;
char *schema; const char *schema;
char *table_name; const char *table;
} HypertableCacheQueryCtx; } HypertableCacheQueryCtx;
static void * static void *
hypertable_cache_get_key(CacheQueryCtx *ctx) hypertable_cache_get_key(CacheQueryCtx * ctx)
{ {
return &((HypertableCacheQueryCtx *) ctx)->main_table_relid; return &((HypertableCacheQueryCtx *) ctx)->main_table_relid;
} }
@ -36,9 +36,8 @@ hypertable_cache_get_key(CacheQueryCtx *ctx)
typedef struct typedef struct
{ {
Oid main_table_relid; Oid main_table_relid;
bool negative; /* true if no such hypertable exists */ Hypertable *hypertable;
Hypertable entry; } HypertableNameCacheEntry;
} HypertableNameCacheEntry;
static Cache * static Cache *
@ -77,15 +76,18 @@ static Cache *hypertable_cache_current = NULL;
/* Column numbers for 'hypertable' table in sql/common/tables.sql */ /* Column numbers for 'hypertable' table in sql/common/tables.sql */
static bool static bool
hypertable_tuple_found(TupleInfo *ti, void *data) hypertable_tuple_found(TupleInfo * ti, void *data)
{ {
Hypertable *he = data; HypertableNameCacheEntry *entry = data;
Hypertable *he;
Datum values[Natts_hypertable]; Datum values[Natts_hypertable];
bool isnull[Natts_hypertable]; bool isnull[Natts_hypertable];
char *root_table_name; char *root_table_name;
char *root_table_schema; char *root_table_schema;
int32 id; int32 id;
he = palloc(sizeof(Hypertable));
heap_deform_tuple(ti->tuple, ti->desc, values, isnull); heap_deform_tuple(ti->tuple, ti->desc, values, isnull);
id = DatumGetInt32(DATUM_GET(values, Anum_hypertable_id)); id = DatumGetInt32(DATUM_GET(values, Anum_hypertable_id));
@ -109,58 +111,58 @@ hypertable_tuple_found(TupleInfo *ti, void *data)
he->chunk_size_bytes = DatumGetInt64(DATUM_GET(values, Anum_hypertable_chunk_size_bytes)); he->chunk_size_bytes = DatumGetInt64(DATUM_GET(values, Anum_hypertable_chunk_size_bytes));
he->num_replicas = DatumGetInt16(DATUM_GET(values, Anum_hypertable_replication_factor)); he->num_replicas = DatumGetInt16(DATUM_GET(values, Anum_hypertable_replication_factor));
entry->hypertable = he;
return false; return false;
} }
static void * static void *
hypertable_cache_create_entry(Cache *cache, CacheQueryCtx *ctx) hypertable_cache_create_entry(Cache * cache, CacheQueryCtx * ctx)
{ {
HypertableCacheQueryCtx *hctx = (HypertableCacheQueryCtx *) ctx; HypertableCacheQueryCtx *hctx = (HypertableCacheQueryCtx *) ctx;
Catalog *catalog = catalog_get(); Catalog *catalog = catalog_get();
HypertableNameCacheEntry *cache_entry = hctx->cctx.entry; HypertableNameCacheEntry *cache_entry = ctx->entry;
Hypertable *he = &cache_entry->entry;
int number_found; int number_found;
char *schema = hctx->schema;
char *table_name = hctx->table_name;
ScanKeyData scankey[2]; ScanKeyData scankey[2];
ScannerCtx scanCtx = { ScannerCtx scanCtx = {
.table = catalog->tables[HYPERTABLE].id, .table = catalog->tables[HYPERTABLE].id,
.index = catalog->tables[HYPERTABLE].index_ids[HYPERTABLE_NAME_INDEX], .index = catalog->tables[HYPERTABLE].index_ids[HYPERTABLE_NAME_INDEX],
.scantype = ScannerTypeIndex, .scantype = ScannerTypeIndex,
.nkeys = 2, .nkeys = 2,
.scankey = scankey, .scankey = scankey,
.data = he, .data = ctx->entry,
.tuple_found = hypertable_tuple_found, .tuple_found = hypertable_tuple_found,
.lockmode = AccessShareLock, .lockmode = AccessShareLock,
.scandirection = ForwardScanDirection, .scandirection = ForwardScanDirection,
}; };
if (NULL == schema) if (NULL == hctx->schema)
{ {
schema = get_namespace_name(get_rel_namespace(hctx->main_table_relid)); hctx->schema = get_namespace_name(get_rel_namespace(hctx->main_table_relid));
} }
if (NULL == table_name)
if (NULL == hctx->table)
{ {
table_name = get_rel_name(hctx->main_table_relid); hctx->table = get_rel_name(hctx->main_table_relid);
} }
/* Perform an index scan on schema and table. */ /* Perform an index scan on schema and table. */
ScanKeyInit(&scankey[0], Anum_hypertable_name_idx_schema, ScanKeyInit(&scankey[0], Anum_hypertable_name_idx_schema,
BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(schema)); BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(hctx->schema));
ScanKeyInit(&scankey[1], Anum_hypertable_name_idx_table, ScanKeyInit(&scankey[1], Anum_hypertable_name_idx_table,
BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(table_name)); BTEqualStrategyNumber, F_NAMEEQ, NameGetDatum(hctx->table));
number_found = scanner_scan(&scanCtx); number_found = scanner_scan(&scanCtx);
switch (number_found) switch (number_found)
{ {
case 0: case 0:
cache_entry->negative = true; /* Negative cache entry: table is not a hypertable */
cache_entry->hypertable = NULL;
break; break;
case 1: case 1:
cache_entry->negative = false; Assert(strncmp(cache_entry->hypertable->schema, hctx->schema, NAMEDATALEN) == 0);
Assert(strncmp(he->schema, get_namespace_name(get_rel_namespace(hctx->main_table_relid)), NAMEDATALEN) == 0); Assert(strncmp(cache_entry->hypertable->table, hctx->table, NAMEDATALEN) == 0);
Assert(strncmp(he->table, get_rel_name(hctx->main_table_relid), NAMEDATALEN) == 0);
break; break;
default: default:
elog(ERROR, "Got an unexpected number of records: %d", number_found); elog(ERROR, "Got an unexpected number of records: %d", number_found);
@ -180,30 +182,22 @@ hypertable_cache_invalidate_callback(void)
/* Get hypertable cache entry. If the entry is not in the cache, add it. */ /* Get hypertable cache entry. If the entry is not in the cache, add it. */
Hypertable * Hypertable *
hypertable_cache_get_entry(Cache *cache, Oid main_table_relid) hypertable_cache_get_entry(Cache * cache, Oid main_table_relid)
{ {
return hypertable_cache_get_entry_with_table(cache, main_table_relid, NULL, NULL); return hypertable_cache_get_entry_with_table(cache, main_table_relid, NULL, NULL);
} }
Hypertable * Hypertable *
hypertable_cache_get_entry_with_table(Cache *cache, Oid main_table_relid, char *schema, char *table_name) hypertable_cache_get_entry_with_table(Cache * cache, Oid main_table_relid, const char *schema, const char *table)
{ {
HypertableCacheQueryCtx ctx = { HypertableCacheQueryCtx ctx = {
.main_table_relid = main_table_relid, .main_table_relid = main_table_relid,
.schema = schema, .schema = schema,
.table_name = table_name, .table = table,
}; };
HypertableNameCacheEntry *entry = cache_fetch(cache, &ctx.cctx); HypertableNameCacheEntry *entry = cache_fetch(cache, &ctx.cctx);
if (entry->negative) return entry->hypertable;
{
return NULL;
}
else
{
return &entry->entry;
}
} }
/* function to compare epochs */ /* function to compare epochs */
@ -227,7 +221,7 @@ cmp_epochs(const void *time_pt_pointer, const void *test)
} }
PartitionEpoch * PartitionEpoch *
hypertable_cache_get_partition_epoch(Cache *cache, Hypertable * hce, int64 time_pt, Oid relid) hypertable_cache_get_partition_epoch(Cache * cache, Hypertable * hce, int64 time_pt, Oid relid)
{ {
MemoryContext old; MemoryContext old;
PartitionEpoch *epoch, PartitionEpoch *epoch,

View File

@ -30,16 +30,15 @@ typedef struct Hypertable
extern Hypertable *hypertable_cache_get_entry(Cache * cache, Oid main_table_relid); extern Hypertable *hypertable_cache_get_entry(Cache * cache, Oid main_table_relid);
extern Hypertable * extern Hypertable *hypertable_cache_get_entry_with_table(Cache * cache, Oid main_table_relid, const char *schema, const char *table);
hypertable_cache_get_entry_with_table(Cache *cache, Oid main_table_relid, char *schema, char *table_name);
PartitionEpoch *hypertable_cache_get_partition_epoch(Cache * cache, Hypertable * hce, int64 time_pt, Oid relid); extern PartitionEpoch *hypertable_cache_get_partition_epoch(Cache * cache, Hypertable * hce, int64 time_pt, Oid relid);
void hypertable_cache_invalidate_callback(void); extern void hypertable_cache_invalidate_callback(void);
extern Cache *hypertable_cache_pin(void); extern Cache *hypertable_cache_pin(void);
void _hypertable_cache_init(void); extern void _hypertable_cache_init(void);
void _hypertable_cache_fini(void); extern void _hypertable_cache_fini(void);
#endif /* TIMESCALEDB_HYPERTABLE_CACHE_H */ #endif /* TIMESCALEDB_HYPERTABLE_CACHE_H */