blob: ad73af1bd48cb2143cbdb2cd93a6fd1951cac023 [file] [log] [blame]
/*-------------------------------------------------------------------------
*
* ipci.c
* POSTGRES inter-process communication initialization code.
*
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.100 2009/05/05 19:59:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <signal.h>
#include "access/clog.h"
#include "access/heapam.h"
#include "access/multixact.h"
#include "access/nbtree.h"
#include "access/subtrans.h"
#include "access/twophase.h"
#include "access/appendonlywriter.h"
#include "cdb/cdbfilerep.h"
#include "cdb/cdbfilesystemcredential.h"
#include "cdb/cdbpersistentdatabase.h"
#include "cdb/cdbpersistentfilespace.h"
#include "cdb/cdbpersistentfilesysobj.h"
#include "cdb/cdbpersistentrecovery.h"
#include "cdb/cdbpersistentrelation.h"
#include "cdb/cdbpersistentrelfile.h"
#include "cdb/cdbpersistenttablespace.h"
#include "cdb/cdbresynchronizechangetracking.h"
#include "cdb/cdbvars.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/autovacuum.h"
#include "postmaster/bgwriter.h"
#include "postmaster/checkpoint.h"
#include "postmaster/identity.h"
#include "postmaster/postmaster.h"
#include "postmaster/primary_mirror_mode.h"
#include "postmaster/seqserver.h"
#include "postmaster/walredoserver.h"
#include "postmaster/walsendserver.h"
#include "storage/freespace.h"
#include "storage/ipc.h"
#include "storage/pg_shmem.h"
#include "storage/pmsignal.h"
#include "storage/procarray.h"
#include "storage/procsignal.h"
#include "storage/sinvaladt.h"
#include "storage/spin.h"
#include "utils/resscheduler.h"
#include "utils/faultinjector.h"
#include "utils/simex.h"
#include "cdb/cdbfts.h"
#include "utils/tqual.h"
#include "cdb/memquota.h"
#include "executor/spi.h"
#include "utils/workfile_mgr.h"
#include "cdb/cdbmetadatacache.h"
#include "cdb/cdbtmpdir.h"
#include "utils/session_state.h"
shmem_startup_hook_type shmem_startup_hook = NULL;
static Size total_addin_request = 0;
static bool addin_request_allowed = true;
/*
* RequestAddinShmemSpace
* Request that extra shmem space be allocated for use by
* a loadable module.
*
* This is only useful if called from the _PG_init hook of a library that
* is loaded into the postmaster via shared_preload_libraries. Once
* shared memory has been allocated, calls will be ignored. (We could
* raise an error, but it seems better to make it a no-op, so that
* libraries containing such calls can be reloaded if needed.)
*/
void
RequestAddinShmemSpace(Size size)
{
if (IsUnderPostmaster || !addin_request_allowed)
return; /* too late */
total_addin_request = add_size(total_addin_request, size);
}
/*
* CreateSharedMemoryAndSemaphores
* Creates and initializes shared memory and semaphores.
*
* This is called by the postmaster or by a standalone backend.
* It is also called by a backend forked from the postmaster in the
* EXEC_BACKEND case. In the latter case, the shared memory segment
* already exists and has been physically attached to, but we have to
* initialize pointers in local memory that reference the shared structures,
* because we didn't inherit the correct pointer values from the postmaster
* as we do in the fork() scenario. The easiest way to do that is to run
* through the same code as before. (Note that the called routines mostly
* check IsUnderPostmaster, rather than EXEC_BACKEND, to detect this case.
* This is a bit code-wasteful and could be cleaned up.)
*
* If "makePrivate" is true then we only need private memory, not shared
* memory. This is true for a standalone backend, false for a postmaster.
*/
void
CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
{
if (!IsUnderPostmaster)
{
PGShmemHeader *seghdr;
Size size;
int numSemas;
/*
* Size of the Postgres shared-memory block is estimated via
* moderately-accurate estimates for the big hogs, plus 100K for the
* stuff that's too small to bother with estimating.
*
* We take some care during this phase to ensure that the total size
* request doesn't overflow size_t. If this gets through, we don't
* need to be so careful during the actual allocation phase.
*/
size = 150000;
size = add_size(size, hash_estimate_size(SHMEM_INDEX_SIZE,
sizeof(ShmemIndexEnt)));
size = add_size(size, BufferShmemSize());
size = add_size(size, LockShmemSize());
size = add_size(size, workfile_mgr_shmem_size());
if (Gp_role == GP_ROLE_DISPATCH)
{
size = add_size(size, AppendOnlyWriterShmemSize());
}
size = add_size(size, ProcGlobalShmemSize());
size = add_size(size, XLOGShmemSize());
size = add_size(size, CLOGShmemSize());
size = add_size(size, SUBTRANSShmemSize());
size = add_size(size, TwoPhaseShmemSize());
size = add_size(size, MultiXactShmemSize());
size = add_size(size, LWLockShmemSize());
size = add_size(size, ProcArrayShmemSize());
size = add_size(size, BackendStatusShmemSize());
size = add_size(size, SharedSnapshotShmemSize());
size = add_size(size, SInvalShmemSize());
size = add_size(size, PMSignalShmemSize());
size = add_size(size, ProcSignalShmemSize());
size = add_size(size, primaryMirrorModeShmemSize());
size = add_size(size, FreeSpaceShmemSize());
//size = add_size(size, AutoVacuumShmemSize());
size = add_size(size, FtsShmemSize());
size = add_size(size, SeqServerShmemSize());
size = add_size(size, WalSendServerShmemSize());
size = add_size(size, WalRedoServerShmemSize());
size = add_size(size, PersistentFileSysObj_ShmemSize());
size = add_size(size, PersistentFilespace_ShmemSize());
size = add_size(size, PersistentTablespace_ShmemSize());
size = add_size(size, PersistentDatabase_ShmemSize());
size = add_size(size, PersistentRelation_ShmemSize());
size = add_size(size, PersistentRelfile_ShmemSize());
size = add_size(size, Pass2Recovery_ShmemSize());
size = add_size(size, FSCredShmemSize());
if (Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_UTILITY)
{
size = add_size(size, MetadataCache_ShmemSize());
elog(LOG, "Metadata Cache Share Memory Size : %lu", MetadataCache_ShmemSize());
}
#ifdef FAULT_INJECTOR
size = add_size(size, FaultInjector_ShmemSize());
#endif
#ifdef EXEC_BACKEND
size = add_size(size, ShmemBackendArraySize());
#endif
#ifdef USE_TEST_UTILS
if (gp_simex_init)
{
// initialize SimEx
simex_init();
size = add_size(size, SyncBitVector_ShmemSize(simex_get_subclass_count()));
}
#endif
/* This elog happens before we know the name of the log file we are supposed to use */
elog(DEBUG1, "Size not including the buffer pool %lu",
(unsigned long) size);
size = add_size(size, BgWriterShmemSize());
size = add_size(size, CheckpointShmemSize());
/* freeze the addin request size and include it */
addin_request_allowed = false;
size = add_size(size, total_addin_request);
/* might as well round it off to a multiple of a typical page size */
size = add_size(size, BLCKSZ - (size % BLCKSZ));
/* Consider the size of the SessionState array */
size = add_size(size, SessionState_ShmemSize());
/*
* Create the shmem segment
*/
seghdr = PGSharedMemoryCreate(size, makePrivate, port);
InitShmemAccess(seghdr);
/*
* Create semaphores
*/
numSemas = ProcGlobalSemas();
numSemas += SpinlockSemas();
elog(DEBUG3,"reserving %d semaphores",numSemas);
PGReserveSemaphores(numSemas, port);
}
else
{
/*
* We are reattaching to an existing shared memory segment. This
* should only be reached in the EXEC_BACKEND case, and even then only
* with makePrivate == false.
*/
#ifdef EXEC_BACKEND
Assert(!makePrivate);
#else
elog(PANIC, "should be attached to shared memory already");
#endif
}
/*
* Set up shared memory allocation mechanism
*/
if (!IsUnderPostmaster)
InitShmemAllocation();
/*
* Now initialize LWLocks, which do shared memory allocation and are
* needed for InitShmemIndex.
*/
if (!IsUnderPostmaster)
CreateLWLocks();
/*
* Set up shmem.c index hashtable
*/
InitShmemIndex();
primaryMirrorModeShmemInit();
/*
* Set up xlog, clog, and buffers
*/
XLOGShmemInit();
CLOGShmemInit();
SUBTRANSShmemInit();
TwoPhaseShmemInit();
MultiXactShmemInit();
FtsShmemInit();
InitBufferPool();
/*
* Set up lock manager
*/
InitLocks();
/*
* Set up append only writer
*/
if (Gp_role == GP_ROLE_DISPATCH)
{
InitAppendOnlyWriter();
}
PersistentFileSysObj_ShmemInit();
PersistentFilespace_ShmemInit();
PersistentTablespace_ShmemInit();
PersistentDatabase_ShmemInit();
PersistentRelation_ShmemInit();
PersistentRelfile_ShmemInit();
Pass2Recovery_ShmemInit();
if (Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_UTILITY)
{
MetadataCache_ShmemInit();
}
if (!IsUnderPostmaster)
{
/* Set up process table */
InitProcGlobal(PostmasterGetMppLocalProcessCounter());
}
/* Initialize SessionState shared memory array */
SessionState_ShmemInit();
/* Initialize vmem protection */
GPMemoryProtect_ShmemInit();
CreateSharedProcArray();
CreateSharedBackendStatus();
/*
* Set up Shared snapshot slots
*
* TODO: only need to do this if we aren't the QD. for now we are just
* doing it all the time and wasting shemem on the QD. This is
* because this happens at postmaster startup time when we don't
* know who we are.
*/
CreateSharedSnapshotArray();
/*
* Set up shared-inval messaging
*/
CreateSharedInvalidationState();
/*
* Set up free-space map
*/
InitFreeSpaceMap();
/*
* Set up interprocess signaling mechanisms
*/
PMSignalShmemInit();
ProcSignalShmemInit();
BgWriterShmemInit();
CheckpointShmemInit();
//AutoVacuumShmemInit();
SeqServerShmemInit();
WalSendServerShmemInit();
WalRedoServerShmemInit();
#ifdef FAULT_INJECTOR
FaultInjector_ShmemInit();
#endif
#ifdef USE_TEST_UTILS
if (gp_simex_init)
{
// initialize shmem segment for SimEx
simex_set_sync_bitvector_container(
SyncBitVector_ShmemInit("SimEx bit vector container", simex_get_subclass_count()));
}
#endif /* USE_TEST_UTILS */
/*
* Set up other modules that need some shared memory space
*/
BTreeShmemInit();
workfile_mgr_cache_init();
FSCredShmemInit();
#ifdef EXEC_BACKEND
/*
* Alloc the win32 shared backend array
*/
if (!IsUnderPostmaster)
ShmemBackendArrayAllocation();
#endif
SPI_InitMemoryReservation();
/*
* Now give loadable modules a chance to set up their shmem allocations
*/
if (shmem_startup_hook)
shmem_startup_hook();
}