timescaledb/src/hypercube.h
Erik Nordström 2cc2df23bd Lock dimension slices when creating new chunk
This change makes two changes to address issues with processes doing
concurrent inserts and `drop_chunks` calls:

- When a new chunk is created, any dimension slices that existed prior
  to creating the new chunk are locked to prevent them from being
  dropped before the chunk-creating process commits.

- When a chunk is being dropped, concurrent inserts into the chunk
  that is being dropped will try to lock the dimension slices of the
  chunk. In case the locking fails (due to the slices being
  concurrently deleted), the insert process will treat the chunk as
  not existing and will instead recreate it. Previously, the chunk
  slices (and thus chunk) would be found, but the insert would fail
  when committing since the chunk was concurrently deleted.

A prior commit (PR #2150) partially solved a related problem, but
didn't lock all the slices of a chunk. That commit also threw an error
when a lock on a slice could not be taken due to the slice being
deleted by another transaction. This is now changed to treat that case
as a missing slice instead, causing it to be recreated.

Fixes #1986
2020-10-15 21:56:10 +02:00

43 lines
1.7 KiB
C

/*
* This file and its contents are licensed under the Apache License 2.0.
* Please see the included NOTICE for copyright information and
* LICENSE-APACHE for a copy of the license.
*/
#ifndef TIMESCALEDB_HYPERCUBE_H
#define TIMESCALEDB_HYPERCUBE_H
#include <postgres.h>
#include "dimension_slice.h"
/*
* Hypercube is a collection of slices from N distinct dimensions, i.e., the
* N-dimensional analogue of a cube.
*/
typedef struct Hypercube
{
int16 capacity; /* capacity of slices[] */
int16 num_slices; /* actual number of slices (should equal
* capacity after create) */
/* Slices are stored in dimension order */
DimensionSlice *slices[FLEXIBLE_ARRAY_MEMBER];
} Hypercube;
#define HYPERCUBE_SIZE(num_dimensions) \
(sizeof(Hypercube) + sizeof(DimensionSlice *) * (num_dimensions))
extern TSDLLEXPORT Hypercube *ts_hypercube_alloc(int16 num_dimensions);
extern void ts_hypercube_free(Hypercube *hc);
extern TSDLLEXPORT void ts_hypercube_add_slice(Hypercube *hc, DimensionSlice *slice);
extern Hypercube *ts_hypercube_from_constraints(ChunkConstraints *constraints, MemoryContext mctx);
extern int ts_hypercube_find_existing_slices(Hypercube *cube, ScanTupLock *tuplock);
extern Hypercube *ts_hypercube_calculate_from_point(Hyperspace *hs, Point *p, ScanTupLock *tuplock);
extern bool ts_hypercubes_collide(Hypercube *cube1, Hypercube *cube2);
extern TSDLLEXPORT DimensionSlice *ts_hypercube_get_slice_by_dimension_id(Hypercube *hc,
int32 dimension_id);
extern Hypercube *ts_hypercube_copy(Hypercube *hc);
extern bool ts_hypercube_equal(Hypercube *hc1, Hypercube *hc2);
extern void ts_hypercube_slice_sort(Hypercube *hc);
#endif /* TIMESCALEDB_HYPERCUBE_H */