Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move freeze/unfreeze chunk to tsl #4974

Merged
merged 1 commit into from Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
66 changes: 11 additions & 55 deletions src/chunk.c
Expand Up @@ -71,8 +71,6 @@ TS_FUNCTION_INFO_V1(ts_chunk_show_chunks);
TS_FUNCTION_INFO_V1(ts_chunk_drop_chunks);
TS_FUNCTION_INFO_V1(ts_chunk_drop_single_chunk);
TS_FUNCTION_INFO_V1(ts_chunk_attach_osm_table_chunk);
TS_FUNCTION_INFO_V1(ts_chunk_freeze_chunk);
TS_FUNCTION_INFO_V1(ts_chunk_unfreeze_chunk);
TS_FUNCTION_INFO_V1(ts_chunks_in);
TS_FUNCTION_INFO_V1(ts_chunk_id_from_relid);
TS_FUNCTION_INFO_V1(ts_chunk_show);
Expand Down Expand Up @@ -3549,6 +3547,17 @@ ts_chunk_unset_frozen(Chunk *chunk)
#endif
}

bool
ts_chunk_is_frozen(Chunk *chunk)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this exported function intended for later use? I could not find any calls at the moment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

called from the tsl code.

{
#if PG14_GE
return ts_flags_are_set_32(chunk->fd.status, CHUNK_STATUS_FROZEN);
#else
elog(ERROR, "freeze chunk supported only for PG14 or greater");
return false;
#endif
}

#if PG14_GE
/* only caller is ts_chunk_unset_frozen. This code is in PG14 block as we run into
* defined but unsed error in CI/CD builds for PG < 14.
Expand Down Expand Up @@ -4121,59 +4130,6 @@ find_hypertable_from_table_or_cagg(Cache *hcache, Oid relid, bool allow_matht)
return ht;
}

/* Data in a frozen chunk cannot be modified. So any operation
* that rewrites data for a frozen chunk will be blocked.
* Note that a frozen chunk can still be dropped.
*/
Datum
ts_chunk_freeze_chunk(PG_FUNCTION_ARGS)
{
Oid chunk_relid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
TS_PREVENT_FUNC_IF_READ_ONLY();
Chunk *chunk = ts_chunk_get_by_relid(chunk_relid, true);
Assert(chunk != NULL);
if (chunk->relkind == RELKIND_FOREIGN_TABLE)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("operation not supported on distributed chunk or foreign table \"%s\"",
get_rel_name(chunk_relid))));
}
if (ts_flags_are_set_32(chunk->fd.status, CHUNK_STATUS_FROZEN))
PG_RETURN_BOOL(true);
/* get Share lock. will wait for other concurrent transactions that are
* modifying the chunk. Does not block SELECTs on the chunk.
* Does not block other DDL on the chunk table.
*/
DEBUG_WAITPOINT("freeze_chunk_before_lock");
LockRelationOid(chunk_relid, ShareLock);
bool ret = ts_chunk_set_frozen(chunk);
PG_RETURN_BOOL(ret);
}

Datum
ts_chunk_unfreeze_chunk(PG_FUNCTION_ARGS)
{
Oid chunk_relid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
TS_PREVENT_FUNC_IF_READ_ONLY();
Chunk *chunk = ts_chunk_get_by_relid(chunk_relid, true);
Assert(chunk != NULL);
if (chunk->relkind == RELKIND_FOREIGN_TABLE)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("operation not supported on distributed chunk or foreign table \"%s\"",
get_rel_name(chunk_relid))));
}
if (!ts_flags_are_set_32(chunk->fd.status, CHUNK_STATUS_FROZEN))
PG_RETURN_BOOL(true);
/* This is a previously frozen chunk. Only selects are permitted on this chunk.
* This changes the status in the catalog to allow previously blocked operations.
*/
bool ret = ts_chunk_unset_frozen(chunk);
PG_RETURN_BOOL(ret);
}

