Veil
veil_shmem.c
Go to the documentation of this file.
1 /**
2  * @file veil_shmem.c
3  * \code
4  * Author: Marc Munro
5  * Copyright (c) 2005 - 2018 Marc Munro
6  * License: BSD
7  *
8  * \endcode
9  * @brief
10  * Functions for dealing with veil shared memory.
11  *
12  * This provides dynamic memory allocation, like malloc, from chunks of
13  * shared memory allocated from the Postgres shared memory pool. In
14  * order to be able to reset and reload shared memory structures while
15  * other backends continue to use the existing structures, a shared
16  * memory reset creates a new context, or switches to an existing one
17  * that is no longer in use. No more than two separate contexts will be
18  * created.
19  *
20  * Each context of veil shared memory is associated with a shared hash,
21  * which is used to store veil's shared variables. A specially named
22  * variable, VEIL_SHMEMCTL appears only in context0 and contains a
23  * reference to chunk0, and the ShmemCtl structure. From this structure
24  * we can identify the current context, the initial chunks for each
25  * active context, and whether a context switch is in progress.
26  *
27  * A context switch takes place in 3 steps:
28  * - preparation, in which we determine if a context switch is allowed,
29  * initialise the new context and record the fact that we are in the
30  * process of switching. All subsequent operations in the current
31  * backend will work in the new context, while other backends will
32  * continue to use the original context
33  * - initialisation of the new context, variables, etc. This is done
34  * by the user-space function veil_init().
35  * - switchover, when all other processes gain access to the newly
36  * initialised context. They may continue to use the previous
37  * context for the duration of their current transactions.
38  *
39  * To access shared variable "x" in a new session, the following steps
40  * are taken:
41  * - We access the hash "VEIL_SHARED1_nnn" (where nnn is the oid of our
42  * database). This gives us a reference to the ShmemCtl structure.
43  * We record hash0 and shared_meminfo on the way.
44  * - We access ShemCtl to identify the current hash and current
45  * context.
46  * - We look up variable "x" in the current hash, and if we have to
47  * allocate space for it, allocate it from the current context.
48  *
49  * Note that We use a dynamically allocated LWLock, VeilLWLock to protect
50  * our shared control structures.
51  *
52  */
53 
54 #include "postgres.h"
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"
63 #include "veil_version.h"
64 #include "veil_shmem.h"
65 #include "veil_funcs.h"
66 
67 /**
68  * shared_meminfo provides access to the ShmemCtl structure allocated in
69  * context 0.
70  */
71 static ShmemCtl *shared_meminfo = NULL;
72 
73 /**
74  * Whether the current backend is in the process of switching contexts.
75  * If so, it will be setting up the non-current context in readiness for
76  * making it available to all other backends.
77  */
78 static bool prepared_for_switch = false;
79 
80 /**
81  * The LWLock that Veil will use for managing concurrent access to
82  * shared memory. It is initialised in _PG_init() to a lock id that is
83  * distinct from any that will be dynamically allocated.
84  */
85 static LWLockId VeilLWLock = 0;
86 
87 /**
88  * The LWLock to be used while initially setting up shared memory and
89  * allocating a veil database-specific LWLock. Initialised in
90  * _PG_Init()
91  */
92 static LWLockId InitialLWLock = 0;
93 
94 /**
95  * Return the index of the other context from the one supplied.
96  *
97  * @param x the context for which we want the other one.
98  *
99  * @return the opposite context to that of x.
100  */
101 #define OTHER_CONTEXT(x) (x ? 0: 1)
102 
103 /**
104  * The MemContext that we use to manage our tranche of LWLocks
105  */
107 
108 /**
109  * Name of tranche of LWLocks used by veil.
110  */
111 static char *TRANCHE_NAME = "veil";
112 
113 /**
114  * Return the next LWLock from our tranche.
115  * Note that locking is the responsibility of the caller.
116  */
117 static LWLock *
119 {
120  // TODO: Ensure we don't exceed the number of locks in our tranche
121  if (lwlock_context->lwlock_idx > 0) {
122  lwlock_context->lwlock_idx--;
123  }
124  else {
125  // Error
126  ereport(ERROR,
127  (errcode(ERRCODE_INTERNAL_ERROR),
128  errmsg("veil: out of LWLocks")));
129  }
130  return
131  &(lwlock_context->lwlock_tranche[lwlock_context->lwlock_idx].lock);
132 }
133 
134 
135 /**
136  * Veil's startup function. This should be run when the Veil shared
137  * library is loaded by postgres.
138  *
139  */
140 void
142 {
143  int veil_dbs;
144 
145  /* See definitions of the following two variables, for comments. */
146  VeilLWLock = AddinShmemInitLock;
147  InitialLWLock = AddinShmemInitLock;
148 
149  /* Define GUCs for veil */
150  veil_config_init();
151  veil_dbs = veil_dbs_in_cluster();
152 
153  /* Request a Veil-specific shared memory context */
154  RequestAddinShmemSpace(2 * veil_shmem_context_size() * veil_dbs);
155 
156  /* Request LWLocks for later use by all backends */
157  RequestNamedLWLockTranche(TRANCHE_NAME, veil_dbs);
158 }
159 
160 /**
161  * Create/attach to the shared hash identified by hashname. Return a
162  * pointer to an HTAB that references the shared hash. All locking is
163  * handled by the caller.
164  *
165  * @param hashname
166  *
167  * @return Pointer to HTAB referencing the shared hash.
168  */
169 static HTAB *
170 create_shared_hash(const char *hashname)
171 {
172  HASHCTL hashctl;
173  HTAB *result;
174  char *db_hashname;
175  int hash_elems = veil_shared_hash_elems();
176 
177  /* Add the current database oid into the hashname so that it is
178  * distinct from the shared hash for other databases in the
179  * cluster. */
180  db_hashname = (char *) vl_malloc(HASH_KEYLEN);
181  (void) snprintf(db_hashname, HASH_KEYLEN - 1, "%s_%u",
182  hashname, MyDatabaseId);
183  hashctl.keysize = HASH_KEYLEN;
184  hashctl.entrysize = sizeof(VarEntry);
185 
186  result = ShmemInitHash(db_hashname, hash_elems,
187  hash_elems, &hashctl, HASH_ELEM);
188  pfree(db_hashname);
189  return result;
190 }
191 
192 /**
193  * Return reference to the HTAB for the shared hash associated with
194  * context 0.
195  *
196  * @return Pointer to HTAB referencing shared hash for context 0.
197  */
198 static HTAB *
200 {
201  static HTAB *hash0 = NULL;
202 
203  if (!hash0) {
204  hash0 = create_shared_hash("VEIL_SHARED1");
205  }
206  return hash0;
207 }
208 
209 /**
210  * Return reference to the HTAB for the shared hash associated with
211  * context 1.
212  *
213  * @return Pointer to HTAB referencing shared hash for context 1.
214  */
215 static HTAB *
217 {
218  static HTAB *hash1 = NULL;
219 
220  if (!hash1) {
221  hash1 = create_shared_hash("VEIL_SHARED2");
222  }
223 
224  return hash1;
225 }
226 
227 
228 /**
229  * Allocate or attach to, a new chunk of shared memory for a named
230  * memory context.
231  *
232  * @param name The name
233  * @param size The size of the shared memory chunk to be allocated.
234  * @param p_found Pointer to boolean that will identify whether this
235  * chunk has already been initialised.
236  *
237  * @return Pointer to chunk of shared memory.
238  */
239 static MemContext *
240 get_shmem_context(char *name,
241  size_t size,
242  bool *p_found)
243 {
244  int i;
245  MemContext *context;
246  char *uniqname = (char *) vl_malloc(strlen(name) + 16);
247  int max_dbs = veil_dbs_in_cluster();
248 
249  for (i = 0; i < max_dbs; i++) {
250  (void) sprintf(uniqname, "%s_%d", name, i);
251  context = ShmemInitStruct(uniqname, size, p_found);;
252  if (!context) {
253  ereport(ERROR,
254  (errcode(ERRCODE_INTERNAL_ERROR),
255  errmsg("veil: cannot allocate shared memory(1)")));
256  }
257 
258  if (*p_found) {
259  /* Already exists. Check database id. */
260  if (context->db_id == MyDatabaseId) {
261  /* This context is the one for the current database,
262  * nothing else to do. */
263  return context;
264  }
265  }
266  else {
267  /* We Just allocated our first context */
268  context->db_id = MyDatabaseId;
269  context->next = sizeof(MemContext);
270  context->limit = size;
271  context->lwlock = VeilLWLock;
272 
273  if (i == 0) {
274  /* This context is the very first MemContext for the
275  * cluster: this is the one used to manage our LWLocks
276  * tranche. */
277  context->lwlock_tranche = GetNamedLWLockTranche(TRANCHE_NAME);
278  context->lwlock_idx = max_dbs;
279  lwlock_context = context;
280  }
281  return context;
282  }
283  }
284 
285  /* We reach this point if no existing contexts are allocated to our
286  * database. Now we check those existing contexts to see whether
287  * they are still in use. If not, we will redeploy them. */
288 
289  for (i = 0; i < max_dbs; i++) {
290  (void) sprintf(uniqname, "%s_%d", name, i);
291  context = ShmemInitStruct(uniqname, size, p_found);;
292 
293  if (!context) {
294  ereport(ERROR,
295  (errcode(ERRCODE_INTERNAL_ERROR),
296  errmsg("veil: cannot allocate shared memory(2)")));
297  }
298 
299  if (*p_found) {
300  /* Is this context for a still existant database? */
301  if (!vl_db_exists(context->db_id)) {
302  /* We can re-use this context. */
303  context->db_id = MyDatabaseId;
304  context->next = sizeof(MemContext);
305  context->limit = size;
306 
307  *p_found = false; /* Tell the caller that init is
308  * required */
309  return context;
310  }
311  }
312  else {
313  /* We didn't find an unused context, so now we have created
314  * a new one. */
315 
316  context->db_id = MyDatabaseId;
317  context->next = sizeof(MemContext);
318  context->limit = size;
319  return context;
320  }
321  }
322  ereport(ERROR,
323  (errcode(ERRCODE_INTERNAL_ERROR),
324  errmsg("veil: no more shared memory contexts allowed")));
325  return NULL;
326 }
327 
328 /* Forward ref, required by next function. */
329 static void shmalloc_init(void);
330 
331 /**
332  * Return the id (index) of the current context for this session
333  *
334  * @return The current context id
335  */
336 static int
338 {
339  static bool initialised = false;
340  int context;
341 
342  if (!initialised) {
343  shmalloc_init();
344  initialised = true;
345  }
346 
347  context = shared_meminfo->current_context;
348  if (prepared_for_switch) {
349  context = OTHER_CONTEXT(context);
350  }
351  else {
352  /* Check for the default context being for a later transaction
353  * than current and, if so, use the other one. */
354  if (TransactionIdPrecedes(GetCurrentTransactionId(),
355  shared_meminfo->xid[context]))
356  {
357  context = OTHER_CONTEXT(context);
358  }
359  }
360 
361  return context;
362 }
363 
364 /**
365  * Return pointer to shared memory allocated for the current context.
366  *
367  * @return The current context.
368  */
369 static MemContext *
371 {
372  int context;
373  context = get_cur_context_id();
374  return shared_meminfo->context[context];
375 }
376 
377 /**
378  * Dynamically allocate a piece of shared memory from the current
379  * context, doing no locking.
380  *
381  * @param context The context in which we are operating
382  * @param size The size of the requested piece of memory.
383  *
384  * @return Pointer to dynamically allocated memory.
385  */
386 static void *
388  size_t size)
389 {
390  void *result = NULL;
391  size_t amount = (size_t) MAXALIGN(size);
392 
393  if ((amount + context->next) <= context->limit) {
394  result = (void *) ((char *) context + context->next);
395  context->next += amount;
396  }
397  else {
398  ereport(ERROR,
399  (ERROR,
400  (errcode(ERRCODE_INTERNAL_ERROR),
401  errmsg("veil: out of shared memory"))));
402  }
403  return result;
404 }
405 
406 /**
407  * Dynamically allocate a piece of shared memory from the current context.
408  *
409  * @param size The size of the requested piece of memory.
410  *
411  * @return Pointer to dynamically allocated memory.
412  */
413 void *
414 vl_shmalloc(size_t size)
415 {
416  MemContext *context;
417  void *result;
418 
419  context = get_cur_context();
420 
421  LWLockAcquire(VeilLWLock, LW_EXCLUSIVE);
422  result = do_vl_shmalloc(context, size);
423  LWLockRelease(VeilLWLock);
424 
425  return result;
426 }
427 
428 /**
429  * Free a piece of shared memory within the current context. Currently
430  * this does nothing as implementation of freeing of shared memory has
431  * been deferred.
432  *
433  * @param mem Pointer to the memory to be freed.
434  *
435  */
436 void
437 vl_free(void *mem)
438 {
439  return;
440 }
441 
442 
443 
444 /**
445  * Attach to, creating and initialising as necessary, the shared memory
446  * control structure. Record this for the session in shared_meminfo.
447  */
448 static void
450 {
451  VeilLWLock = AddinShmemInitLock;
452  InitialLWLock = AddinShmemInitLock;
453 
454  if (!shared_meminfo) {
455  VarEntry *var;
456  MemContext *context0;
457  MemContext *context1;
458  bool found = false;
459  HTAB *hash0;
460  size_t size;
461 
462  size = veil_shmem_context_size();
463 
464  LWLockAcquire(InitialLWLock, LW_EXCLUSIVE);
465  context0 = get_shmem_context("VEIL_SHMEM0", size, &found);
466 
467  if (found && context0->memctl) {
468  shared_meminfo = context0->memctl;
469  VeilLWLock = shared_meminfo->veil_lwlock;
470  /* By aquiring and releasing this lock, we ensure that Veil
471  * shared memory has been fully initialised, by a process
472  * following the else clause of this code path. */
473  LWLockAcquire(VeilLWLock, LW_EXCLUSIVE);
474  LWLockRelease(InitialLWLock);
475  LWLockRelease(VeilLWLock);
476  }
477  else {
478  /* Do minimum amount of initialisation while holding
479  * the initial lock. We don't want to do anything that
480  * may cause other locks to be aquired as this could lead
481  * to deadlock with other add-ins. Instead, we aquire the
482  * Veil-specific lock before finishing the initialisation. */
483 
484  shared_meminfo = do_vl_shmalloc(context0, sizeof(ShmemCtl));
485 
486  if (context0->lwlock != InitialLWLock) {
487  /* Re-use the LWLock previously allocated to this memory
488  * context */
489  VeilLWLock = context0->lwlock;
490  }
491  else {
492  /* Allocate new LWLock for this new shared memory
493  * context */
494  VeilLWLock = NextLWLock();
495  }
496  /* Record the lock id in context0 (for possible re-use if
497  * the current database is dropped and a new veil-using
498  * database created), and in the shared_meminfo struct */
499  context0->lwlock = VeilLWLock;
500  shared_meminfo->veil_lwlock = VeilLWLock;
501 
502  /* Exchange the initial lock for our Veil-specific one. */
503  LWLockAcquire(VeilLWLock, LW_EXCLUSIVE);
504  LWLockRelease(InitialLWLock);
505 
506  /* Now do the rest of the Veil shared memory initialisation */
507 
508  /* Set up the other memory context */
509  context1 = get_shmem_context("VEIL_SHMEM1", size, &found);
510 
511  /* Record location of shmemctl structure in each context */
512  context0->memctl = shared_meminfo;
513  context1->memctl = shared_meminfo;
514 
515  /* Finish initialising the shmemctl structure */
516  shared_meminfo->type = OBJ_SHMEMCTL;
517  shared_meminfo->current_context = 0;
518  shared_meminfo->total_allocated[0] = size;
519  shared_meminfo->total_allocated[1] = size;
520  shared_meminfo->switching = false;
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];
525  shared_meminfo->initialised = true;
526 
527  /* Set up both shared hashes */
528  hash0 = get_hash0();
529  (void) get_hash1();
530 
531  /* Record the shmemctl structure in hash0 */
532  var = (VarEntry *) hash_search(hash0, (void *) "VEIL_SHMEMCTL",
533  HASH_ENTER, &found);
534 
535  var->obj = (Object *) shared_meminfo;
536  var->shared = true;
537 
538  var = (VarEntry *) hash_search(hash0, (void *) "VEIL_SHMEMCTL",
539  HASH_ENTER, &found);
540 
541  LWLockRelease(VeilLWLock);
542  }
543  }
544 }
545 
546 /**
547  * Return the shared hash for the current context.
548  *
549  * @return Pointer to the HTAB for the current context's shared hash.
550  */
551 HTAB *
553 {
554  int context;
555  HTAB *hash;
556  static bool initialised = false;
557 
558  if (!initialised) {
559  (void) get_cur_context(); /* Ensure shared memory is set up. */
560  initialised = true;
561  }
562 
563  context = get_cur_context_id();
564 
565  if (context == 0) {
566  hash = get_hash0();
567  }
568  else {
569  hash = get_hash1();
570  }
571 
572  return hash;
573 }
574 
575 /**
576  * Reset one of the shared hashes. This is one of the final steps in a
577  * context switch.
578  *
579  * @return hash The shared hash that is to be reset.
580  */
581 static void
582 clear_hash(HTAB *hash)
583 {
584  static HASH_SEQ_STATUS status;
585  VarEntry *var;
586 
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);
591  }
592  }
593 }
594 
595 /**
596  * Prepare for a switch to the alternate context. Switching will
597  * only be allowed if there are no transactions that may still be using
598  * the context to which we are switching, and there is no other
599  * process attempting the switch.
600  *
601  * @return true if the switch preparation was successful.
602  */
603 bool
605 {
606  int context_curidx;
607  int context_newidx;
608  HTAB *hash0 = get_hash0(); /* We must not attempt to create hashes
609  * on the fly below as they also acquire
610  * the lock */
611  HTAB *hash1 = get_hash1();
612  TransactionId oldest_xid;
613  MemContext *context;
614 
615  (void) get_cur_context(); /* Ensure shared memory is set up */
616 
617  LWLockAcquire(VeilLWLock, LW_EXCLUSIVE);
618 
619  if (shared_meminfo->switching) {
620  /* Another process is performing the switch */
621  LWLockRelease(VeilLWLock);
622  return false;
623  }
624 
625  shared_meminfo->switching = true;
626 
627  /* We have claimed the switch. If we decide that we cannot proceed,
628  * we will return it to its previous state. */
629 
630  context_curidx = shared_meminfo->current_context;
631  context_newidx = OTHER_CONTEXT(context_curidx);
632 
633  /* In case the alternate context has been used before, we must
634  * clear it. */
635 
636  oldest_xid = GetOldestXmin(false, true);
637  if (TransactionIdPrecedes(oldest_xid,
638  shared_meminfo->xid[context_curidx]))
639  {
640  /* There is a transaction running that precedes the time of
641  * the last context switch. That transaction may still be
642  * using the chunk to which we wish to switch. We cannot
643  * allow the switch. */
644  shared_meminfo->switching = false;
645  LWLockRelease(VeilLWLock);
646  return false;
647  }
648  else {
649  /* It looks like we can safely make the switch. Reset the
650  * new context, and make it the current context for this
651  * session only. */
652  context = shared_meminfo->context[context_newidx];
653  context->next = sizeof(MemContext);
654 
655  /* If we are switching to context 0, reset the next field of
656  * the first chunk to leave space for the ShmemCtl struct. */
657  if (context_newidx == 0) {
658  context->next += sizeof(ShmemCtl);
659  clear_hash(hash0);
660  }
661  else {
662  clear_hash(hash1);
663  }
664  }
665 
666  LWLockRelease(VeilLWLock);
667  prepared_for_switch = true;
668  return true;
669 }
670 
671 /**
672  * Complete the context switch started by vl_prepare_context_switch().
673  * Raise an ERROR if the context switch cannot be completed.
674  *
675  * @return true if the context switch is successfully completed.
676  */
677 bool
679 {
680  int context_curidx;
681  int context_newidx;
682 
683  if (!prepared_for_switch) {
684  ereport(ERROR,
685  (errcode(ERRCODE_INTERNAL_ERROR),
686  errmsg("failed to complete context switch"),
687  errdetail("Not prepared for switch - "
688  "invalid state for operation")));
689  }
690 
691  LWLockAcquire(VeilLWLock, LW_EXCLUSIVE);
692  context_curidx = shared_meminfo->current_context;
693  context_newidx = OTHER_CONTEXT(context_curidx);
694 
695  if (!shared_meminfo->switching) {
696  /* We do not claim to be switching. We should. */
697  LWLockRelease(VeilLWLock);
698 
699  ereport(ERROR,
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")));
704  }
705 
706  shared_meminfo->switching = false;
707  shared_meminfo->current_context = context_newidx;
708  shared_meminfo->xid[context_newidx] = GetCurrentTransactionId();
709  LWLockRelease(VeilLWLock);
710  prepared_for_switch = false;
711  return true;
712 }
713 
714 /**
715  * In desparation, if we are unable to complete a context switch, we
716  * should use this function.
717  */
718 void
720 {
721  int context_curidx;
722  int context_newidx;
723  MemContext *context;
724  HTAB *hash0 = get_hash0();
725  HTAB *hash1 = get_hash1();
726 
727  (void) get_cur_context();
728 
729  LWLockAcquire(VeilLWLock, LW_EXCLUSIVE);
730 
731  context_curidx = shared_meminfo->current_context;
732  context_newidx = OTHER_CONTEXT(context_curidx);
733 
734  /* Clear the alternate context. */
735 
736  context = shared_meminfo->context[context_newidx];
737  context->next = sizeof(MemContext);
738 
739  /* If we are switching to context 0, reset the next field of
740  * the first chunk to leave space for the ShmemCtl struct. */
741  if (context_newidx == 0) {
742  context->next += sizeof(ShmemCtl);
743  clear_hash(hash0);
744  }
745  else {
746  clear_hash(hash1);
747  }
748 
749  shared_meminfo->switching = false;
750  shared_meminfo->current_context = context_newidx;
751  shared_meminfo->xid[context_newidx] = GetCurrentTransactionId();
752  shared_meminfo->xid[0] = GetCurrentTransactionId();
753  LWLockRelease(VeilLWLock);
754  prepared_for_switch = false;
755 }
756 
static HTAB * get_hash1()
Return reference to the HTAB for the shared hash associated with context 1.
Definition: veil_shmem.c:216
size_t next
Offset of 1st free byte.
Definition: veil_shmem.h:61
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.
Definition: veil_shmem.h:64
bool vl_prepare_context_switch()
Prepare for a switch to the alternate context.
Definition: veil_shmem.c:604
HTAB * vl_get_shared_hash()
Return the shared hash for the current context.
Definition: veil_shmem.c:552
Oid db_id
Identifier for the database for which this context was created, or by which it has been taken over...
Definition: veil_shmem.h:55
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...
Definition: veil_shmem.c:92
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.
Definition: veil_config.c:52
MemContexts are large single chunks of shared memory from which smaller allocations may be made...
Definition: veil_shmem.h:54
#define OTHER_CONTEXT(x)
Return the index of the other context from the one supplied.
Definition: veil_shmem.c:101
#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.
Definition: veil_shmem.c:106
static ShmemCtl * shared_meminfo
shared_meminfo provides access to the ShmemCtl structure allocated in context 0.
Definition: veil_shmem.c:71
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.
Definition: veil_shmem.c:240
static void * do_vl_shmalloc(MemContext *context, size_t size)
Dynamically allocate a piece of shared memory from the current context, doing no locking.
Definition: veil_shmem.c:387
int lwlock_idx
Index into the above.
Definition: veil_shmem.h:66
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.
Definition: veil_shmem.c:437
General purpose object-type.
Provides version information for veil.
bool vl_complete_context_switch()
Complete the context switch started by vl_prepare_context_switch().
Definition: veil_shmem.c:678
struct ShmemCtl * memctl
Pointer to shared memory control structure.
Definition: veil_shmem.h:67
static LWLockId VeilLWLock
The LWLock that Veil will use for managing concurrent access to shared memory.
Definition: veil_shmem.c:85
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&#39;s use of GUC variables.
Definition: veil_config.c:92
A Veil variable.
size_t limit
Offset, of 1st byte beyond this struct.
Definition: veil_shmem.h:62
int veil_shmem_context_size()
Return the amount of shared memory to be requested for each of the two shared memory contexts...
Definition: veil_config.c:82
static bool prepared_for_switch
Whether the current backend is in the process of switching contexts.
Definition: veil_shmem.c:78
ObjType type
This must have the value OBJ_SHMEMCTL.
void * vl_malloc(size_t size)
Dynamically allocate memory using palloc in TopMemoryContext.
Definition: veil_utils.c:28
LWLockId veil_lwlock
dynamically allocated LWLock
static char * TRANCHE_NAME
Name of tranche of LWLocks used by veil.
Definition: veil_shmem.c:111
static void clear_hash(HTAB *hash)
Reset one of the shared hashes.
Definition: veil_shmem.c:582
bool vl_db_exists(Oid db_id)
Determine whether the given oid represents an existing database or not.
Definition: veil_query.c:275
Object * obj
Pointer to the contents of the variable.
static MemContext * get_cur_context()
Return pointer to shared memory allocated for the current context.
Definition: veil_shmem.c:370
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.
Definition: veil_shmem.c:170
static HTAB * get_hash0()
Return reference to the HTAB for the shared hash associated with context 0.
Definition: veil_shmem.c:199
size_t total_allocated[2]
Total shared memory allocated in chunks in each context.
void _PG_init()
Veil&#39;s startup function.
Definition: veil_shmem.c:141
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...
Definition: veil_config.c:65
void * vl_shmalloc(size_t size)
Dynamically allocate a piece of shared memory from the current context.
Definition: veil_shmem.c:414
LWLock * lwlock
The LWLock associated with this memory context.
Definition: veil_shmem.h:59
static int get_cur_context_id()
Return the id (index) of the current context for this session.
Definition: veil_shmem.c:337
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...
Definition: veil_shmem.c:719
static LWLock * NextLWLock()
Return the next LWLock from our tranche.
Definition: veil_shmem.c:118
static void shmalloc_init(void)
Attach to, creating and initialising as necessary, the shared memory control structure.
Definition: veil_shmem.c:449