55 #include "utils/hsearch.h" 56 #include "storage/pg_shmem.h" 57 #include "storage/shmem.h" 58 #include "storage/lwlock.h" 59 #include "storage/procarray.h" 60 #include "access/xact.h" 61 #include "access/transam.h" 62 #include "miscadmin.h" 101 #define OTHER_CONTEXT(x) (x ? 0: 1) 127 (errcode(ERRCODE_INTERNAL_ERROR),
128 errmsg(
"veil: out of LWLocks")));
181 (void) snprintf(db_hashname,
HASH_KEYLEN - 1,
"%s_%u",
182 hashname, MyDatabaseId);
184 hashctl.entrysize =
sizeof(
VarEntry);
186 result = ShmemInitHash(db_hashname, hash_elems,
187 hash_elems, &hashctl, HASH_ELEM);
201 static HTAB *hash0 = NULL;
218 static HTAB *hash1 = NULL;
246 char *uniqname = (
char *)
vl_malloc(strlen(name) + 16);
249 for (i = 0; i < max_dbs; i++) {
250 (void) sprintf(uniqname,
"%s_%d", name, i);
251 context = ShmemInitStruct(uniqname, size, p_found);;
254 (errcode(ERRCODE_INTERNAL_ERROR),
255 errmsg(
"veil: cannot allocate shared memory(1)")));
260 if (context->
db_id == MyDatabaseId) {
268 context->
db_id = MyDatabaseId;
270 context->
limit = size;
279 lwlock_context = context;
289 for (i = 0; i < max_dbs; i++) {
290 (void) sprintf(uniqname,
"%s_%d", name, i);
291 context = ShmemInitStruct(uniqname, size, p_found);;
295 (errcode(ERRCODE_INTERNAL_ERROR),
296 errmsg(
"veil: cannot allocate shared memory(2)")));
303 context->
db_id = MyDatabaseId;
305 context->
limit = size;
316 context->
db_id = MyDatabaseId;
318 context->
limit = size;
323 (errcode(ERRCODE_INTERNAL_ERROR),
324 errmsg(
"veil: no more shared memory contexts allowed")));
339 static bool initialised =
false;
354 if (TransactionIdPrecedes(GetCurrentTransactionId(),
355 shared_meminfo->
xid[context]))
374 return shared_meminfo->
context[context];
391 size_t amount = (size_t) MAXALIGN(size);
393 if ((amount + context->
next) <= context->
limit) {
394 result = (
void *) ((
char *) context + context->
next);
395 context->
next += amount;
400 (errcode(ERRCODE_INTERNAL_ERROR),
401 errmsg(
"veil: out of shared memory"))));
454 if (!shared_meminfo) {
467 if (found && context0->
memctl) {
468 shared_meminfo = context0->
memctl;
516 shared_meminfo->
type = OBJ_SHMEMCTL;
521 shared_meminfo->
context[0] = context0;
522 shared_meminfo->
context[1] = context1;
523 shared_meminfo->
xid[0] = GetCurrentTransactionId();
524 shared_meminfo->
xid[1] = shared_meminfo->
xid[0];
532 var = (
VarEntry *) hash_search(hash0, (
void *)
"VEIL_SHMEMCTL",
538 var = (
VarEntry *) hash_search(hash0, (
void *)
"VEIL_SHMEMCTL",
556 static bool initialised =
false;
584 static HASH_SEQ_STATUS status;
587 hash_seq_init(&status, hash);
588 while ((var = hash_seq_search(&status))) {
589 if (strncmp(
"VEIL_SHMEMCTL", var->
key, strlen(
"VEIL_SHMEMCTL")) != 0) {
590 (void) hash_search(hash, var->
key, HASH_REMOVE, NULL);
612 TransactionId oldest_xid;
636 oldest_xid = GetOldestXmin(
false,
true);
637 if (TransactionIdPrecedes(oldest_xid,
638 shared_meminfo->
xid[context_curidx]))
652 context = shared_meminfo->
context[context_newidx];
657 if (context_newidx == 0) {
685 (errcode(ERRCODE_INTERNAL_ERROR),
686 errmsg(
"failed to complete context switch"),
687 errdetail(
"Not prepared for switch - " 688 "invalid state for operation")));
700 (errcode(ERRCODE_INTERNAL_ERROR),
701 errmsg(
"failed to complete context switch"),
702 errdetail(
"Session does not have switching set to true- " 703 "invalid state for operation")));
708 shared_meminfo->
xid[context_newidx] = GetCurrentTransactionId();
736 context = shared_meminfo->
context[context_newidx];
741 if (context_newidx == 0) {
751 shared_meminfo->
xid[context_newidx] = GetCurrentTransactionId();
752 shared_meminfo->
xid[0] = GetCurrentTransactionId();
static HTAB * get_hash1()
Return reference to the HTAB for the shared hash associated with context 1.
size_t next
Offset of 1st free byte.
struct ShmemCtl ShmemCtl
The ShmemCtl structure is the first object allocated from the first chunk of shared memory in context...
LWLockPadded * lwlock_tranche
A tranche of lwlocks (only used in the zeroth MemContext.
bool vl_prepare_context_switch()
Prepare for a switch to the alternate context.
HTAB * vl_get_shared_hash()
Return the shared hash for the current context.
Oid db_id
Identifier for the database for which this context was created, or by which it has been taken over...
bool switching
Whether a context-switch is in progress.
bool initialised
Set to true once struct is setup.
struct MemContext MemContext
MemContexts are large single chunks of shared memory from which smaller allocations may be made...
int current_context
Index of the current context (0 or 1)
static LWLockId InitialLWLock
The LWLock to be used while initially setting up shared memory and allocating a veil database-specifi...
Define the basic veil shared memory structures.
int veil_dbs_in_cluster()
Return the number of databases, within the database cluster, that will use Veil.
MemContexts are large single chunks of shared memory from which smaller allocations may be made...
#define OTHER_CONTEXT(x)
Return the index of the other context from the one supplied.
#define HASH_KEYLEN
The key length for veil hash types.
static MemContext * lwlock_context
The MemContext that we use to manage our tranche of LWLocks.
static ShmemCtl * shared_meminfo
shared_meminfo provides access to the ShmemCtl structure allocated in context 0.
static MemContext * get_shmem_context(char *name, size_t size, bool *p_found)
Allocate or attach to, a new chunk of shared memory for a named memory context.
static void * do_vl_shmalloc(MemContext *context, size_t size)
Dynamically allocate a piece of shared memory from the current context, doing no locking.
int lwlock_idx
Index into the above.
Provide definitions for all non-local C-callable Veil functions.
bool shared
Whether this is a shared variable.
void vl_free(void *mem)
Free a piece of shared memory within the current context.
General purpose object-type.
Provides version information for veil.
bool vl_complete_context_switch()
Complete the context switch started by vl_prepare_context_switch().
struct ShmemCtl * memctl
Pointer to shared memory control structure.
static LWLockId VeilLWLock
The LWLock that Veil will use for managing concurrent access to shared memory.
TransactionId xid[2]
The transaction id of the transaction that initialised each context: this is used to determine whethe...
void veil_config_init()
Initialise Veil's use of GUC variables.
size_t limit
Offset, of 1st byte beyond this struct.
int veil_shmem_context_size()
Return the amount of shared memory to be requested for each of the two shared memory contexts...
static bool prepared_for_switch
Whether the current backend is in the process of switching contexts.
ObjType type
This must have the value OBJ_SHMEMCTL.
void * vl_malloc(size_t size)
Dynamically allocate memory using palloc in TopMemoryContext.
LWLockId veil_lwlock
dynamically allocated LWLock
static char * TRANCHE_NAME
Name of tranche of LWLocks used by veil.
static void clear_hash(HTAB *hash)
Reset one of the shared hashes.
bool vl_db_exists(Oid db_id)
Determine whether the given oid represents an existing database or not.
Object * obj
Pointer to the contents of the variable.
static MemContext * get_cur_context()
Return pointer to shared memory allocated for the current context.
The ShmemCtl structure is the first object allocated from the first chunk of shared memory in context...
MemChunk * context[2]
The first chunks of each context.
static HTAB * create_shared_hash(const char *hashname)
Create/attach to the shared hash identified by hashname.
static HTAB * get_hash0()
Return reference to the HTAB for the shared hash associated with context 0.
size_t total_allocated[2]
Total shared memory allocated in chunks in each context.
void _PG_init()
Veil's startup function.
struct VarEntry VarEntry
A Veil variable.
int veil_shared_hash_elems()
Return the number of entries that should be allocated for shared variables in our shared hashes...
void * vl_shmalloc(size_t size)
Dynamically allocate a piece of shared memory from the current context.
LWLock * lwlock
The LWLock associated with this memory context.
static int get_cur_context_id()
Return the id (index) of the current context for this session.
char key[60]
String containing variable name.
void vl_force_context_switch()
In desparation, if we are unable to complete a context switch, we should use this function...
static LWLock * NextLWLock()
Return the next LWLock from our tranche.
static void shmalloc_init(void)
Attach to, creating and initialising as necessary, the shared memory control structure.