Datum
ts_chunk_drop_single_chunk(PG_FUNCTION_ARGS)
{
Expand Down
1 change: 1 addition & 0 deletions src/chunk.h
Expand Up @@ -191,6 +191,7 @@ extern TSDLLEXPORT bool ts_chunk_set_partial(Chunk *chunk);
extern TSDLLEXPORT bool ts_chunk_set_unordered(Chunk *chunk);
extern TSDLLEXPORT bool ts_chunk_set_frozen(Chunk *chunk);
extern TSDLLEXPORT bool ts_chunk_unset_frozen(Chunk *chunk);
extern TSDLLEXPORT bool ts_chunk_is_frozen(Chunk *chunk);
extern TSDLLEXPORT bool ts_chunk_set_compressed_chunk(Chunk *chunk, int32 compressed_chunk_id);
extern TSDLLEXPORT bool ts_chunk_clear_compressed_chunk(Chunk *chunk);
extern TSDLLEXPORT void ts_chunk_drop(const Chunk *chunk, DropBehavior behavior, int32 log_level);
Expand Down
4 changes: 4 additions & 0 deletions src/cross_module_fn.c
Expand Up @@ -104,6 +104,8 @@ CROSSMODULE_WRAPPER(data_node_attach);
CROSSMODULE_WRAPPER(data_node_detach);
CROSSMODULE_WRAPPER(data_node_alter);
CROSSMODULE_WRAPPER(chunk_drop_replica);
CROSSMODULE_WRAPPER(chunk_freeze_chunk);
CROSSMODULE_WRAPPER(chunk_unfreeze_chunk);

CROSSMODULE_WRAPPER(chunk_set_default_data_node);
CROSSMODULE_WRAPPER(chunk_get_relstats);
Expand Down Expand Up @@ -516,6 +518,8 @@ TSDLLEXPORT CrossModuleFunctions ts_cm_functions_default = {
.create_chunk = error_no_default_fn_pg_community,
.create_chunk_on_data_nodes = create_chunk_on_data_nodes_default,
.chunk_drop_replica = error_no_default_fn_pg_community,
.chunk_freeze_chunk = error_no_default_fn_pg_community,
.chunk_unfreeze_chunk = error_no_default_fn_pg_community,
.hypertable_make_distributed = hypertable_make_distributed_default_fn,
.get_and_validate_data_node_list = get_and_validate_data_node_list_default_fn,
.timescaledb_fdw_handler = error_no_default_fn_pg_community,
Expand Down
2 changes: 2 additions & 0 deletions src/cross_module_fn.h
Expand Up @@ -198,6 +198,8 @@ typedef struct CrossModuleFunctions
PGFunction chunk_create_empty_table;
PGFunction chunk_create_replica_table;
PGFunction chunk_drop_replica;
PGFunction chunk_freeze_chunk;
PGFunction chunk_unfreeze_chunk;
void (*update_compressed_chunk_relstats)(Oid uncompressed_relid, Oid compressed_relid);
CompressSingleRowState *(*compress_row_init)(int srcht_id, Relation in_rel, Relation out_rel);
TupleTableSlot *(*compress_row_exec)(CompressSingleRowState *cr, TupleTableSlot *slot);
Expand Down
62 changes: 58 additions & 4 deletions tsl/src/chunk.c
Expand Up @@ -5,15 +5,16 @@
*/

#include <postgres.h>
#include <foreign/foreign.h>
#include <access/htup_details.h>
#include <access/xact.h>
#include <catalog/pg_foreign_server.h>
#include <catalog/pg_foreign_table.h>
#include <catalog/dependency.h>
#include <catalog/namespace.h>
#include <access/htup_details.h>
#include <access/xact.h>
#include <foreign/foreign.h>
#include <nodes/makefuncs.h>
#include <nodes/parsenodes.h>
#include <storage/lmgr.h>
#include <utils/acl.h>
#include <utils/builtins.h>
#include <utils/syscache.h>
Expand All @@ -27,7 +28,6 @@
#include <funcapi.h>
#include <miscadmin.h>
#include <fmgr.h>

#ifdef USE_ASSERT_CHECKING
#include <funcapi.h>
#endif
Expand All @@ -43,6 +43,7 @@
#include "chunk_api.h"
#include "data_node.h"
#include "deparse.h"
#include "debug_point.h"
#include "dist_util.h"
#include "remote/dist_commands.h"
#include "ts_catalog/chunk_data_node.h"
Expand Down Expand Up @@ -507,3 +508,56 @@ chunk_drop_replica(PG_FUNCTION_ARGS)

PG_RETURN_VOID();
}

/* Data in a frozen chunk cannot be modified. So any operation
* that rewrites data for a frozen chunk will be blocked.
* Note that a frozen chunk can still be dropped.
*/
Datum
chunk_freeze_chunk(PG_FUNCTION_ARGS)
{
Oid chunk_relid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
TS_PREVENT_FUNC_IF_READ_ONLY();
Chunk *chunk = ts_chunk_get_by_relid(chunk_relid, true);
Assert(chunk != NULL);
if (chunk->relkind == RELKIND_FOREIGN_TABLE)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("operation not supported on distributed chunk or foreign table \"%s\"",
get_rel_name(chunk_relid))));
}
if (ts_chunk_is_frozen(chunk))
PG_RETURN_BOOL(true);
/* get Share lock. will wait for other concurrent transactions that are
* modifying the chunk. Does not block SELECTs on the chunk.
* Does not block other DDL on the chunk table.
*/
DEBUG_WAITPOINT("freeze_chunk_before_lock");
LockRelationOid(chunk_relid, ShareLock);
bool ret = ts_chunk_set_frozen(chunk);
PG_RETURN_BOOL(ret);
}

Datum
chunk_unfreeze_chunk(PG_FUNCTION_ARGS)
{
Oid chunk_relid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
TS_PREVENT_FUNC_IF_READ_ONLY();
Chunk *chunk = ts_chunk_get_by_relid(chunk_relid, true);
Assert(chunk != NULL);
if (chunk->relkind == RELKIND_FOREIGN_TABLE)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("operation not supported on distributed chunk or foreign table \"%s\"",
get_rel_name(chunk_relid))));
}
if (!ts_chunk_is_frozen(chunk))
PG_RETURN_BOOL(true);
/* This is a previously frozen chunk. Only selects are permitted on this chunk.
* This changes the status in the catalog to allow previously blocked operations.
*/
bool ret = ts_chunk_unset_frozen(chunk);
PG_RETURN_BOOL(ret);
}
2 changes: 2 additions & 0 deletions tsl/src/chunk.h
Expand Up @@ -14,6 +14,8 @@ extern bool chunk_update_foreign_server_if_needed(const Chunk *chunk, Oid data_n
bool available);
extern Datum chunk_set_default_data_node(PG_FUNCTION_ARGS);
extern Datum chunk_drop_replica(PG_FUNCTION_ARGS);
extern Datum chunk_freeze_chunk(PG_FUNCTION_ARGS);
extern Datum chunk_unfreeze_chunk(PG_FUNCTION_ARGS);
extern int chunk_invoke_drop_chunks(Oid relid, Datum older_than, Datum older_than_type);
extern Datum chunk_create_replica_table(PG_FUNCTION_ARGS);

Expand Down
2 changes: 2 additions & 0 deletions tsl/src/init.c
Expand Up @@ -199,6 +199,8 @@ CrossModuleFunctions tsl_cm_functions = {
.create_chunk = chunk_create,
.create_chunk_on_data_nodes = chunk_api_create_on_data_nodes,
.chunk_drop_replica = chunk_drop_replica,
.chunk_freeze_chunk = chunk_freeze_chunk,
.chunk_unfreeze_chunk = chunk_unfreeze_chunk,
.hypertable_make_distributed = hypertable_make_distributed,
.get_and_validate_data_node_list = hypertable_get_and_validate_data_nodes,
.timescaledb_fdw_handler = timescaledb_fdw_handler,
Expand Down