diff options
Diffstat (limited to 'src/include')
56 files changed, 3721 insertions, 3 deletions
diff --git a/src/include/access/gtm.h b/src/include/access/gtm.h new file mode 100644 index 0000000000..66ca3f12c6 --- /dev/null +++ b/src/include/access/gtm.h @@ -0,0 +1,33 @@ +/*------------------------------------------------------------------------- + * + * gtm.h + * + * Module interfacing with GTM definitions + * + * + *------------------------------------------------------------------------- + */ +#ifndef ACCESS_GTM_H +#define ACCESS_GTM_H + +#include "gtm/gtm_c.h" + +/* Configuration variables */ +extern char *GtmHost; +extern int GtmPort; +extern int GtmCoordinatorId; + +extern bool IsGTMConnected(void); +extern void InitGTM(void); +extern void CloseGTM(void); +extern GlobalTransactionId BeginTranGTM(void); +extern GlobalTransactionId BeginTranAutovacuumGTM(void); +extern int CommitTranGTM(GlobalTransactionId gxid); +extern int RollbackTranGTM(GlobalTransactionId gxid); +extern GTM_Snapshot GetSnapshotGTM(GlobalTransactionId gxid, bool canbe_grouped); +extern GTM_Sequence GetNextValGTM(char *seqname); +extern int CreateSequenceGTM(char *seqname, GTM_Sequence increment, + GTM_Sequence minval, GTM_Sequence maxval, GTM_Sequence startval, + bool cycle); +extern int DropSequenceGTM(char *seqname); +#endif /* ACCESS_GTM_H */ diff --git a/src/include/access/transam.h b/src/include/access/transam.h index b23a663c53..a7a8230595 100644 --- a/src/include/access/transam.h +++ b/src/include/access/transam.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/access/transam.h,v 1.68 2009/05/08 03:21:35 momjian Exp $ * @@ -152,6 +153,11 @@ extern TransactionId TransactionIdLatest(TransactionId mainxid, extern XLogRecPtr TransactionIdGetCommitLSN(TransactionId xid); /* in transam/varsup.c */ +#ifdef PGXC /* PGXC_DATANODE */ +extern void SetNextTransactionId(TransactionId xid); +extern void SetForceXidFromGTM(bool value); +extern bool GetForceXidFromGTM(void); +#endif /* PGXC */ extern TransactionId GetNewTransactionId(bool isSubXact); extern TransactionId ReadNewTransactionId(void); extern void SetTransactionIdLimit(TransactionId oldest_datfrozenxid, diff --git a/src/include/access/xact.h b/src/include/access/xact.h index 880b41b707..7cd8e165ec 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.98 2009/06/11 14:49:09 momjian Exp $ * @@ -18,7 +19,9 @@ #include "nodes/pg_list.h" #include "storage/relfilenode.h" #include "utils/timestamp.h" - +#ifdef PGXC /* PGXC_COORD */ +#include "gtm/gtm_c.h" +#endif /* * Xact isolation levels @@ -145,6 +148,9 @@ extern TransactionId GetTopTransactionId(void); extern TransactionId GetTopTransactionIdIfAny(void); extern TransactionId GetCurrentTransactionId(void); extern TransactionId GetCurrentTransactionIdIfAny(void); +#ifdef PGXC /* PGXC_COORD */ +extern GlobalTransactionId GetCurrentGlobalTransactionId(void); +#endif extern SubTransactionId GetCurrentSubTransactionId(void); extern CommandId GetCurrentCommandId(bool used); extern TimestampTz GetCurrentTransactionStartTimestamp(void); diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h index ab549eabb1..e8f96604ad 100644 --- a/src/include/bootstrap/bootstrap.h +++ b/src/include/bootstrap/bootstrap.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.51 2009/01/01 17:23:56 momjian Exp $ * @@ -71,6 +72,9 @@ typedef enum StartupProcess, BgWriterProcess, WalWriterProcess +#ifdef PGXC + ,PoolerProcess +#endif } AuxProcType; #endif /* BOOTSTRAP_H */ diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index fe04aab964..b2af292585 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.40 2009/06/11 14:49:09 momjian Exp $ * @@ -146,6 +147,9 @@ typedef enum ObjectClass OCLASS_FDW, /* pg_foreign_data_wrapper */ OCLASS_FOREIGN_SERVER, /* pg_foreign_server */ OCLASS_USER_MAPPING, /* pg_user_mapping */ +#ifdef PGXC + OCLASS_PGXC_CLASS, /* pgxc_class */ +#endif MAX_OCLASS /* MUST BE LAST */ } ObjectClass; diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h index 2d6eb3c34a..baa9ecaf49 100644 --- a/src/include/catalog/heap.h +++ b/src/include/catalog/heap.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/catalog/heap.h,v 1.91 2009/06/11 14:49:09 momjian Exp $ * @@ -107,4 +108,11 @@ extern void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind); extern void CheckAttributeType(const char *attname, Oid atttypid); +#ifdef PGXC +extern void AddRelationDistribution (Oid relid, + DistributeBy *distributeby, + List *parentOids, + TupleDesc descriptor); +#endif + #endif /* HEAP_H */ diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h index ce117a8eec..5557021e30 100644 --- a/src/include/catalog/indexing.h +++ b/src/include/catalog/indexing.h @@ -7,6 +7,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.108 2009/06/11 14:49:09 momjian Exp $ * @@ -267,6 +268,11 @@ DECLARE_UNIQUE_INDEX(pg_user_mapping_oid_index, 174, on pg_user_mapping using bt DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, on pg_user_mapping using btree(umuser oid_ops, umserver oid_ops)); #define UserMappingUserServerIndexId 175 +#ifdef PGXC +DECLARE_UNIQUE_INDEX(pgxc_class_pcrelid_index, 9002, on pgxc_class using btree(pcrelid oid_ops)); +#define PgxcClassPgxcRelIdIndexId 9002 +#endif + /* last step of initialization script: build the indexes declared above */ BUILD_INDICES diff --git a/src/include/catalog/pgxc_class.h b/src/include/catalog/pgxc_class.h new file mode 100644 index 0000000000..2104e53e42 --- /dev/null +++ b/src/include/catalog/pgxc_class.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2004-2007 EnterpriseDB Corporation. All Rights Reserved. + */ +#ifndef PGXC_CLASS_H +#define PGXC_CLASS_H + +#include "nodes/parsenodes.h" + +#define PgxcClassRelationId 9001 + +CATALOG(pgxc_class,9001) BKI_WITHOUT_OIDS +{ + Oid pcrelid; + char pclocatortype; + int2 pcattnum; + int2 pchashalgorithm; + int2 pchashbuckets; +} FormData_pgxc_class; + +typedef FormData_pgxc_class *Form_pgxc_class; + +#define Natts_pgxc_class 5 + +#define Anum_pgxc_class_pcrelid 1 +#define Anum_pgxc_class_pclocatortype 2 +#define Anum_pgxc_class_pcattnum 3 +#define Anum_pgxc_class_pchashalgorithm 4 +#define Anum_pgxc_class_pchashbuckets 5 + +extern void PgxcClassCreate(Oid pcrelid, + char pclocatortype, + int pcattnum, + int pchashalgorithm, + int pchashbuckets); + +extern void RemovePgxcClass(Oid pcrelid); + +#endif /* PGXC_CLASS_H */ + diff --git a/src/include/gtm/assert.h b/src/include/gtm/assert.h new file mode 100644 index 0000000000..5c71363832 --- /dev/null +++ b/src/include/gtm/assert.h @@ -0,0 +1,72 @@ +/*------------------------------------------------------------------------- + * + * assert.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#ifndef GTM_ASSERT_H +#define GTM_ASSERT_H + +extern bool assert_enabled; + +/* + * USE_ASSERT_CHECKING, if defined, turns on all the assertions. + * - plai 9/5/90 + * + * It should _NOT_ be defined in releases or in benchmark copies + */ + +/* + * Trap + * Generates an exception if the given condition is true. + */ +#define Trap(condition, errorType) \ + do { \ + if ((assert_enabled) && (condition)) \ + ExceptionalCondition(CppAsString(condition), (errorType), \ + __FILE__, __LINE__); \ + } while (0) + +/* + * TrapMacro is the same as Trap but it's intended for use in macros: + * + * #define foo(x) (AssertMacro(x != 0) && bar(x)) + * + * Isn't CPP fun? + */ +#define TrapMacro(condition, errorType) \ + ((bool) ((! assert_enabled) || ! (condition) || \ + (ExceptionalCondition(CppAsString(condition), (errorType), \ + __FILE__, __LINE__)))) + +#ifndef USE_ASSERT_CHECKING +#define Assert(condition) +#define AssertMacro(condition) ((void)true) +#define AssertArg(condition) +#define AssertState(condition) +#else +#define Assert(condition) \ + Trap(!(condition), "FailedAssertion") + +#define AssertMacro(condition) \ + ((void) TrapMacro(!(condition), "FailedAssertion")) + +#define AssertArg(condition) \ + Trap(!(condition), "BadArgument") + +#define AssertState(condition) \ + Trap(!(condition), "BadState") +#endif /* USE_ASSERT_CHECKING */ + +extern int ExceptionalCondition(const char *conditionName, + const char *errorType, + const char *fileName, int lineNumber); + +#endif diff --git a/src/include/gtm/elog.h b/src/include/gtm/elog.h new file mode 100644 index 0000000000..49c463fa3e --- /dev/null +++ b/src/include/gtm/elog.h @@ -0,0 +1,253 @@ +/*------------------------------------------------------------------------- + * + * elog.h + * POSTGRES error reporting/logging definitions. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/utils/elog.h,v 1.98 2009/01/01 17:24:02 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef ELOG_H +#define ELOG_H + +/* Error level codes */ +#define DEBUG5 10 /* Debugging messages, in categories of + * decreasing detail. */ +#define DEBUG4 11 +#define DEBUG3 12 +#define DEBUG2 13 +#define DEBUG1 14 /* used by GUC debug_* variables */ +#define LOG 15 /* Server operational messages; sent only to + * server log by default. */ +#define COMMERROR 16 /* Client communication problems; same as LOG + * for server reporting, but never sent to + * client. */ +#define INFO 17 /* Messages specifically requested by user + * (eg VACUUM VERBOSE output); always sent to + * client regardless of client_min_messages, + * but by default not sent to server log. */ +#define NOTICE 18 /* Helpful messages to users about query + * operation; sent to client and server log + * by default. */ +#define WARNING 19 /* Warnings. NOTICE is for expected messages + * like implicit sequence creation by SERIAL. + * WARNING is for unexpected messages. */ +#define ERROR 20 /* user error - abort transaction; return to + * known state */ +#define ERROR2 21 /* user error - only send error message to the + * client */ +#define FATAL 22 /* fatal error - abort process */ +#define PANIC 23 /* take down the other backends with me */ + + /* #define DEBUG DEBUG1 */ /* Backward compatibility with pre-7.3 */ + + +/* Which __func__ symbol do we have, if any? */ +#ifdef HAVE_FUNCNAME__FUNC +#define PG_FUNCNAME_MACRO __func__ +#else +#ifdef HAVE_FUNCNAME__FUNCTION +#define PG_FUNCNAME_MACRO __FUNCTION__ +#else +#define PG_FUNCNAME_MACRO NULL +#endif +#endif + +/* + * ErrorData holds the data accumulated during any one ereport() cycle. + * Any non-NULL pointers must point to palloc'd data. + * (The const pointers are an exception; we assume they point at non-freeable + * constant strings.) + */ +typedef struct ErrorData +{ + int elevel; /* error level */ + bool output_to_server; /* will report to server log? */ + bool output_to_client; /* will report to client? */ + bool show_funcname; /* true to force funcname inclusion */ + const char *filename; /* __FILE__ of ereport() call */ + int lineno; /* __LINE__ of ereport() call */ + const char *funcname; /* __func__ of ereport() call */ + const char *domain; /* message domain */ + char *message; /* primary error message */ + char *detail; /* detail error message */ + char *detail_log; /* detail error message for server log only */ + char *hint; /* hint message */ + char *context; /* context message */ + int saved_errno; /* errno at entry */ +} ErrorData; + + +/*---------- + * New-style error reporting API: to be used in this way: + * ereport(ERROR, + * (errcode(ERRCODE_UNDEFINED_CURSOR), + * errmsg("portal \"%s\" not found", stmt->portalname), + * ... other errxxx() fields as needed ...)); + * + * The error level is required, and so is a primary error message (errmsg + * or errmsg_internal). All else is optional. errcode() defaults to + * ERRCODE_INTERNAL_ERROR if elevel is ERROR or more, ERRCODE_WARNING + * if elevel is WARNING, or ERRCODE_SUCCESSFUL_COMPLETION if elevel is + * NOTICE or below. + * + * ereport_domain() allows a message domain to be specified, for modules that + * wish to use a different message catalog from the backend's. To avoid having + * one copy of the default text domain per .o file, we define it as NULL here + * and have errstart insert the default text domain. Modules can either use + * ereport_domain() directly, or preferably they can override the TEXTDOMAIN + * macro. + *---------- + */ +#define TEXTDOMAIN "GTM" + +#define ereport_domain(elevel, domain, rest) \ + (errstart(elevel, __FILE__, __LINE__, PG_FUNCNAME_MACRO, domain) ? \ + (errfinish rest) : (void) 0) + +#define ereport(level, rest) \ + ereport_domain(level, TEXTDOMAIN, rest) + + +#define PG_RE_THROW() pg_re_throw() + +extern bool errstart(int elevel, const char *filename, int lineno, + const char *funcname, const char *domain); +extern void errfinish(int dummy,...); + +extern int +errmsg(const char *fmt,...) +/* This extension allows gcc to check the format string for consistency with + the supplied arguments. */ +__attribute__((format(printf, 1, 2))); + +extern int +errmsg_internal(const char *fmt,...) +/* This extension allows gcc to check the format string for consistency with + the supplied arguments. */ +__attribute__((format(printf, 1, 2))); + +extern int +errdetail(const char *fmt,...) +/* This extension allows gcc to check the format string for consistency with + the supplied arguments. */ +__attribute__((format(printf, 1, 2))); + +extern int +errdetail_log(const char *fmt,...) +/* This extension allows gcc to check the format string for consistency with + the supplied arguments. */ +__attribute__((format(printf, 1, 2))); + +extern int +errhint(const char *fmt,...) +/* This extension allows gcc to check the format string for consistency with + the supplied arguments. */ +__attribute__((format(printf, 1, 2))); + +/*---------- + * Old-style error reporting API: to be used in this way: + * elog(ERROR, "portal \"%s\" not found", stmt->portalname); + *---------- + */ +#define elog elog_start(__FILE__, __LINE__, PG_FUNCNAME_MACRO), elog_finish + +extern void elog_start(const char *filename, int lineno, const char *funcname); +extern void +elog_finish(int elevel, const char *fmt,...) +/* This extension allows gcc to check the format string for consistency with + the supplied arguments. */ +__attribute__((format(printf, 2, 3))); + +/*---------- + * API for catching ereport(ERROR) exits. Use these macros like so: + * + * PG_TRY(); + * { + * ... code that might throw ereport(ERROR) ... + * } + * PG_CATCH(); + * { + * ... error recovery code ... + * } + * PG_END_TRY(); + * + * (The braces are not actually necessary, but are recommended so that + * pg_indent will indent the construct nicely.) The error recovery code + * can optionally do PG_RE_THROW() to propagate the same error outwards. + * + * Note: while the system will correctly propagate any new ereport(ERROR) + * occurring in the recovery section, there is a small limit on the number + * of levels this will work for. It's best to keep the error recovery + * section simple enough that it can't generate any new errors, at least + * not before popping the error stack. + * + * Note: an ereport(FATAL) will not be caught by this construct; control will + * exit straight through proc_exit(). Therefore, do NOT put any cleanup + * of non-process-local resources into the error recovery section, at least + * not without taking thought for what will happen during ereport(FATAL). + * The PG_ENSURE_ERROR_CLEANUP macros provided by storage/ipc.h may be + * helpful in such cases. + *---------- + */ +#define PG_TRY() \ + do { \ + sigjmp_buf *save_exception_stack = PG_exception_stack; \ + sigjmp_buf local_sigjmp_buf; \ + if (sigsetjmp(local_sigjmp_buf, 0) == 0) \ + { \ + PG_exception_stack = &local_sigjmp_buf + +#define PG_CATCH() \ + } \ + else \ + { \ + PG_exception_stack = save_exception_stack; \ + +#define PG_END_TRY() \ + } \ + PG_exception_stack = save_exception_stack; \ + } while (0) + +int errfunction(const char *funcname); + +extern void EmitErrorReport(void *port); + +/* GUC-configurable parameters */ + +typedef enum +{ + PGERROR_TERSE, /* single-line error messages */ + PGERROR_DEFAULT, /* recommended style */ + PGERROR_VERBOSE /* all the facts, ma'am */ +} PGErrorVerbosity; + +/* Log destination bitmap */ +#define LOG_DESTINATION_STDERR 1 +#define LOG_DESTINATION_SYSLOG 2 +#define LOG_DESTINATION_EVENTLOG 4 +#define LOG_DESTINATION_CSVLOG 8 + +/* Other exported functions */ +extern void pg_re_throw(void); +extern void DebugFileOpen(void); +extern void FlushErrorState(void); + + +/* + * Write errors to stderr (or by equal means when stderr is + * not available). Used before ereport/elog can be used + * safely (memory context, GUC load etc) + */ +extern void +write_stderr(const char *fmt,...) +/* This extension allows gcc to check the format string for consistency with + the supplied arguments. */ +__attribute__((format(printf, 1, 2))); + +#endif /* ELOG_H */ diff --git a/src/include/gtm/gtm.h b/src/include/gtm/gtm.h new file mode 100644 index 0000000000..37e23a7ffa --- /dev/null +++ b/src/include/gtm/gtm.h @@ -0,0 +1,140 @@ +/*------------------------------------------------------------------------- + * + * gtm.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#ifndef _GTM_H +#define _GTM_H + +#include <setjmp.h> + +#include "gtm/gtm_c.h" +#include "gtm/palloc.h" +#include "gtm/gtm_lock.h" +#include "gtm/gtm_conn.h" +#include "gtm/elog.h" +#include "gtm/gtm_list.h" + +extern char *GTMLogFile; + +typedef enum GTM_ThreadStatus +{ + GTM_THREAD_STARTING, + GTM_THREAD_RUNNING, + GTM_THREAD_EXITING, + /* Must be the last */ + GTM_THREAD_INVALID +} GTM_ThreadStatus; + +struct GTM_ConnectionInfo; + +#define ERRORDATA_STACK_SIZE 5 + +typedef struct GTM_ThreadInfo +{ + /* + * Thread specific information such as connection(s) served by it + */ + GTM_ThreadID thr_id; + uint32 thr_localid; + void * (* thr_startroutine)(void *); + + MemoryContext thr_thread_context; + MemoryContext thr_message_context; + MemoryContext thr_current_context; + MemoryContext thr_error_context; + MemoryContext thr_parent_context; + + sigjmp_buf *thr_sigjmp_buf; + + ErrorData thr_error_data[ERRORDATA_STACK_SIZE]; + int thr_error_stack_depth; + int thr_error_recursion_depth; + int thr_criticalsec_count; + + GTM_ThreadStatus thr_status; + GTM_ConnectionInfo *thr_conn; + + GTM_RWLock thr_lock; + List *thr_cached_txninfo; + +} GTM_ThreadInfo; + +typedef struct GTM_Threads +{ + uint32 gt_thread_count; + uint32 gt_array_size; + GTM_ThreadInfo **gt_threads; + GTM_RWLock gt_lock; +} GTM_Threads; + +extern GTM_Threads *GTMThreads; + +int GTM_ThreadAdd(GTM_ThreadInfo *thrinfo); +int GTM_ThreadRemove(GTM_ThreadInfo *thrinfo); +int GTM_ThreadJoin(GTM_ThreadInfo *thrinfo); +void GTM_ThreadExit(void); +void ConnFree(Port *port); + +GTM_ThreadInfo *GTM_ThreadCreate(GTM_ConnectionInfo *conninfo, + void *(* startroutine)(void *)); +GTM_ThreadInfo * GTM_GetThreadInfo(GTM_ThreadID thrid); + +/* + * pthread keys to get thread specific information + */ +extern pthread_key_t threadinfo_key; +extern MemoryContext TopMostMemoryContext; + +#define SetMyThreadInfo(thrinfo) pthread_setspecific(threadinfo_key, (thrinfo)) +#define GetMyThreadInfo ((GTM_ThreadInfo *)pthread_getspecific(threadinfo_key)) + +#define TopMemoryContext (GetMyThreadInfo->thr_thread_context) +#define ThreadTopContext (GetMyThreadInfo->thr_thread_context) +#define MessageContext (GetMyThreadInfo->thr_message_context) +#define CurrentMemoryContext (GetMyThreadInfo->thr_current_context) +#define ErrorContext (GetMyThreadInfo->thr_error_context) +#define errordata (GetMyThreadInfo->thr_error_data) +#define recursion_depth (GetMyThreadInfo->thr_error_recursion_depth) +#define errordata_stack_depth (GetMyThreadInfo->thr_error_stack_depth) +#define CritSectionCount (GetMyThreadInfo->thr_criticalsec_count) + +#define PG_exception_stack (GetMyThreadInfo->thr_sigjmp_buf) +#define MyConnection (GetMyThreadInfo->thr_conn) +#define MyPort ((GetMyThreadInfo->thr_conn != NULL) ? \ + GetMyThreadInfo->thr_conn->con_port : \ + NULL) +#define MyThreadID (GetMyThreadInfo->thr_id) + +#define GTM_CachedTransInfo (GetMyThreadInfo->thr_cached_txninfo) +#define GTM_HaveFreeCachedTransInfo() (list_length(GTM_CachedTransInfo)) + +#define GTM_MAX_CACHED_TRANSINFO 0 +#define GTM_HaveEnoughCachedTransInfo() (list_length(GTM_CachedTransInfo) >= GTM_MAX_CACHED_TRANSINFO) + +#define START_CRIT_SECTION() (CritSectionCount++) + +#define END_CRIT_SECTION() \ + do { \ + Assert(CritSectionCount > 0); \ + CritSectionCount--; \ + } while(0) + + +#if 0 + +/* Coordinator registration */ +int GTM_RegisterCoordinator(GTM_CoordInfo *cinfo); +int GTM_UnregisterCoordinator(GTM_CoordinatorId cid); + +#endif + +#endif diff --git a/src/include/gtm/gtm_c.h b/src/include/gtm/gtm_c.h new file mode 100644 index 0000000000..1a04064b6d --- /dev/null +++ b/src/include/gtm/gtm_c.h @@ -0,0 +1,101 @@ +/*------------------------------------------------------------------------- + * + * c.h + * Fundamental C definitions. This is included by every .c file in + * PostgreSQL (via either postgres.h or postgres_fe.h, as appropriate). + * + * Note that the definitions here are not intended to be exposed to clients + * of the frontend interface libraries --- so we don't worry much about + * polluting the namespace with lots of stuff... + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/c.h,v 1.234 2009/01/01 17:23:55 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef GTM_C_H +#define GTM_C_H + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stddef.h> +#include <stdarg.h> +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#include <sys/types.h> + +#include <errno.h> +#include <pthread.h> +#include "c.h" + +typedef uint32 GlobalTransactionId; /* 32-bit global transaction ids */ +typedef uint32 PGXC_NodeId; +typedef uint32 GTM_CoordinatorId; +typedef int16 GTMProxy_ConnID; + +#define InvalidGTMProxyConnID -1 + +typedef pthread_t GTM_ThreadID; + +/* + * A unique handle to identify transaction at the GTM. It could just be + * an index in an array or a pointer to the structure + * + * Note: If we get rid of BEGIN transaction at the GTM, we can use GXID + * as a handle because we would never have a transaction state at the + * GTM without assigned GXID. + */ +typedef int32 GTM_TransactionHandle; + +#define InvalidTransactionHandle -1 + +typedef int64 GTM_Sequence; /* a 64-bit sequence */ +typedef struct GTM_SequenceKeyData +{ + uint32 gsk_keylen; + char *gsk_key; +} GTM_SequenceKeyData; /* Counter key, set by the client */ + +typedef GTM_SequenceKeyData *GTM_SequenceKey; +#define GTM_MAX_SEQKEY_LENGTH 1024 + +#define InvalidSequenceValue 0x7fffffffffffffffLL +#define SEQVAL_IS_VALID(v) ((v) != InvalidSequenceValue) + +#define GTM_MAX_GLOBAL_TRANSACTIONS 4096 + +typedef enum GTM_IsolationLevel +{ + GTM_ISOLATION_SERIALIZABLE, /* serializable txn */ + GTM_ISOLATION_RC /* read-committed txn */ +} GTM_IsolationLevel; + +typedef struct GTM_SnapshotData +{ + GlobalTransactionId sn_xmin; + GlobalTransactionId sn_xmax; + GlobalTransactionId sn_recent_global_xmin; + uint32 sn_xcnt; + GlobalTransactionId *sn_xip; +} GTM_SnapshotData; + +typedef GTM_SnapshotData *GTM_Snapshot; + +typedef struct GTM_StartupPacket { + GTM_CoordinatorId sp_cid; + bool sp_isproxy; +} GTM_StartupPacket; + +#define InvalidGlobalTransactionId ((GlobalTransactionId) 0) + +#define GlobalTransactionIdIsValid(gxid) ((GlobalTransactionId) (gxid)) != InvalidGlobalTransactionId + +#define _(x) gettext(x) + +#endif /* GTM_C_H */ diff --git a/src/include/gtm/gtm_client.h b/src/include/gtm/gtm_client.h new file mode 100644 index 0000000000..29eeaf95f9 --- /dev/null +++ b/src/include/gtm/gtm_client.h @@ -0,0 +1,129 @@ +/*------------------------------------------------------------------------- + * + * gtm_client.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#ifndef GTM_CLIENT_H +#define GTM_CLIENT_H + +#include "gtm/gtm_c.h" +#include "gtm/gtm_msg.h" +#include "gtm/libpq-fe.h" + +typedef union GTM_ResultData +{ + GTM_TransactionHandle grd_txnhandle; /* TXN_BEGIN */ + GlobalTransactionId grd_gxid; /* TXN_BEGIN_GETGXID + * TXN_PREPARE + * TXN_COMMIT + * TXN_ROLLBACK + */ + + struct + { + GTM_TransactionHandle txnhandle; + GlobalTransactionId gxid; + } grd_txn; /* TXN_GET_GXID + * SNAPSHOT_GET + * SNAPSHOT_GXID_GET */ + + GTM_SequenceKeyData grd_seqkey; /* SEQUENCE_INIT + * SEQUENCE_RESET + * SEQUENCE_CLOSE */ + struct + { + GTM_SequenceKeyData seqkey; + GTM_Sequence seqval; + } grd_seq; /* SEQUENCE_GET_CURRENT + SEQUENCE_GET_NEXT */ + + struct + { + int txn_count; /* TXN_BEGIN_GETGXID_MULTI */ + GlobalTransactionId start_gxid; + } grd_txn_get_multi; + + struct + { + int txn_count; /* TXN_COMMIT_MULTI */ + int status[GTM_MAX_GLOBAL_TRANSACTIONS]; + } grd_txn_rc_multi; + + struct + { + int txn_count; /* GET_SNAPSHOT_MULTI */ + int status[GTM_MAX_GLOBAL_TRANSACTIONS]; + } grd_txn_snap_multi; + + /* + * TODO + * TXN_GET_STATUS + * TXN_GET_ALL_PREPARED + */ +} GTM_ResultData; + +typedef struct GTM_Result +{ + GTM_ResultType gr_type; + int gr_msglen; + int gr_status; + GTM_ProxyMsgHeader gr_proxyhdr; + GTM_ResultData gr_resdata; + /* + * We keep these two items outside the union to avoid repeated malloc/free + * of the xip array. If these items are pushed inside the union, they may + * get overwritten by other members in the union + */ + int gr_xip_size; + GTM_SnapshotData gr_snapshot; + + /* + * Similarly, keep the buffer for proxying data outside the union + */ + char *gr_proxy_data; + int gr_proxy_datalen; +} GTM_Result; + +/* + * Connection Management API + */ +GTM_Conn *connect_gtm(const char *connect_string); +void disconnect_gtm(GTM_Conn *conn); + +/* + * Transaction Management API + */ +GlobalTransactionId begin_transaction(GTM_Conn *conn, GTM_IsolationLevel isolevel); +GlobalTransactionId begin_transaction_autovacuum(GTM_Conn *conn, GTM_IsolationLevel isolevel); +int commit_transaction(GTM_Conn *conn, GlobalTransactionId gxid); +int abort_transaction(GTM_Conn *conn, GlobalTransactionId gxid); +int prepare_transaction(GTM_Conn *conn, GlobalTransactionId gxid, + int nodecnt, PGXC_NodeId nodes[]); + +/* + * Snapshot Management API + */ +GTM_SnapshotData *get_snapshot(GTM_Conn *conn, GlobalTransactionId gxid, + bool canbe_grouped); + +/* + * Sequence Management API + */ +int open_sequence(GTM_Conn *conn, GTM_SequenceKey key, GTM_Sequence increment, + GTM_Sequence minval, GTM_Sequence maxval, + GTM_Sequence startval, bool cycle); +int close_sequence(GTM_Conn *conn, GTM_SequenceKey key); +GTM_Sequence get_current(GTM_Conn *conn, GTM_SequenceKey key); +GTM_Sequence get_next(GTM_Conn *conn, GTM_SequenceKey key); +int reset_sequence(GTM_Conn *conn, GTM_SequenceKey key); + + +#endif diff --git a/src/include/gtm/gtm_conn.h b/src/include/gtm/gtm_conn.h new file mode 100644 index 0000000000..911a345c4f --- /dev/null +++ b/src/include/gtm/gtm_conn.h @@ -0,0 +1,38 @@ +/*------------------------------------------------------------------------- + * + * gtm_conn.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#ifndef GTM_CONN_H +#define GTM_CONN_H + +#include "gtm/libpq-be.h" + +struct GTM_ThreadInfo; + +typedef struct GTM_ConnectionInfo +{ + /* Port contains all the vital information about this connection */ + Port *con_port; + struct GTM_ThreadInfo *con_thrinfo; + bool con_authenticated; +} GTM_ConnectionInfo; + +typedef struct GTM_Connections +{ + uint32 gc_conn_count; + uint32 gc_array_size; + GTM_ConnectionInfo *gc_connections; + GTM_RWLock gc_lock; +} GTM_Connections; + + +#endif diff --git a/src/include/gtm/gtm_ext.h b/src/include/gtm/gtm_ext.h new file mode 100644 index 0000000000..b492941779 --- /dev/null +++ b/src/include/gtm/gtm_ext.h @@ -0,0 +1,31 @@ +/*------------------------------------------------------------------------- + * + * gtm_ext.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#ifndef GTM_EXT_H +#define GTM_EXT_H + +/* + * Identifiers of error message fields. Kept here to keep common + * between frontend and backend, and also to export them to libpq + * applications. + */ +#define PG_DIAG_SEVERITY 'S' +#define PG_DIAG_MESSAGE_PRIMARY 'M' +#define PG_DIAG_MESSAGE_DETAIL 'D' +#define PG_DIAG_MESSAGE_HINT 'H' +#define PG_DIAG_SOURCE_FILE 'F' +#define PG_DIAG_SOURCE_LINE 'L' +#define PG_DIAG_SOURCE_FUNCTION 'R' + + +#endif diff --git a/src/include/gtm/gtm_ip.h b/src/include/gtm/gtm_ip.h new file mode 100644 index 0000000000..30da3081d3 --- /dev/null +++ b/src/include/gtm/gtm_ip.h @@ -0,0 +1,50 @@ +/*------------------------------------------------------------------------- + * + * ip.h + * Definitions for IPv6-aware network access. + * + * These definitions are used by both frontend and backend code. Be careful + * what you include here! + * + * Copyright (c) 2003-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/libpq/ip.h,v 1.20 2008/01/01 19:45:58 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef IP_H +#define IP_H + +#include "gtm/pqcomm.h" + + +extern int gtm_getaddrinfo_all(const char *hostname, const char *servname, + const struct addrinfo * hintp, + struct addrinfo ** result); +extern void gtm_freeaddrinfo_all(int hint_ai_family, struct addrinfo * ai); + +extern int gtm_getnameinfo_all(const struct sockaddr_storage * addr, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags); + +extern int gtm_range_sockaddr(const struct sockaddr_storage * addr, + const struct sockaddr_storage * netaddr, + const struct sockaddr_storage * netmask); + +extern int gtm_sockaddr_cidr_mask(struct sockaddr_storage * mask, + char *numbits, int family); + +#ifdef HAVE_IPV6 +extern void gtm_promote_v4_to_v6_addr(struct sockaddr_storage * addr); +extern void gtm_promote_v4_to_v6_mask(struct sockaddr_storage * addr); +#endif + +#ifdef HAVE_UNIX_SOCKETS +#define IS_AF_UNIX(fam) ((fam) == AF_UNIX) +#else +#define IS_AF_UNIX(fam) (0) +#endif + +#endif /* IP_H */ diff --git a/src/include/gtm/gtm_list.h b/src/include/gtm/gtm_list.h new file mode 100644 index 0000000000..6a5727f36a --- /dev/null +++ b/src/include/gtm/gtm_list.h @@ -0,0 +1,280 @@ +/*------------------------------------------------------------------------- + * + * pg_list.h + * interface for PostgreSQL generic linked list package + * + * This package implements singly-linked homogeneous lists. + * + * It is important to have constant-time length, append, and prepend + * operations. To achieve this, we deal with two distinct data + * structures: + * + * 1. A set of "list cells": each cell contains a data field and + * a link to the next cell in the list or NULL. + * 2. A single structure containing metadata about the list: the + * type of the list, pointers to the head and tail cells, and + * the length of the list. + * + * We support three types of lists: + * + * T_List: lists of pointers + * (in practice usually pointers to Nodes, but not always; + * declared as "void *" to minimize casting annoyances) + * T_IntList: lists of integers + * T_OidList: lists of Oids + * + * (At the moment, ints and Oids are the same size, but they may not + * always be so; try to be careful to maintain the distinction.) + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/nodes/pg_list.h,v 1.59 2008/08/14 18:48:00 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef GTM_LIST_H +#define GTM_LIST_H + + +typedef struct ListCell ListCell; + +typedef struct List +{ + int length; + ListCell *head; + ListCell *tail; +} List; + +struct ListCell +{ + union + { + void *ptr_value; + int int_value; + } data; + ListCell *next; +}; + +/* + * The *only* valid representation of an empty list is NIL; in other + * words, a non-NIL list is guaranteed to have length >= 1 and + * head/tail != NULL + */ +#define NIL ((List *) NULL) + +/* + * These routines are used frequently. However, we can't implement + * them as macros, since we want to avoid double-evaluation of macro + * arguments. Therefore, we implement them using GCC inline functions, + * and as regular functions with non-GCC compilers. + */ +#ifdef __GNUC__ + +static __inline__ ListCell * +list_head(List *l) +{ + return l ? l->head : NULL; +} + +static __inline__ ListCell * +list_tail(List *l) +{ + return l ? l->tail : NULL; +} + +static __inline__ int +list_length(List *l) +{ + return l ? l->length : 0; +} +#else + +extern ListCell *list_head(List *l); +extern ListCell *list_tail(List *l); +extern int list_length(List *l); +#endif /* __GNUC__ */ + +/* + * NB: There is an unfortunate legacy from a previous incarnation of + * the List API: the macro lfirst() was used to mean "the data in this + * cons cell". To avoid changing every usage of lfirst(), that meaning + * has been kept. As a result, lfirst() takes a ListCell and returns + * the data it contains; to get the data in the first cell of a + * List, use linitial(). Worse, lsecond() is more closely related to + * linitial() than lfirst(): given a List, lsecond() returns the data + * in the second cons cell. + */ + +#define lnext(lc) ((lc)->next) +#define lfirst(lc) ((lc)->data.ptr_value) +#define lfirst_int(lc) ((lc)->data.int_value) + +#define linitial(l) lfirst(list_head(l)) +#define linitial_int(l) lfirst_int(list_head(l)) + +#define lsecond(l) lfirst(lnext(list_head(l))) +#define lsecond_int(l) lfirst_int(lnext(list_head(l))) + +#define lthird(l) lfirst(lnext(lnext(list_head(l)))) +#define lthird_int(l) lfirst_int(lnext(lnext(list_head(l)))) + +#define lfourth(l) lfirst(lnext(lnext(lnext(list_head(l))))) +#define lfourth_int(l) lfirst_int(lnext(lnext(lnext(list_head(l))))) + +#define llast(l) lfirst(list_tail(l)) +#define llast_int(l) lfirst_int(list_tail(l)) + +/* + * Convenience macros for building fixed-length lists + */ +#define list_make1(x1) lcons(x1, NIL) +#define list_make2(x1,x2) lcons(x1, list_make1(x2)) +#define list_make3(x1,x2,x3) lcons(x1, list_make2(x2, x3)) +#define list_make4(x1,x2,x3,x4) lcons(x1, list_make3(x2, x3, x4)) + +#define list_make1_int(x1) lcons_int(x1, NIL) +#define list_make2_int(x1,x2) lcons_int(x1, list_make1_int(x2)) +#define list_make3_int(x1,x2,x3) lcons_int(x1, list_make2_int(x2, x3)) +#define list_make4_int(x1,x2,x3,x4) lcons_int(x1, list_make3_int(x2, x3, x4)) + +/* + * foreach - + * a convenience macro which loops through the list + */ +#define foreach(cell, l) \ + for ((cell) = list_head(l); (cell) != NULL; (cell) = lnext(cell)) + +/* + * for_each_cell - + * a convenience macro which loops through a list starting from a + * specified cell + */ +#define for_each_cell(cell, initcell) \ + for ((cell) = (initcell); (cell) != NULL; (cell) = lnext(cell)) + +/* + * forboth - + * a convenience macro for advancing through two linked lists + * simultaneously. This macro loops through both lists at the same + * time, stopping when either list runs out of elements. Depending + * on the requirements of the call site, it may also be wise to + * assert that the lengths of the two lists are equal. + */ +#define forboth(cell1, list1, cell2, list2) \ + for ((cell1) = list_head(list1), (cell2) = list_head(list2); \ + (cell1) != NULL && (cell2) != NULL; \ + (cell1) = lnext(cell1), (cell2) = lnext(cell2)) + +extern List *lappend(List *list, void *datum); +extern List *lappend_int(List *list, int datum); + +extern ListCell *lappend_cell(List *list, ListCell *prev, void *datum); +extern ListCell *lappend_cell_int(List *list, ListCell *prev, int datum); + +extern List *lcons(void *datum, List *list); +extern List *lcons_int(int datum, List *list); + +extern List *list_concat(List *list1, List *list2); +extern List *list_truncate(List *list, int new_size); + +extern void *list_nth(List *list, int n); +extern int list_nth_int(List *list, int n); + +extern bool list_member(List *list, void *datum); +extern bool list_member_ptr(List *list, void *datum); +extern bool list_member_int(List *list, int datum); + +extern List *list_delete(List *list, void *datum); +extern List *list_delete_ptr(List *list, void *datum); +extern List *list_delete_int(List *list, int datum); +extern List *list_delete_first(List *list); +extern List *list_delete_cell(List *list, ListCell *cell, ListCell *prev); + +extern List *list_union(List *list1, List *list2); +extern List *list_union_ptr(List *list1, List *list2); +extern List *list_union_int(List *list1, List *list2); + +extern List *list_intersection(List *list1, List *list2); +/* currently, there's no need for list_intersection_int etc */ + +extern List *list_difference(List *list1, List *list2); +extern List *list_difference_ptr(List *list1, List *list2); +extern List *list_difference_int(List *list1, List *list2); + +extern List *list_append_unique(List *list, void *datum); +extern List *list_append_unique_ptr(List *list, void *datum); +extern List *list_append_unique_int(List *list, int datum); + +extern List *list_concat_unique(List *list1, List *list2); +extern List *list_concat_unique_ptr(List *list1, List *list2); +extern List *list_concat_unique_int(List *list1, List *list2); + +extern void list_free(List *list); +extern void list_free_deep(List *list); + +extern List *list_copy(List *list); +extern List *list_copy_tail(List *list, int nskip); + +/* + * To ease migration to the new list API, a set of compatibility + * macros are provided that reduce the impact of the list API changes + * as far as possible. Until client code has been rewritten to use the + * new list API, the ENABLE_LIST_COMPAT symbol can be defined before + * including pg_list.h + */ +#ifdef ENABLE_LIST_COMPAT + +#define lfirsti(lc) lfirst_int(lc) + +#define makeList1(x1) list_make1(x1) +#define makeList2(x1, x2) list_make2(x1, x2) +#define makeList3(x1, x2, x3) list_make3(x1, x2, x3) +#define makeList4(x1, x2, x3, x4) list_make4(x1, x2, x3, x4) + +#define makeListi1(x1) list_make1_int(x1) +#define makeListi2(x1, x2) list_make2_int(x1, x2) + +#define lconsi(datum, list) lcons_int(datum, list) + +#define lappendi(list, datum) lappend_int(list, datum) + +#define nconc(l1, l2) list_concat(l1, l2) + +#define nth(n, list) list_nth(list, n) + +#define member(datum, list) list_member(list, datum) +#define ptrMember(datum, list) list_member_ptr(list, datum) +#define intMember(datum, list) list_member_int(list, datum) + +/* + * Note that the old lremove() determined equality via pointer + * comparison, whereas the new list_delete() uses equal(); in order to + * keep the same behavior, we therefore need to map lremove() calls to + * list_delete_ptr() rather than list_delete() + */ +#define lremove(elem, list) list_delete_ptr(list, elem) +#define LispRemove(elem, list) list_delete(list, elem) +#define lremovei(elem, list) list_delete_int(list, elem) + +#define ltruncate(n, list) list_truncate(list, n) + +#define set_union(l1, l2) list_union(l1, l2) +#define set_ptrUnion(l1, l2) list_union_ptr(l1, l2) + +#define set_difference(l1, l2) list_difference(l1, l2) +#define set_ptrDifference(l1, l2) list_difference_ptr(l1, l2) + +#define equali(l1, l2) equal(l1, l2) +#define equalo(l1, l2) equal(l1, l2) + +#define freeList(list) list_free(list) + +#define listCopy(list) list_copy(list) + +extern int length(List *list); +#endif /* ENABLE_LIST_COMPAT */ + +#endif /* GTM_LIST_H */ diff --git a/src/include/gtm/gtm_lock.h b/src/include/gtm/gtm_lock.h new file mode 100644 index 0000000000..f4a5e025ba --- /dev/null +++ b/src/include/gtm/gtm_lock.h @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------- + * + * gtm_lock.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ + +#ifndef GTM_LOCK_H +#define GTM_LOCK_H + +#include <pthread.h> + +typedef struct GTM_RWLock +{ + pthread_rwlock_t lk_lock; +} GTM_RWLock; + +typedef struct GTM_MutexLock +{ + pthread_mutex_t lk_lock; +} GTM_MutexLock; + +typedef enum GTM_LockMode +{ + GTM_LOCKMODE_WRITE, + GTM_LOCKMODE_READ +} GTM_LockMode; + +typedef struct GTM_CV +{ + pthread_cond_t cv_condvar; +} GTM_CV; + +extern bool GTM_RWLockAcquire(GTM_RWLock *lock, GTM_LockMode mode); +extern bool GTM_RWLockRelease(GTM_RWLock *lock); +extern int GTM_RWLockInit(GTM_RWLock *lock); +extern int GTM_RWLockDestroy(GTM_RWLock *lock); +extern bool GTM_RWLockConditionalAcquire(GTM_RWLock *lock, GTM_LockMode mode); + +extern bool GTM_MutexLockAcquire(GTM_MutexLock *lock); +extern bool GTM_MutexLockRelease(GTM_MutexLock *lock); +extern int GTM_MutexLockInit(GTM_MutexLock *lock); +extern int GTM_MutexLockDestroy(GTM_MutexLock *lock); +extern bool GTM_MutexLockConditionalAcquire(GTM_MutexLock *lock); + +extern int GTM_CVInit(GTM_CV *cv); +extern int GTM_CVDestroy(GTM_CV *cv); +extern int GTM_CVSignal(GTM_CV *cv); +extern int GTM_CVBcast(GTM_CV *cv); +extern int GTM_CVWait(GTM_CV *cv, GTM_MutexLock *lock); + +#endif diff --git a/src/include/gtm/gtm_msg.h b/src/include/gtm/gtm_msg.h new file mode 100644 index 0000000000..cae061437d --- /dev/null +++ b/src/include/gtm/gtm_msg.h @@ -0,0 +1,88 @@ +/*------------------------------------------------------------------------- + * + * gtm_msg.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#ifndef GTM_MSG_H +#define GTM_MSG_H + +typedef enum GTM_MessageType +{ + MSG_TYPE_INVALID, + MSG_REGISTER_COORD, /* Register a Coordinator with GTM */ + MSG_UNREGISTER_COORD, /* Unregister a Coordinator with GTM */ + MSG_TXN_BEGIN, /* Start a new transaction */ + MSG_TXN_BEGIN_GETGXID, /* Start a new transaction and get GXID */ + MSG_TXN_BEGIN_GETGXID_MULTI, /* Start multiple new transactions and get GXIDs */ + MSG_TXN_PREPARE, /* Prepare a transation for commit */ + MSG_TXN_COMMIT, /* Commit a running or prepared transaction */ + MSG_TXN_COMMIT_MULTI, /* Commit multiple running or prepared transactions */ + MSG_TXN_ROLLBACK, /* Rollback a transaction */ + MSG_TXN_ROLLBACK_MULTI, /* Rollback multiple transactions */ + MSG_TXN_GET_GXID, /* Get a GXID for a transaction */ + MSG_SNAPSHOT_GET, /* Get a global snapshot */ + MSG_SNAPSHOT_GET_MULTI, /* Get multiple global snapshots */ + MSG_SNAPSHOT_GXID_GET, /* Get GXID and snapshot together */ + MSG_SEQUENCE_INIT, /* Initialize a new global sequence */ + MSG_SEQUENCE_GET_CURRENT,/* Get the current value of sequence */ + MSG_SEQUENCE_GET_NEXT, /* Get the next sequence value of sequence */ + MSG_SEQUENCE_RESET, /* Reset the sequence */ + MSG_SEQUENCE_CLOSE, /* Close a previously inited sequence */ + MSG_TXN_GET_STATUS, /* Get status of a given transaction */ + MSG_TXN_GET_ALL_PREPARED, /* Get information about all outstanding + * prepared transactions */ + MSG_TXN_BEGIN_GETGXID_AUTOVACUUM, /* Start a new transaction and get GXID for autovacuum */ + MSG_DATA_FLUSH, /* flush pending data */ + MSG_BACKEND_DISCONNECT, /* tell GTM that the backend diconnected from the proxy */ + + /* + * Must be at the end + */ + MSG_TYPE_COUNT /* A dummmy entry just to count the message types */ +} GTM_MessageType; + +typedef enum GTM_ResultType +{ + TXN_BEGIN_RESULT, + TXN_BEGIN_GETGXID_RESULT, + TXN_BEGIN_GETGXID_MULTI_RESULT, + TXN_PREPARE_RESULT, + TXN_COMMIT_RESULT, + TXN_COMMIT_MULTI_RESULT, + TXN_ROLLBACK_RESULT, + TXN_ROLLBACK_MULTI_RESULT, + TXN_GET_GXID_RESULT, + SNAPSHOT_GET_RESULT, + SNAPSHOT_GET_MULTI_RESULT, + SNAPSHOT_GXID_GET_RESULT, + SEQUENCE_INIT_RESULT, + SEQUENCE_GET_CURRENT_RESULT, + SEQUENCE_GET_NEXT_RESULT, + SEQUENCE_RESET_RESULT, + SEQUENCE_CLOSE_RESULT, + TXN_GET_STATUS_RESULT, + TXN_GET_ALL_PREPARED_RESULT, + TXN_BEGIN_GETGXID_AUTOVACUUM_RESULT, +} GTM_ResultType; + +/* + * Special message header for the messgaes exchanged between the GTM server and + * the proxy. + * + * ph_conid: connection identifier which is used to route + * the messages to the right backend. + */ +typedef struct GTM_ProxyMsgHeader +{ + GTMProxy_ConnID ph_conid; +} GTM_ProxyMsgHeader; + +#endif diff --git a/src/include/gtm/gtm_proxy.h b/src/include/gtm/gtm_proxy.h new file mode 100644 index 0000000000..8dc16bca0e --- /dev/null +++ b/src/include/gtm/gtm_proxy.h @@ -0,0 +1,221 @@ +/*------------------------------------------------------------------------- + * + * gtm_proxy.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#ifndef _GTM_PROXY_H +#define _GTM_PROXY_H + +#include <setjmp.h> +#include <poll.h> + +#include "gtm/gtm_c.h" +#include "gtm/palloc.h" +#include "gtm/gtm_lock.h" +#include "gtm/gtm_conn.h" +#include "gtm/elog.h" +#include "gtm/gtm_list.h" +#include "gtm/gtm_msg.h" +#include "gtm/libpq-fe.h" + +extern char *GTMProxyLogFile; + +typedef enum GTMProxy_ThreadStatus +{ + GTM_PROXY_THREAD_STARTING, + GTM_PROXY_THREAD_RUNNING, + GTM_PROXY_THREAD_EXITING, + /* Must be the last */ + GTM_PROXY_THREAD_INVALID +} GTMProxy_ThreadStatus; + +typedef struct GTMProxy_ConnectionInfo +{ + /* Port contains all the vital information about this connection */ + Port *con_port; + struct GTMProxy_ThreadInfo *con_thrinfo; + bool con_authenticated; + bool con_disconnected; + GTMProxy_ConnID con_id; + + GTM_MessageType con_pending_msg; + GlobalTransactionId con_txid; + GTM_TransactionHandle con_handle; +} GTMProxy_ConnectionInfo; + +typedef struct GTMProxy_Connections +{ + uint32 gc_conn_count; + uint32 gc_array_size; + GTMProxy_ConnectionInfo *gc_connections; + GTM_RWLock gc_lock; +} GTMProxy_Connections; + +#define ERRORDATA_STACK_SIZE 5 +#define GTM_PROXY_MAX_CONNECTIONS 1024 + +typedef struct GTMProxy_ThreadInfo +{ + /* + * Thread specific information such as connection(s) served by it + */ + GTM_ThreadID thr_id; + uint32 thr_localid; + void * (* thr_startroutine)(void *); + + MemoryContext thr_thread_context; + MemoryContext thr_message_context; + MemoryContext thr_current_context; + MemoryContext thr_error_context; + MemoryContext thr_parent_context; + + sigjmp_buf *thr_sigjmp_buf; + + ErrorData thr_error_data[ERRORDATA_STACK_SIZE]; + int thr_error_stack_depth; + int thr_error_recursion_depth; + int thr_criticalsec_count; + + GTMProxy_ThreadStatus thr_status; + GTMProxy_ConnectionInfo *thr_conn; /* Current active */ + + /* + * The structure member type/sequence upto this point must match the + * GTM_ThreadInfo structure in gtm.h since they are shared in some common + * library routines such as elog.c. Keeping them in sync helps us use the + * same library for the proxy as well as the server. + */ + GTM_MutexLock thr_lock; + GTM_CV thr_cv; + + /* + * We use a sequence number to track the state of connection/fd array. + * Whenever a new connection is added or an existing connection is deleted + * from the connection array, the sequence number is incremented. The + * thread main routine can then reconstruct the fd array again. + */ + int32 thr_seqno; + + /* number of connections served by this thread */ + uint32 thr_conn_count; + + /* connection array */ + GTMProxy_ConnectionInfo *thr_all_conns[GTM_PROXY_MAX_CONNECTIONS]; + struct pollfd thr_poll_fds[GTM_PROXY_MAX_CONNECTIONS]; + List *thr_processed_commands; + List *thr_pending_commands[MSG_TYPE_COUNT]; + + GTM_Conn *thr_gtm_conn; + +} GTMProxy_ThreadInfo; + +typedef struct GTMProxy_Threads +{ + uint32 gt_thread_count; + uint32 gt_array_size; + uint32 gt_next_worker; + GTMProxy_ThreadInfo **gt_threads; + GTM_RWLock gt_lock; +} GTMProxy_Threads; + +extern GTMProxy_Threads *GTMProxyThreads; + +int GTMProxy_ThreadAdd(GTMProxy_ThreadInfo *thrinfo); +int GTMProxy_ThreadRemove(GTMProxy_ThreadInfo *thrinfo); +int GTMProxy_ThreadJoin(GTMProxy_ThreadInfo *thrinfo); +void GTMProxy_ThreadExit(void); + +extern GTMProxy_ThreadInfo *GTMProxy_ThreadCreate(void *(* startroutine)(void *)); +extern GTMProxy_ThreadInfo * GTMProxy_GetThreadInfo(GTM_ThreadID thrid); +extern GTMProxy_ThreadInfo *GTMProxy_ThreadAddConnection(GTMProxy_ConnectionInfo *conninfo); +extern int GTMProxy_ThreadRemoveConnection(GTMProxy_ThreadInfo *thrinfo, + GTMProxy_ConnectionInfo *conninfo); + +/* + * Command data - the only relevant information right now is the XID + */ +typedef union GTMProxy_CommandData +{ + struct + { + bool rdonly; + GTM_IsolationLevel iso_level; + } cd_beg; + + struct + { + bool isgxid; + GlobalTransactionId gxid; + GTM_TransactionHandle handle; + } cd_rc; + + struct + { + bool isgxid; + GlobalTransactionId gxid; + GTM_TransactionHandle handle; + } cd_snap; +} GTMProxy_CommandData; + +/* + * Structures to be used for message proxing. There will be one such entry for + * each pending command from a backend. To keep it simple, we have a separate + * entry even if the commands are grouped together. + * + * An array of these entries is maintained which is sorted by the order in + * which the commands are sent to the GTM server. We expect the GTM server to + * respond back in the same order and the sorted array helps us in + * matching/confirming the responses. + */ +typedef struct GTMProxy_CommandInfo +{ + GTM_MessageType ci_mtype; + int ci_res_index; + GTMProxy_CommandData ci_data; + GTMProxy_ConnectionInfo *ci_conn; +} GTMProxy_CommandInfo; + +/* + * pthread keys to get thread specific information + */ +extern pthread_key_t threadinfo_key; +extern MemoryContext TopMostMemoryContext; +extern char *GTMLogFile; + +#define SetMyThreadInfo(thrinfo) pthread_setspecific(threadinfo_key, (thrinfo)) +#define GetMyThreadInfo ((GTMProxy_ThreadInfo *)pthread_getspecific(threadinfo_key)) + +#define TopMemoryContext (GetMyThreadInfo->thr_thread_context) +#define ThreadTopContext (GetMyThreadInfo->thr_thread_context) +#define MessageContext (GetMyThreadInfo->thr_message_context) +#define CurrentMemoryContext (GetMyThreadInfo->thr_current_context) +#define ErrorContext (GetMyThreadInfo->thr_error_context) +#define errordata (GetMyThreadInfo->thr_error_data) +#define recursion_depth (GetMyThreadInfo->thr_error_recursion_depth) +#define errordata_stack_depth (GetMyThreadInfo->thr_error_stack_depth) +#define CritSectionCount (GetMyThreadInfo->thr_criticalsec_count) + +#define PG_exception_stack (GetMyThreadInfo->thr_sigjmp_buf) +#define MyConnection (GetMyThreadInfo->thr_conn) +#define MyPort ((GetMyThreadInfo->thr_conn != NULL) ? \ + GetMyThreadInfo->thr_conn->con_port : \ + NULL) +#define MyThreadID (GetMyThreadInfo->thr_id) + +#define START_CRIT_SECTION() (CritSectionCount++) + +#define END_CRIT_SECTION() \ + do { \ + Assert(CritSectionCount > 0); \ + CritSectionCount--; \ + } while(0) + +#endif diff --git a/src/include/gtm/gtm_seq.h b/src/include/gtm/gtm_seq.h new file mode 100644 index 0000000000..6cb8cb3027 --- /dev/null +++ b/src/include/gtm/gtm_seq.h @@ -0,0 +1,75 @@ +/*------------------------------------------------------------------------- + * + * gtm_seq.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#ifndef GTM_SEQ_H +#define GTM_SEQ_H + +#include "gtm/stringinfo.h" + +/* Global sequence related structures */ + +typedef struct GTM_SeqInfo +{ + GTM_SequenceKey gs_key; + GTM_Sequence gs_value; + GTM_Sequence gs_init_value; + GTM_Sequence gs_increment_by; + GTM_Sequence gs_min_value; + GTM_Sequence gs_max_value; + bool gs_cycle; + bool gs_called; + + int32 gs_ref_count; + int32 gs_state; + GTM_RWLock gs_lock; +} GTM_SeqInfo; + +#define SEQ_STATE_ACTIVE 1 +#define SEQ_STATE_DELETED 2 + +#define SEQ_IS_ASCENDING(s) ((s)->gs_increment_by > 0) +#define SEQ_IS_CYCLE(s) ((s)->gs_cycle) +#define SEQ_IS_CALLED(s) ((s)->gs_called) + +#define SEQ_DEF_MAX_SEQVAL_ASCEND 0x7ffffffffffffffeLL +#define SEQ_DEF_MIN_SEQVAL_ASCEND 0x1 + +#define SEQ_DEF_MAX_SEQVAL_DESCEND -0x1 +#define SEQ_DEF_MIN_SEQVAL_DESCEND -0x7ffffffffffffffeLL + +#define SEQ_MAX_REFCOUNT 1024 + +/* SEQUENCE Management */ +void GTM_InitSeqManager(void); +int GTM_SeqOpen(GTM_SequenceKey seqkey, + GTM_Sequence increment_by, + GTM_Sequence minval, + GTM_Sequence maxval, + GTM_Sequence startval, + bool cycle); +int GTM_SeqClose(GTM_SequenceKey sqkey); +GTM_Sequence GTM_SeqGetNext(GTM_SequenceKey seqkey); +GTM_Sequence GTM_SeqGetCurrent(GTM_SequenceKey seqkey); +int GTM_SeqReset(GTM_SequenceKey seqkey); + + +void ProcessSequenceInitCommand(Port *myport, StringInfo message); +void ProcessSequenceGetCurrentCommand(Port *myport, StringInfo message); +void ProcessSequenceGetNextCommand(Port *myport, StringInfo message); +void ProcessSequenceResetCommand(Port *myport, StringInfo message); +void ProcessSequenceCloseCommand(Port *myport, StringInfo message); + +void GTM_SaveSeqInfo(int ctlfd); +void GTM_RestoreSeqInfo(int ctlfd); + +#endif diff --git a/src/include/gtm/gtm_txn.h b/src/include/gtm/gtm_txn.h new file mode 100644 index 0000000000..2d789463f7 --- /dev/null +++ b/src/include/gtm/gtm_txn.h @@ -0,0 +1,235 @@ +/*------------------------------------------------------------------------- + * + * gtm_txn.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#ifndef _GTM_TXN_H +#define _GTM_TXN_H + +#include "gtm/gtm_c.h" +#include "gtm/gtm_lock.h" +#include "gtm/gtm_list.h" +#include "gtm/stringinfo.h" + +/* ---------------- + * Special transaction ID values + * + * BootstrapGlobalTransactionId is the XID for "bootstrap" operations, and + * FrozenGlobalTransactionId is used for very old tuples. Both should + * always be considered valid. + * + * FirstNormalGlobalTransactionId is the first "normal" transaction id. + * Note: if you need to change it, you must change pg_class.h as well. + * ---------------- + */ +#define BootstrapGlobalTransactionId ((GlobalTransactionId) 1) +#define FrozenGlobalTransactionId ((GlobalTransactionId) 2) +#define FirstNormalGlobalTransactionId ((GlobalTransactionId) 3) +#define MaxGlobalTransactionId ((GlobalTransactionId) 0xFFFFFFFF) + +/* ---------------- + * transaction ID manipulation macros + * ---------------- + */ +#define GlobalTransactionIdIsNormal(xid) ((xid) >= FirstNormalGlobalTransactionId) +#define GlobalTransactionIdEquals(id1, id2) ((id1) == (id2)) +#define GlobalTransactionIdStore(xid, dest) (*(dest) = (xid)) +#define StoreInvalidGlobalTransactionId(dest) (*(dest) = InvalidGlobalTransactionId) + +/* advance a transaction ID variable, handling wraparound correctly */ +#define GlobalTransactionIdAdvance(dest) \ + do { \ + (dest)++; \ + if ((dest) < FirstNormalGlobalTransactionId) \ + (dest) = FirstNormalGlobalTransactionId; \ + } while(0) + +/* back up a transaction ID variable, handling wraparound correctly */ +#define GlobalTransactionIdRetreat(dest) \ + do { \ + (dest)--; \ + } while ((dest) < FirstNormalGlobalTransactionId) + +typedef int XidStatus; + +#define TRANSACTION_STATUS_IN_PROGRESS 0x00 +#define TRANSACTION_STATUS_COMMITTED 0x01 +#define TRANSACTION_STATUS_ABORTED 0x02 + +/* + * prototypes for functions in transam/transam.c + */ +extern bool GlobalTransactionIdDidCommit(GlobalTransactionId transactionId); +extern bool GlobalTransactionIdDidAbort(GlobalTransactionId transactionId); +extern void GlobalTransactionIdAbort(GlobalTransactionId transactionId); +extern bool GlobalTransactionIdPrecedes(GlobalTransactionId id1, GlobalTransactionId id2); +extern bool GlobalTransactionIdPrecedesOrEquals(GlobalTransactionId id1, GlobalTransactionId id2); +extern bool GlobalTransactionIdFollows(GlobalTransactionId id1, GlobalTransactionId id2); +extern bool GlobalTransactionIdFollowsOrEquals(GlobalTransactionId id1, GlobalTransactionId id2); + +/* in transam/varsup.c */ +extern GlobalTransactionId GTM_GetGlobalTransactionId(GTM_TransactionHandle handle); +extern GlobalTransactionId GTM_GetGlobalTransactionIdMulti(GTM_TransactionHandle handle[], int txn_count); +extern GlobalTransactionId ReadNewGlobalTransactionId(void); +extern void SetGlobalTransactionIdLimit(GlobalTransactionId oldest_datfrozenxid); +extern void SetNextGlobalTransactionId(GlobalTransactionId gxid); +extern void GTM_SetShuttingDown(void); + +typedef enum GTM_States +{ + GTM_STARTING, + GTM_RUNNING, + GTM_SHUTTING_DOWN +} GTM_States; + +/* Global transaction states at the GTM */ +typedef enum GTM_TransactionStates +{ + GTM_TXN_STARTING, + GTM_TXN_IN_PROGRESS, + GTM_TXN_PREPARE_IN_PROGRESS, + GTM_TXN_PREPARED, + GTM_TXN_COMMIT_IN_PROGRESS, + GTM_TXN_COMMITTED, + GTM_TXN_ABORT_IN_PROGRESS, + GTM_TXN_ABORTED +} GTM_TransactionStates; + +typedef struct GTM_TransactionInfo +{ + GTM_TransactionHandle gti_handle; + GTM_ThreadID gti_thread_id; + + bool gti_in_use; + GlobalTransactionId gti_gxid; + GTM_TransactionStates gti_state; + PGXC_NodeId gti_coordid; + GlobalTransactionId gti_xmin; + GTM_IsolationLevel gti_isolevel; + bool gti_readonly; + GTMProxy_ConnID gti_backend_id; + uint32 gti_nodecount; + PGXC_NodeId *gti_nodes; + + GTM_SnapshotData gti_current_snapshot; + bool gti_snapshot_set; + + GTM_RWLock gti_lock; + bool gti_vacuum; +} GTM_TransactionInfo; + +#define GTM_MAX_2PC_NODES 16 +#define GTM_CheckTransactionHandle(x) ((x) >= 0 && (x) < GTM_MAX_GLOBAL_TRANSACTIONS) +#define GTM_IsTransSerializable(x) ((x)->gti_isolevel == GTM_ISOLATION_SERIALIZABLE) + +typedef struct GTM_Transactions +{ + uint32 gt_txn_count; + GTM_States gt_gtm_state; + + GTM_RWLock gt_XidGenLock; + + /* + * These fields are protected by XidGenLock + */ + GlobalTransactionId gt_nextXid; /* next XID to assign */ + + GlobalTransactionId gt_oldestXid; /* cluster-wide minimum datfrozenxid */ + GlobalTransactionId gt_xidVacLimit; /* start forcing autovacuums here */ + GlobalTransactionId gt_xidWarnLimit; /* start complaining here */ + GlobalTransactionId gt_xidStopLimit; /* refuse to advance nextXid beyond here */ + GlobalTransactionId gt_xidWrapLimit; /* where the world ends */ + + /* + * These fields are protected by TransArrayLock. + */ + GlobalTransactionId gt_latestCompletedXid; /* newest XID that has committed or + * aborted */ + + GlobalTransactionId gt_recent_global_xmin; + + int32 gt_lastslot; + GTM_TransactionInfo gt_transactions_array[GTM_MAX_GLOBAL_TRANSACTIONS]; + List *gt_open_transactions; + + GTM_RWLock gt_TransArrayLock; +} GTM_Transactions; + +extern GTM_Transactions GTMTransactions; + +#define GTM_CountOpenTransactions() (list_length(GTMTransactions.gt_open_transactions)) + +/* + * Two hash tables will be maintained to quickly find the + * GTM_TransactionInfo block given either the GXID or the GTM_TransactionHandle. + */ + +GTM_TransactionInfo *GTM_HandleToTransactionInfo(GTM_TransactionHandle handle); +GTM_TransactionHandle GTM_GXIDToHandle(GlobalTransactionId gxid); + +/* Transaction Control */ +void GTM_InitTxnManager(void); +GTM_TransactionHandle GTM_BeginTransaction(GTM_CoordinatorId coord_id, + GTM_IsolationLevel isolevel, + bool readonly); +int GTM_BeginTransactionMulti(GTM_CoordinatorId coord_id, + GTM_IsolationLevel isolevel[], + bool readonly[], + GTMProxy_ConnID connid[], + int txn_count, + GTM_TransactionHandle txns[]); +int GTM_RollbackTransaction(GTM_TransactionHandle txn); +int GTM_RollbackTransactionMulti(GTM_TransactionHandle txn[], int txn_count, int status[]); +int GTM_RollbackTransactionGXID(GlobalTransactionId gxid); +int GTM_CommitTransaction(GTM_TransactionHandle txn); +int GTM_CommitTransactionMulti(GTM_TransactionHandle txn[], int txn_count, int status[]); +int GTM_CommitTransactionGXID(GlobalTransactionId gxid); +int GTM_PrepareTransaction(GTM_TransactionHandle txn, + uint32 nodecnt, + PGXC_NodeId nodes[]); +int GTM_PrepareTransactionGXID(GlobalTransactionId gxid, + uint32 nodecnt, + PGXC_NodeId nodes[]); +uint32 GTM_GetAllPrepared(GlobalTransactionId gxids[], uint32 gxidcnt); +GTM_TransactionStates GTM_GetStatus(GTM_TransactionHandle txn); +GTM_TransactionStates GTM_GetStatusGXID(GlobalTransactionId gxid); +int GTM_GetAllTransactions(GTM_TransactionInfo txninfo[], uint32 txncnt); +void GTM_RemoveAllTransInfos(int backend_id); + +GTM_Snapshot GTM_GetSnapshotData(GTM_TransactionInfo *my_txninfo, + GTM_Snapshot snapshot); +GTM_Snapshot GTM_GetTransactionSnapshot(GTM_TransactionHandle handle[], + int txn_count, int *status); +void GTM_FreeCachedTransInfo(void); + +void ProcessBeginTransactionCommand(Port *myport, StringInfo message); +void ProcessBeginTransactionCommandMulti(Port *myport, StringInfo message); +void ProcessBeginTransactionGetGXIDCommand(Port *myport, StringInfo message); +void ProcessCommitTransactionCommand(Port *myport, StringInfo message); +void ProcessRollbackTransactionCommand(Port *myport, StringInfo message); +void ProcessPrepareTransactionCommand(Port *myport, StringInfo message); +void ProcessGetGXIDTransactionCommand(Port *myport, StringInfo message); + +void ProcessBeginTransactionGetGXIDAutovacuumCommand(Port *myport, StringInfo message); +void ProcessBeginTransactionGetGXIDCommandMulti(Port *myport, StringInfo message); +void ProcessCommitTransactionCommandMulti(Port *myport, StringInfo message); +void ProcessRollbackTransactionCommandMulti(Port *myport, StringInfo message) ; + +void GTM_SaveTxnInfo(int ctlfd); +void GTM_RestoreTxnInfo(int ctlfd, GlobalTransactionId next_gxid); + +/* + * In gtm_snap.c + */ +void ProcessGetSnapshotCommand(Port *myport, StringInfo message, bool get_gxid); +void ProcessGetSnapshotCommandMulti(Port *myport, StringInfo message); +void GTM_FreeSnapshotData(GTM_Snapshot snapshot); +#endif diff --git a/src/include/gtm/ip.h b/src/include/gtm/ip.h new file mode 100644 index 0000000000..c5d975298b --- /dev/null +++ b/src/include/gtm/ip.h @@ -0,0 +1,50 @@ +/*------------------------------------------------------------------------- + * + * ip.h + * Definitions for IPv6-aware network access. + * + * These definitions are used by both frontend and backend code. Be careful + * what you include here! + * + * Copyright (c) 2003-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/libpq/ip.h,v 1.20 2008/01/01 19:45:58 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef IP_H +#define IP_H + +#include "gtm/pqcomm.h" + + +extern int pg_getaddrinfo_all(const char *hostname, const char *servname, + const struct addrinfo * hintp, + struct addrinfo ** result); +extern void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo * ai); + +extern int pg_getnameinfo_all(const struct sockaddr_storage * addr, int salen, + char *node, int nodelen, + char *service, int servicelen, + int flags); + +extern int pg_range_sockaddr(const struct sockaddr_storage * addr, + const struct sockaddr_storage * netaddr, + const struct sockaddr_storage * netmask); + +extern int pg_sockaddr_cidr_mask(struct sockaddr_storage * mask, + char *numbits, int family); + +#ifdef HAVE_IPV6 +extern void pg_promote_v4_to_v6_addr(struct sockaddr_storage * addr); +extern void pg_promote_v4_to_v6_mask(struct sockaddr_storage * addr); +#endif + +#ifdef HAVE_UNIX_SOCKETS +#define IS_AF_UNIX(fam) ((fam) == AF_UNIX) +#else +#define IS_AF_UNIX(fam) (0) +#endif + +#endif /* IP_H */ diff --git a/src/include/gtm/libpq-be.h b/src/include/gtm/libpq-be.h new file mode 100644 index 0000000000..0a795def67 --- /dev/null +++ b/src/include/gtm/libpq-be.h @@ -0,0 +1,86 @@ +/*------------------------------------------------------------------------- + * + * libpq_be.h + * This file contains definitions for structures and externs used + * by the postmaster during client authentication. + * + * Note that this is backend-internal and is NOT exported to clients. + * Structs that need to be client-visible are in pqcomm.h. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/libpq/libpq-be.h,v 1.69 2009/01/01 17:23:59 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef LIBPQ_BE_H +#define LIBPQ_BE_H + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif + +#include "gtm/pqcomm.h" + +/* + * This is used by the postmaster in its communication with frontends. It + * contains all state information needed during this communication before the + * backend is run. The Port structure is kept in malloc'd memory and is + * still available when a backend is running (see MyProcPort). The data + * it points to must also be malloc'd, or else palloc'd in TopMostMemoryContext, + * so that it survives into GTM_ThreadMain execution! + */ + +typedef struct Port +{ + int sock; /* File descriptor */ + SockAddr laddr; /* local addr (postmaster) */ + SockAddr raddr; /* remote addr (client) */ + char *remote_host; /* name (or ip addr) of remote host */ + char *remote_port; /* text rep of remote port */ + + GTMProxy_ConnID conn_id; /* RequestID of this command */ + + GTM_CoordinatorId coordinator_id; /* Coordinator ID */ + bool is_proxy; /* Is this a connection from GTM proxy ? */ +#define PQ_BUFFER_SIZE 8192 + + char PqSendBuffer[PQ_BUFFER_SIZE]; + int PqSendPointer; /* Next index to store a byte in PqSendBuffer */ + + char PqRecvBuffer[PQ_BUFFER_SIZE]; + int PqRecvPointer; /* Next index to read a byte from PqRecvBuffer */ + int PqRecvLength; /* End of data available in PqRecvBuffer */ + + /* + * TCP keepalive settings. + * + * default values are 0 if AF_UNIX or not yet known; current values are 0 + * if AF_UNIX or using the default. Also, -1 in a default value means we + * were unable to find out the default (getsockopt failed). + */ + int default_keepalives_idle; + int default_keepalives_interval; + int default_keepalives_count; + int keepalives_idle; + int keepalives_interval; + int keepalives_count; +} Port; + +/* TCP keepalives configuration. These are no-ops on an AF_UNIX socket. */ + +extern int pq_getkeepalivesidle(Port *port); +extern int pq_getkeepalivesinterval(Port *port); +extern int pq_getkeepalivescount(Port *port); + +extern int pq_setkeepalivesidle(int idle, Port *port); +extern int pq_setkeepalivesinterval(int interval, Port *port); +extern int pq_setkeepalivescount(int count, Port *port); + +#endif /* LIBPQ_BE_H */ diff --git a/src/include/gtm/libpq-fe.h b/src/include/gtm/libpq-fe.h new file mode 100644 index 0000000000..2c5c2c4e04 --- /dev/null +++ b/src/include/gtm/libpq-fe.h @@ -0,0 +1,138 @@ +/*------------------------------------------------------------------------- + * + * libpq-fe.h + * This file contains definitions for structures and + * externs for functions used by frontend postgres applications. + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-fe.h,v 1.145 2009/01/01 17:24:03 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + +#ifndef LIBPQ_FE_H +#define LIBPQ_FE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdio.h> + +/* + * postgres_ext.h defines the backend's externally visible types, + * such as Oid. + */ +#include "gtm/gtm_ext.h" + +/* + * Option flags for PQcopyResult + */ +#define PG_COPYRES_ATTRS 0x01 +#define PG_COPYRES_TUPLES 0x02 /* Implies PG_COPYRES_ATTRS */ +#define PG_COPYRES_EVENTS 0x04 +#define PG_COPYRES_NOTICEHOOKS 0x08 + +/* Application-visible enum types */ + +typedef enum +{ + /* + * Although it is okay to add to this list, values which become unused + * should never be removed, nor should constants be redefined - that would + * break compatibility with existing code. + */ + CONNECTION_OK, + CONNECTION_BAD, + /* Non-blocking mode only below here */ + + /* + * The existence of these should never be relied upon - they should only + * be used for user feedback or similar purposes. + */ + CONNECTION_STARTED, /* Waiting for connection to be made. */ + CONNECTION_MADE, /* Connection OK; waiting to send. */ + CONNECTION_AWAITING_RESPONSE, /* Waiting for a response from the + * postmaster. */ + CONNECTION_AUTH_OK, /* Received authentication; waiting for + * backend startup. */ + CONNECTION_SETENV, /* Negotiating environment. */ + CONNECTION_SSL_STARTUP, /* Negotiating SSL. */ + CONNECTION_NEEDED /* Internal state: connect() needed */ +} ConnStatusType; + +typedef enum +{ + PGRES_POLLING_FAILED = 0, + PGRES_POLLING_READING, /* These two indicate that one may */ + PGRES_POLLING_WRITING, /* use select before polling again. */ + PGRES_POLLING_OK, + PGRES_POLLING_ACTIVE /* unused; keep for awhile for backwards + * compatibility */ +} GTMClientPollingStatusType; + +/* ---------------- + * Structure for the conninfo parameter definitions returned by PQconndefaults + * or GTMPQconninfoParse. + * + * All fields except "val" point at static strings which must not be altered. + * "val" is either NULL or a malloc'd current-value string. GTMPQconninfoFree() + * will release both the val strings and the GTMPQconninfoOption array itself. + * ---------------- + */ +typedef struct _GTMPQconninfoOption +{ + char *keyword; /* The keyword of the option */ + char *val; /* Option's current value, or NULL */ +} GTMPQconninfoOption; + +typedef struct gtm_conn GTM_Conn; + +/* ---------------- + * Exported functions of libpq + * ---------------- + */ + +/* === in fe-connect.c === */ + +/* make a new client connection to the backend */ +/* Asynchronous (non-blocking) */ +extern GTM_Conn *PQconnectGTMStart(const char *conninfo); +extern GTMClientPollingStatusType GTMPQconnectPoll(GTM_Conn *conn); + +/* Synchronous (blocking) */ +extern GTM_Conn *PQconnectGTM(const char *conninfo); + +/* close the current connection and free the GTM_Conn data structure */ +extern void GTMPQfinish(GTM_Conn *conn); + +/* parse connection options in same way as PQconnectGTM */ +extern GTMPQconninfoOption *GTMPQconninfoParse(const char *conninfo, char **errmsg); + +/* free the data structure returned by PQconndefaults() or GTMPQconninfoParse() */ +extern void GTMPQconninfoFree(GTMPQconninfoOption *connOptions); + +extern char *GTMPQhost(const GTM_Conn *conn); +extern char *GTMPQport(const GTM_Conn *conn); +extern ConnStatusType GTMPQstatus(const GTM_Conn *conn); +extern char *GTMPQerrorMessage(const GTM_Conn *conn); +extern int GTMPQsocket(const GTM_Conn *conn); + +/* Enable/disable tracing */ +extern void GTMPQtrace(GTM_Conn *conn, FILE *debug_port); +extern void GTMPQuntrace(GTM_Conn *conn); + +/* Force the write buffer to be written (or at least try) */ +extern int PQflush(GTM_Conn *conn); + +#define libpq_gettext(x) x + +#ifdef __cplusplus +} +#endif + +#endif /* LIBPQ_FE_H */ diff --git a/src/include/gtm/libpq-int.h b/src/include/gtm/libpq-int.h new file mode 100644 index 0000000000..5956de8ff2 --- /dev/null +++ b/src/include/gtm/libpq-int.h @@ -0,0 +1,129 @@ +/*------------------------------------------------------------------------- + * + * libpq-int.h + * This file contains internal definitions meant to be used only by + * the frontend libpq library, not by applications that call it. + * + * An application can include this file if it wants to bypass the + * official API defined by libpq-fe.h, but code that does so is much + * more likely to break across PostgreSQL releases than code that uses + * only the official API. + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.139 2009/01/01 17:24:03 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + +#ifndef LIBPQ_INT_H +#define LIBPQ_INT_H + +#include <time.h> +#include <sys/types.h> +#include <sys/time.h> +#include "gtm/pqcomm.h" +#include "gtm/pqexpbuffer.h" +#include "gtm/gtm_client.h" + +/* + * GTM_Conn stores all the state data associated with a single connection + * to a backend. + */ +struct gtm_conn +{ + /* Saved values of connection options */ + char *pghost; /* the machine on which the server is running */ + char *pghostaddr; /* the IPv4 address of the machine on which + * the server is running, in IPv4 + * numbers-and-dots notation. Takes precedence + * over above. */ + char *pgport; /* the server's communication port */ + char *connect_timeout; /* connection timeout (numeric string) */ + char *coordinator_id; /* coordinator id */ + int is_proxy; /* is this a connection to/from a proxy ? */ + + /* Optional file to write trace info to */ + FILE *Pfdebug; + + /* Status indicators */ + ConnStatusType status; + + /* Connection data */ + int sock; /* Unix FD for socket, -1 if not connected */ + SockAddr laddr; /* Local address */ + SockAddr raddr; /* Remote address */ + + /* Transient state needed while establishing connection */ + struct addrinfo *addrlist; /* list of possible backend addresses */ + struct addrinfo *addr_cur; /* the one currently being tried */ + int addrlist_family; /* needed to know how to free addrlist */ + + /* Buffer for data received from backend and not yet processed */ + char *inBuffer; /* currently allocated buffer */ + int inBufSize; /* allocated size of buffer */ + int inStart; /* offset to first unconsumed data in buffer */ + int inCursor; /* next byte to tentatively consume */ + int inEnd; /* offset to first position after avail data */ + + /* Buffer for data not yet sent to backend */ + char *outBuffer; /* currently allocated buffer */ + int outBufSize; /* allocated size of buffer */ + int outCount; /* number of chars waiting in buffer */ + + /* State for constructing messages in outBuffer */ + int outMsgStart; /* offset to msg start (length word); if -1, + * msg has no length word */ + int outMsgEnd; /* offset to msg end (so far) */ + + /* Buffer for current error message */ + PQExpBufferData errorMessage; /* expansible string */ + + /* Buffer for receiving various parts of messages */ + PQExpBufferData workBuffer; /* expansible string */ + + /* Pointer to the result of last operation */ + GTM_Result *result; +}; + +/* === in fe-misc.c === */ + + /* + * "Get" and "Put" routines return 0 if successful, EOF if not. Note that for + * Get, EOF merely means the buffer is exhausted, not that there is + * necessarily any error. + */ +extern int gtmpqCheckOutBufferSpace(size_t bytes_needed, GTM_Conn *conn); +extern int gtmpqCheckInBufferSpace(size_t bytes_needed, GTM_Conn *conn); +extern int gtmpqGetc(char *result, GTM_Conn *conn); +extern int gtmpqPutc(char c, GTM_Conn *conn); +extern int gtmpqGets(PQExpBuffer buf, GTM_Conn *conn); +extern int gtmpqGets_append(PQExpBuffer buf, GTM_Conn *conn); +extern int gtmpqPuts(const char *s, GTM_Conn *conn); +extern int gtmpqGetnchar(char *s, size_t len, GTM_Conn *conn); +extern int gtmpqPutnchar(const char *s, size_t len, GTM_Conn *conn); +extern int gtmpqGetInt(int *result, size_t bytes, GTM_Conn *conn); +extern int gtmpqPutInt(int value, size_t bytes, GTM_Conn *conn); +extern int gtmpqPutMsgStart(char msg_type, bool force_len, GTM_Conn *conn); +extern int gtmpqPutMsgEnd(GTM_Conn *conn); +extern int gtmpqReadData(GTM_Conn *conn); +extern int gtmpqFlush(GTM_Conn *conn); +extern int gtmpqWait(int forRead, int forWrite, GTM_Conn *conn); +extern int gtmpqWaitTimed(int forRead, int forWrite, GTM_Conn *conn, + time_t finish_time); +extern int gtmpqReadReady(GTM_Conn *conn); +extern int gtmpqWriteReady(GTM_Conn *conn); + +/* + * In fe-protocol.c + */ +GTM_Result * GTMPQgetResult(GTM_Conn *conn); +extern int gtmpqGetError(GTM_Conn *conn, GTM_Result *result); +void gtmpqFreeResultData(GTM_Result *result, bool is_proxy); + +#define SOCK_ERRNO errno +#define SOCK_ERRNO_SET(e) (errno = (e)) + +#endif /* LIBPQ_INT_H */ diff --git a/src/include/gtm/libpq.h b/src/include/gtm/libpq.h new file mode 100644 index 0000000000..29621a43c4 --- /dev/null +++ b/src/include/gtm/libpq.h @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------------- + * + * libpq.h + * POSTGRES LIBPQ buffer structure definitions. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/libpq/libpq.h,v 1.70 2008/11/20 09:29:36 mha Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef LIBPQ_H +#define LIBPQ_H + +#include <sys/types.h> +#include <netinet/in.h> + +#include "gtm/stringinfo.h" +#include "gtm/libpq-be.h" + +/* + * External functions. + */ + +/* + * prototypes for functions in pqcomm.c + */ +extern int StreamServerPort(int family, char *hostName, + unsigned short portNumber, int ListenSocket[], + int MaxListen); +extern int StreamConnection(int server_fd, Port *port); +extern void StreamClose(int sock); +extern void TouchSocketFile(void); +extern void pq_comm_reset(void); +extern int pq_getbytes(Port *myport, char *s, size_t len); +extern int pq_getstring(Port *myport, StringInfo s); +extern int pq_getmessage(Port *myport, StringInfo s, int maxlen); +extern int pq_getbyte(Port *myport); +extern int pq_peekbyte(Port *myport); +extern int pq_putbytes(Port *myport, const char *s, size_t len); +extern int pq_flush(Port *myport); +extern int pq_putmessage(Port *myport, char msgtype, const char *s, size_t len); + +#endif /* LIBPQ_H */ diff --git a/src/include/gtm/memnodes.h b/src/include/gtm/memnodes.h new file mode 100644 index 0000000000..dea51b2bbd --- /dev/null +++ b/src/include/gtm/memnodes.h @@ -0,0 +1,79 @@ +/*------------------------------------------------------------------------- + * + * memnodes.h + * POSTGRES memory context node definitions. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/nodes/memnodes.h,v 1.34 2008/01/01 19:45:58 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef MEMNODES_H +#define MEMNODES_H + +#include "gtm/gtm_lock.h" + +/* + * MemoryContext + * A logical context in which memory allocations occur. + * + * MemoryContext itself is an abstract type that can have multiple + * implementations, though for now we have only AllocSetContext. + * The function pointers in MemoryContextMethods define one specific + * implementation of MemoryContext --- they are a virtual function table + * in C++ terms. + * + * Note: for largely historical reasons, typedef MemoryContext is a pointer + * to the context struct rather than the struct type itself. + */ + +typedef struct MemoryContextMethods +{ + void *(*alloc) (MemoryContext context, Size size); + /* call this free_p in case someone #define's free() */ + void (*free_p) (MemoryContext context, void *pointer); + void *(*realloc) (MemoryContext context, void *pointer, Size size); + void (*init) (MemoryContext context); + void (*reset) (MemoryContext context); + void (*delete) (MemoryContext context); + Size (*get_chunk_space) (MemoryContext context, void *pointer); + bool (*is_empty) (MemoryContext context); + void (*stats) (MemoryContext context, int level); +#ifdef MEMORY_CONTEXT_CHECKING + void (*check) (MemoryContext context); +#endif +} MemoryContextMethods; + + +typedef struct MemoryContextData +{ + MemoryContextMethods *methods; /* virtual function table */ + MemoryContext parent; /* NULL if no parent (toplevel context) */ + MemoryContext firstchild; /* head of linked list of children */ + MemoryContext nextchild; /* next child of same parent */ + char *name; /* context name (just for debugging) */ + bool is_shared; /* context is shared by threads */ + GTM_RWLock lock; /* lock to protect members if the context is shared */ +} MemoryContextData; + +#define MemoryContextIsShared(context) \ + (((MemoryContextData *)(context))->is_shared) + +#define MemoryContextLock(context) \ + (GTM_RWLockAcquire(&((MemoryContextData *)(context))->lock, GTM_LOCKMODE_WRITE)) +#define MemoryContextUnlock(context) \ + (GTM_RWLockRelease(&((MemoryContextData *)(context))->lock)) +/* + * MemoryContextIsValid + * True iff memory context is valid. + * + * Add new context types to the set accepted by this macro. + */ +#define MemoryContextIsValid(context) \ + ((context) != NULL) + +#endif /* MEMNODES_H */ diff --git a/src/include/gtm/memutils.h b/src/include/gtm/memutils.h new file mode 100644 index 0000000000..5d89995d4d --- /dev/null +++ b/src/include/gtm/memutils.h @@ -0,0 +1,123 @@ +/*------------------------------------------------------------------------- + * + * memutils.h + * This file contains declarations for memory allocation utility + * functions. These are functions that are not quite widely used + * enough to justify going in utils/palloc.h, but are still part + * of the API of the memory management subsystem. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/utils/memutils.h,v 1.64 2008/01/01 19:45:59 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef MEMUTILS_H +#define MEMUTILS_H + +#include "gtm/gtm_c.h" +#include "gtm/palloc.h" +#include "gtm/memnodes.h" + +/* + * MaxAllocSize + * Quasi-arbitrary limit on size of allocations. + * + * Note: + * There is no guarantee that allocations smaller than MaxAllocSize + * will succeed. Allocation requests larger than MaxAllocSize will + * be summarily denied. + * + * XXX This is deliberately chosen to correspond to the limiting size + * of varlena objects under TOAST. See VARATT_MASK_SIZE in postgres.h. + * + * XXX Also, various places in aset.c assume they can compute twice an + * allocation's size without overflow, so beware of raising this. + */ +#define MaxAllocSize ((Size) 0x3fffffff) /* 1 gigabyte - 1 */ + +#define AllocSizeIsValid(size) ((Size) (size) <= MaxAllocSize) + +/* + * All chunks allocated by any memory context manager are required to be + * preceded by a StandardChunkHeader at a spacing of STANDARDCHUNKHEADERSIZE. + * A currently-allocated chunk must contain a backpointer to its owning + * context as well as the allocated size of the chunk. The backpointer is + * used by pfree() and repalloc() to find the context to call. The allocated + * size is not absolutely essential, but it's expected to be needed by any + * reasonable implementation. + */ +typedef struct StandardChunkHeader +{ + MemoryContext context; /* owning context */ + Size size; /* size of data space allocated in chunk */ +#ifdef MEMORY_CONTEXT_CHECKING + /* when debugging memory usage, also store actual requested size */ + Size requested_size; +#endif +} StandardChunkHeader; + +#define STANDARDCHUNKHEADERSIZE MAXALIGN(sizeof(StandardChunkHeader)) + +/* + * Memory-context-type-independent functions in mcxt.c + */ +extern void MemoryContextInit(void); +extern void MemoryContextReset(MemoryContext context); +extern void MemoryContextDelete(MemoryContext context); +extern void MemoryContextResetChildren(MemoryContext context); +extern void MemoryContextDeleteChildren(MemoryContext context); +extern void MemoryContextResetAndDeleteChildren(MemoryContext context); +extern Size GetMemoryChunkSpace(void *pointer); +extern MemoryContext GetMemoryChunkContext(void *pointer); +extern bool MemoryContextIsEmpty(MemoryContext context); +extern void MemoryContextStats(MemoryContext context); + +#ifdef MEMORY_CONTEXT_CHECKING +extern void MemoryContextCheck(MemoryContext context); +#endif +extern bool MemoryContextContains(MemoryContext context, void *pointer); + +/* + * This routine handles the context-type-independent part of memory + * context creation. It's intended to be called from context-type- + * specific creation routines, and noplace else. + */ +extern MemoryContext MemoryContextCreate(Size size, + MemoryContextMethods *methods, + MemoryContext parent, + const char *name); + + +/* + * Memory-context-type-specific functions + */ + +/* aset.c */ +extern MemoryContext AllocSetContextCreate(MemoryContext parent, + const char *name, + Size minContextSize, + Size initBlockSize, + Size maxBlockSize, + bool isShared); + +/* + * Recommended default alloc parameters, suitable for "ordinary" contexts + * that might hold quite a lot of data. + */ +#define ALLOCSET_DEFAULT_MINSIZE 0 +#define ALLOCSET_DEFAULT_INITSIZE (8 * 1024) +#define ALLOCSET_DEFAULT_MAXSIZE (8 * 1024 * 1024) + +/* + * Recommended alloc parameters for "small" contexts that are not expected + * to contain much data (for example, a context to contain a query plan). + */ +#define ALLOCSET_SMALL_MINSIZE 0 +#define ALLOCSET_SMALL_INITSIZE (1 * 1024) +#define ALLOCSET_SMALL_MAXSIZE (8 * 1024) + +#endif /* MEMUTILS_H */ diff --git a/src/include/gtm/palloc.h b/src/include/gtm/palloc.h new file mode 100644 index 0000000000..380e280694 --- /dev/null +++ b/src/include/gtm/palloc.h @@ -0,0 +1,90 @@ +/*------------------------------------------------------------------------- + * + * palloc.h + * POSTGRES memory allocator definitions. + * + * This file contains the basic memory allocation interface that is + * needed by almost every backend module. It is included directly by + * postgres.h, so the definitions here are automatically available + * everywhere. Keep it lean! + * + * Memory allocation occurs within "contexts". Every chunk obtained from + * palloc()/MemoryContextAlloc() is allocated within a specific context. + * The entire contents of a context can be freed easily and quickly by + * resetting or deleting the context --- this is both faster and less + * prone to memory-leakage bugs than releasing chunks individually. + * We organize contexts into context trees to allow fine-grain control + * over chunk lifetime while preserving the certainty that we will free + * everything that should be freed. See utils/mmgr/README for more info. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/utils/palloc.h,v 1.40 2008/06/28 16:45:22 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef PALLOC_H +#define PALLOC_H + +/* + * Type MemoryContextData is declared in nodes/memnodes.h. Most users + * of memory allocation should just treat it as an abstract type, so we + * do not provide the struct contents here. + */ +typedef struct MemoryContextData *MemoryContext; + +/* + * Fundamental memory-allocation operations (more are in utils/memutils.h) + */ +extern void *MemoryContextAlloc(MemoryContext context, Size size); +extern void *MemoryContextAllocZero(MemoryContext context, Size size); +extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size); + +#define palloc(sz) MemoryContextAlloc(CurrentMemoryContext, (sz)) + +#define palloc0(sz) MemoryContextAllocZero(CurrentMemoryContext, (sz)) + +/* + * The result of palloc() is always word-aligned, so we can skip testing + * alignment of the pointer when deciding which MemSet variant to use. + * Note that this variant does not offer any advantage, and should not be + * used, unless its "sz" argument is a compile-time constant; therefore, the + * issue that it evaluates the argument multiple times isn't a problem in + * practice. + */ +#define palloc0fast(sz) \ + ( MemSetTest(0, sz) ? \ + MemoryContextAllocZeroAligned(CurrentMemoryContext, sz) : \ + MemoryContextAllocZero(CurrentMemoryContext, sz) ) + +extern void pfree(void *pointer); + +extern void *repalloc(void *pointer, Size size); + +/* + * MemoryContextSwitchTo can't be a macro in standard C compilers. + * But we can make it an inline function when using GCC. + */ + +extern MemoryContext MemoryContextSwitchTo(MemoryContext context); + +/* + * These are like standard strdup() except the copied string is + * allocated in a context, not with malloc(). + */ +extern char *MemoryContextStrdup(MemoryContext context, const char *string); + +#define pstrdup(str) MemoryContextStrdup(CurrentMemoryContext, (str)) + +extern char *pnstrdup(const char *in, Size len); + +#if defined(WIN32) || defined(__CYGWIN__) +extern void *pgport_palloc(Size sz); +extern char *pgport_pstrdup(const char *str); +extern void pgport_pfree(void *pointer); +#endif + +#endif /* PALLOC_H */ diff --git a/src/include/gtm/path.h b/src/include/gtm/path.h new file mode 100644 index 0000000000..624fd183c9 --- /dev/null +++ b/src/include/gtm/path.h @@ -0,0 +1,16 @@ +/*------------------------------------------------------------------------- + * + * path.h + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL$ + * + *------------------------------------------------------------------------- + */ +#include "gtm/gtm_c.h" + +extern void canonicalize_path(char *path); diff --git a/src/include/gtm/pqcomm.h b/src/include/gtm/pqcomm.h new file mode 100644 index 0000000000..cdae6ca284 --- /dev/null +++ b/src/include/gtm/pqcomm.h @@ -0,0 +1,57 @@ +/*------------------------------------------------------------------------- + * + * pqcomm.h + * Definitions common to frontends and backends. + * + * NOTE: for historical reasons, this does not correspond to pqcomm.c. + * pqcomm.c's routines are declared in libpq.h. + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/libpq/pqcomm.h,v 1.109 2008/10/28 12:10:44 mha Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef PQCOMM_H +#define PQCOMM_H + +#include <sys/socket.h> +#include <netdb.h> +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif +#include <netinet/in.h> + +typedef struct +{ + struct sockaddr_storage addr; + size_t salen; +} SockAddr; + +/* Configure the UNIX socket location for the well known port. */ + +#define UNIXSOCK_PATH(path, port, sockdir) \ + snprintf(path, sizeof(path), "%s/.s.PGSQL.%d", \ + ((sockdir) && *(sockdir) != '\0') ? (sockdir) : \ + DEFAULT_PGSOCKET_DIR, \ + (port)) + +/* + * Packet lengths are 4 bytes in network byte order. + * + * The initial length is omitted from the packet layouts appearing below. + */ + +typedef uint32 PacketLen; + +/* + * In protocol 3.0 and later, the startup packet length is not fixed, but + * we set an arbitrary limit on it anyway. This is just to prevent simple + * denial-of-service attacks via sending enough data to run the server + * out of memory. + */ +#define MAX_STARTUP_PACKET_LENGTH 10000 + +#endif /* PQCOMM_H */ diff --git a/src/include/gtm/pqexpbuffer.h b/src/include/gtm/pqexpbuffer.h new file mode 100644 index 0000000000..7ae0411423 --- /dev/null +++ b/src/include/gtm/pqexpbuffer.h @@ -0,0 +1,181 @@ +/*------------------------------------------------------------------------- + * + * pqexpbuffer.h + * Declarations/definitions for "PQExpBuffer" functions. + * + * PQExpBuffer provides an indefinitely-extensible string data type. + * It can be used to buffer either ordinary C strings (null-terminated text) + * or arbitrary binary data. All storage is allocated with malloc(). + * + * This module is essentially the same as the backend's StringInfo data type, + * but it is intended for use in frontend libpq and client applications. + * Thus, it does not rely on palloc() nor elog(). + * + * It does rely on vsnprintf(); if configure finds that libc doesn't provide + * a usable vsnprintf(), then a copy of our own implementation of it will + * be linked into libpq. + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/interfaces/libpq/pqexpbuffer.h,v 1.21 2008/11/26 16:23:11 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef PQEXPBUFFER_H +#define PQEXPBUFFER_H + +/*------------------------- + * PQExpBufferData holds information about an extensible string. + * data is the current buffer for the string (allocated with malloc). + * len is the current string length. There is guaranteed to be + * a terminating '\0' at data[len], although this is not very + * useful when the string holds binary data rather than text. + * maxlen is the allocated size in bytes of 'data', i.e. the maximum + * string size (including the terminating '\0' char) that we can + * currently store in 'data' without having to reallocate + * more space. We must always have maxlen > len. + * + * An exception occurs if we failed to allocate enough memory for the string + * buffer. In that case data points to a statically allocated empty string, + * and len = maxlen = 0. + *------------------------- + */ +typedef struct PQExpBufferData +{ + char *data; + size_t len; + size_t maxlen; +} PQExpBufferData; + +typedef PQExpBufferData *PQExpBuffer; + +/*------------------------ + * Test for a broken (out of memory) PQExpBuffer. + * When a buffer is "broken", all operations except resetting or deleting it + * are no-ops. + *------------------------ + */ +#define PQExpBufferBroken(str) \ + ((str) == NULL || (str)->maxlen == 0) + +/*------------------------ + * Initial size of the data buffer in a PQExpBuffer. + * NB: this must be large enough to hold error messages that might + * be returned by PQrequestCancel(). + *------------------------ + */ +#define INITIAL_EXPBUFFER_SIZE 256 + +/*------------------------ + * There are two ways to create a PQExpBuffer object initially: + * + * PQExpBuffer stringptr = createGTMPQExpBuffer(); + * Both the PQExpBufferData and the data buffer are malloc'd. + * + * PQExpBufferData string; + * initGTMPQExpBuffer(&string); + * The data buffer is malloc'd but the PQExpBufferData is presupplied. + * This is appropriate if the PQExpBufferData is a field of another + * struct. + *------------------------- + */ + +/*------------------------ + * createGTMPQExpBuffer + * Create an empty 'PQExpBufferData' & return a pointer to it. + */ +extern PQExpBuffer createGTMPQExpBuffer(void); + +/*------------------------ + * initGTMPQExpBuffer + * Initialize a PQExpBufferData struct (with previously undefined contents) + * to describe an empty string. + */ +extern void initGTMPQExpBuffer(PQExpBuffer str); + +/*------------------------ + * To destroy a PQExpBuffer, use either: + * + * destroyGTMPQExpBuffer(str); + * free()s both the data buffer and the PQExpBufferData. + * This is the inverse of createGTMPQExpBuffer(). + * + * termGTMPQExpBuffer(str) + * free()s the data buffer but not the PQExpBufferData itself. + * This is the inverse of initGTMPQExpBuffer(). + * + * NOTE: some routines build up a string using PQExpBuffer, and then + * release the PQExpBufferData but return the data string itself to their + * caller. At that point the data string looks like a plain malloc'd + * string. + */ +extern void destroyGTMPQExpBuffer(PQExpBuffer str); +extern void termGTMPQExpBuffer(PQExpBuffer str); + +/*------------------------ + * resetGTMPQExpBuffer + * Reset a PQExpBuffer to empty + * + * Note: if possible, a "broken" PQExpBuffer is returned to normal. + */ +extern void resetGTMPQExpBuffer(PQExpBuffer str); + +/*------------------------ + * enlargeGTMPQExpBuffer + * Make sure there is enough space for 'needed' more bytes in the buffer + * ('needed' does not include the terminating null). + * + * Returns 1 if OK, 0 if failed to enlarge buffer. (In the latter case + * the buffer is left in "broken" state.) + */ +extern int enlargeGTMPQExpBuffer(PQExpBuffer str, size_t needed); + +/*------------------------ + * printfGTMPQExpBuffer + * Format text data under the control of fmt (an sprintf-like format string) + * and insert it into str. More space is allocated to str if necessary. + * This is a convenience routine that does the same thing as + * resetGTMPQExpBuffer() followed by appendGTMPQExpBuffer(). + */ +extern void +printfGTMPQExpBuffer(PQExpBuffer str, const char *fmt,...) +/* This extension allows gcc to check the format string */ +__attribute__((format(printf, 2, 3))); + +/*------------------------ + * appendGTMPQExpBuffer + * Format text data under the control of fmt (an sprintf-like format string) + * and append it to whatever is already in str. More space is allocated + * to str if necessary. This is sort of like a combination of sprintf and + * strcat. + */ +extern void +appendGTMPQExpBuffer(PQExpBuffer str, const char *fmt,...) +/* This extension allows gcc to check the format string */ +__attribute__((format(printf, 2, 3))); + +/*------------------------ + * appendGTMPQExpBufferStr + * Append the given string to a PQExpBuffer, allocating more space + * if necessary. + */ +extern void appendGTMPQExpBufferStr(PQExpBuffer str, const char *data); + +/*------------------------ + * appendGTMPQExpBufferChar + * Append a single byte to str. + * Like appendGTMPQExpBuffer(str, "%c", ch) but much faster. + */ +extern void appendGTMPQExpBufferChar(PQExpBuffer str, char ch); + +/*------------------------ + * appendBinaryGTMPQExpBuffer + * Append arbitrary binary data to a PQExpBuffer, allocating more space + * if necessary. + */ +extern void appendBinaryGTMPQExpBuffer(PQExpBuffer str, + const char *data, size_t datalen); + +#endif /* PQEXPBUFFER_H */ diff --git a/src/include/gtm/pqformat.h b/src/include/gtm/pqformat.h new file mode 100644 index 0000000000..3febf2cf2e --- /dev/null +++ b/src/include/gtm/pqformat.h @@ -0,0 +1,48 @@ +/*------------------------------------------------------------------------- + * + * pqformat.h + * Definitions for formatting and parsing frontend/backend messages + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/libpq/pqformat.h,v 1.27 2009/01/01 17:23:59 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef PQFORMAT_H +#define PQFORMAT_H + +#include "gtm/stringinfo.h" + +extern void pq_beginmessage(StringInfo buf, char msgtype); +extern void pq_sendbyte(StringInfo buf, int byt); +extern void pq_sendbytes(StringInfo buf, const char *data, int datalen); +extern void pq_sendcountedtext(StringInfo buf, const char *str, int slen, + bool countincludesself); +extern void pq_sendtext(StringInfo buf, const char *str, int slen); +extern void pq_sendstring(StringInfo buf, const char *str); +extern void pq_send_ascii_string(StringInfo buf, const char *str); +extern void pq_sendint(StringInfo buf, int i, int b); +extern void pq_sendint64(StringInfo buf, int64 i); +extern void pq_sendfloat4(StringInfo buf, float4 f); +extern void pq_sendfloat8(StringInfo buf, float8 f); +extern void pq_endmessage(Port *myport, StringInfo buf); + +extern void pq_puttextmessage(Port *myport, char msgtype, const char *str); +extern void pq_putemptymessage(Port *myport, char msgtype); + +extern int pq_getmsgbyte(StringInfo msg); +extern unsigned int pq_getmsgint(StringInfo msg, int b); +extern int64 pq_getmsgint64(StringInfo msg); +extern float4 pq_getmsgfloat4(StringInfo msg); +extern float8 pq_getmsgfloat8(StringInfo msg); +extern const char *pq_getmsgbytes(StringInfo msg, int datalen); +extern void pq_copymsgbytes(StringInfo msg, char *buf, int datalen); +extern char *pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes); +extern const char *pq_getmsgstring(StringInfo msg); +extern void pq_getmsgend(StringInfo msg); +extern int pq_getmsgunreadlen(StringInfo msg); + +#endif /* PQFORMAT_H */ diff --git a/src/include/gtm/pqsignal.h b/src/include/gtm/pqsignal.h new file mode 100644 index 0000000000..e3a53dc3ed --- /dev/null +++ b/src/include/gtm/pqsignal.h @@ -0,0 +1,49 @@ +/*------------------------------------------------------------------------- + * + * pqsignal.h + * prototypes for the reliable BSD-style signal(2) routine. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/libpq/pqsignal.h,v 1.32 2008/01/01 19:45:58 momjian Exp $ + * + * NOTES + * This shouldn't be in libpq, but the monitor and some other + * things need it... + * + *------------------------------------------------------------------------- + */ +#ifndef PQSIGNAL_H +#define PQSIGNAL_H + +#include <signal.h> + +#ifdef HAVE_SIGPROCMASK +extern sigset_t UnBlockSig, + BlockSig, + AuthBlockSig; + +#define PG_SETMASK(mask) sigprocmask(SIG_SETMASK, mask, NULL) +#else +extern int UnBlockSig, + BlockSig, + AuthBlockSig; + +#ifndef WIN32 +#define PG_SETMASK(mask) sigsetmask(*((int*)(mask))) +#else +#define PG_SETMASK(mask) pqsigsetmask(*((int*)(mask))) +int pqsigsetmask(int mask); +#endif +#endif + +typedef void (*pqsigfunc) (int); + +extern void pqinitmask(void); + +extern pqsigfunc pqsignal(int signo, pqsigfunc func); + +#endif /* PQSIGNAL_H */ diff --git a/src/include/gtm/stringinfo.h b/src/include/gtm/stringinfo.h new file mode 100644 index 0000000000..197aa877a1 --- /dev/null +++ b/src/include/gtm/stringinfo.h @@ -0,0 +1,149 @@ +/*------------------------------------------------------------------------- + * + * stringinfo.h + * Declarations/definitions for "StringInfo" functions. + * + * StringInfo provides an indefinitely-extensible string data type. + * It can be used to buffer either ordinary C strings (null-terminated text) + * or arbitrary binary data. All storage is allocated with palloc(). + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * $PostgreSQL: pgsql/src/include/lib/stringinfo.h,v 1.35 2008/01/01 19:45:57 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef STRINGINFO_H +#define STRINGINFO_H + +/*------------------------- + * StringInfoData holds information about an extensible string. + * data is the current buffer for the string (allocated with palloc). + * len is the current string length. There is guaranteed to be + * a terminating '\0' at data[len], although this is not very + * useful when the string holds binary data rather than text. + * maxlen is the allocated size in bytes of 'data', i.e. the maximum + * string size (including the terminating '\0' char) that we can + * currently store in 'data' without having to reallocate + * more space. We must always have maxlen > len. + * cursor is initialized to zero by makeStringInfo or initStringInfo, + * but is not otherwise touched by the stringinfo.c routines. + * Some routines use it to scan through a StringInfo. + *------------------------- + */ +typedef struct StringInfoData +{ + char *data; + int len; + int maxlen; + int cursor; +} StringInfoData; + +typedef StringInfoData *StringInfo; + + +/*------------------------ + * There are two ways to create a StringInfo object initially: + * + * StringInfo stringptr = makeStringInfo(); + * Both the StringInfoData and the data buffer are palloc'd. + * + * StringInfoData string; + * initStringInfo(&string); + * The data buffer is palloc'd but the StringInfoData is just local. + * This is the easiest approach for a StringInfo object that will + * only live as long as the current routine. + * + * To destroy a StringInfo, pfree() the data buffer, and then pfree() the + * StringInfoData if it was palloc'd. There's no special support for this. + * + * NOTE: some routines build up a string using StringInfo, and then + * release the StringInfoData but return the data string itself to their + * caller. At that point the data string looks like a plain palloc'd + * string. + *------------------------- + */ + +/*------------------------ + * makeStringInfo + * Create an empty 'StringInfoData' & return a pointer to it. + */ +extern StringInfo makeStringInfo(void); + +/*------------------------ + * initStringInfo + * Initialize a StringInfoData struct (with previously undefined contents) + * to describe an empty string. + */ +extern void initStringInfo(StringInfo str); + +/*------------------------ + * resetStringInfo + * Clears the current content of the StringInfo, if any. The + * StringInfo remains valid. + */ +extern void resetStringInfo(StringInfo str); + +/*------------------------ + * appendStringInfo + * Format text data under the control of fmt (an sprintf-style format string) + * and append it to whatever is already in str. More space is allocated + * to str if necessary. This is sort of like a combination of sprintf and + * strcat. + */ +extern void +appendStringInfo(StringInfo str, const char *fmt,...) +/* This extension allows gcc to check the format string */ +__attribute__((format(printf, 2, 3))); + +/*------------------------ + * appendStringInfoVA + * Attempt to format text data under the control of fmt (an sprintf-style + * format string) and append it to whatever is already in str. If successful + * return true; if not (because there's not enough space), return false + * without modifying str. Typically the caller would enlarge str and retry + * on false return --- see appendStringInfo for standard usage pattern. + */ +extern bool appendStringInfoVA(StringInfo str, const char *fmt, va_list args); + +/*------------------------ + * appendStringInfoString + * Append a null-terminated string to str. + * Like appendStringInfo(str, "%s", s) but faster. + */ +extern void appendStringInfoString(StringInfo str, const char *s); + +/*------------------------ + * appendStringInfoChar + * Append a single byte to str. + * Like appendStringInfo(str, "%c", ch) but much faster. + */ +extern void appendStringInfoChar(StringInfo str, char ch); + +/*------------------------ + * appendStringInfoCharMacro + * As above, but a macro for even more speed where it matters. + * Caution: str argument will be evaluated multiple times. + */ +#define appendStringInfoCharMacro(str,ch) \ + (((str)->len + 1 >= (str)->maxlen) ? \ + appendStringInfoChar(str, ch) : \ + (void)((str)->data[(str)->len] = (ch), (str)->data[++(str)->len] = '\0')) + +/*------------------------ + * appendBinaryStringInfo + * Append arbitrary binary data to a StringInfo, allocating more space + * if necessary. + */ +extern void appendBinaryStringInfo(StringInfo str, + const char *data, int datalen); + +/*------------------------ + * enlargeStringInfo + * Make sure a StringInfo's buffer can hold at least 'needed' more bytes. + */ +extern void enlargeStringInfo(StringInfo str, int needed); + +#endif /* STRINGINFO_H */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index f255c44d1c..078b6733e7 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.223 2009/06/11 14:49:11 momjian Exp $ * @@ -157,6 +158,9 @@ typedef enum NodeTag T_JoinExpr, T_FromExpr, T_IntoClause, +#ifdef PGXC + T_DistributeBy, +#endif /* * TAGS FOR EXPRESSION STATE NODES (execnodes.h) @@ -337,6 +341,7 @@ typedef enum NodeTag T_CreateUserMappingStmt, T_AlterUserMappingStmt, T_DropUserMappingStmt, + T_ExecDirectStmt, /* * TAGS FOR PARSE TREE NODES (parsenodes.h) diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 7793f66f20..e0515ba95d 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -12,6 +12,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.395 2009/06/18 01:27:02 tgl Exp $ * @@ -1335,6 +1336,9 @@ typedef struct CreateStmt List *options; /* options from WITH clause */ OnCommitAction oncommit; /* what do we do at COMMIT? */ char *tablespacename; /* table space to use, or NULL */ +#ifdef PGXC + DistributeBy *distributeby; /* distribution to use, or NULL */ +#endif } CreateStmt; /* ---------- @@ -2389,4 +2393,17 @@ typedef struct AlterTSConfigurationStmt bool missing_ok; /* for DROP - skip error if missing? */ } AlterTSConfigurationStmt; +/* PGXC_BEGIN */ +/* + * EXECUTE DIRECT statement + */ +typedef struct ExecDirectStmt +{ + NodeTag type; + bool coordinator; + List *nodes; + char *query; +} ExecDirectStmt; +/* PGXC_END */ + #endif /* PARSENODES_H */ diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h index a41b0e2f7d..36c5e6e633 100644 --- a/src/include/nodes/primnodes.h +++ b/src/include/nodes/primnodes.h @@ -9,6 +9,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.149 2009/06/11 14:49:11 momjian Exp $ * @@ -1174,4 +1175,30 @@ typedef struct FromExpr Node *quals; /* qualifiers on join, if any */ } FromExpr; +#ifdef PGXC +/*---------- + * DistributionType - how to distribute the data + * + *---------- + */ +typedef enum DistributionType +{ + DISTTYPE_REPLICATION, /* Replicated */ + DISTTYPE_HASH, /* Hash partitioned */ + DISTTYPE_ROUNDROBIN /* Round Robin */ +} DistributionType; + +/*---------- + * DistributeBy - represents a DISTRIBUTE BY clause in a CREATE TABLE statement + * + *---------- + */ +typedef struct DistributeBy +{ + NodeTag type; + DistributionType disttype; /* Distribution type */ + char *colname; /* Distribution column name */ +} DistributeBy; +#endif + #endif /* PRIMNODES_H */ diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index 23f5d87a7a..aec7b6b3d9 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -9,6 +9,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * IDENTIFICATION * $PostgreSQL: pgsql/src/include/parser/kwlist.h,v 1.2 2009/04/06 08:42:53 heikki Exp $ @@ -90,6 +91,7 @@ PG_KEYWORD("constraints", CONSTRAINTS, UNRESERVED_KEYWORD) PG_KEYWORD("content", CONTENT_P, UNRESERVED_KEYWORD) PG_KEYWORD("continue", CONTINUE_P, UNRESERVED_KEYWORD) PG_KEYWORD("conversion", CONVERSION_P, UNRESERVED_KEYWORD) +PG_KEYWORD("coordinator", COORDINATOR, UNRESERVED_KEYWORD) PG_KEYWORD("copy", COPY, UNRESERVED_KEYWORD) PG_KEYWORD("cost", COST, UNRESERVED_KEYWORD) PG_KEYWORD("create", CREATE, RESERVED_KEYWORD) @@ -125,9 +127,13 @@ PG_KEYWORD("delimiter", DELIMITER, UNRESERVED_KEYWORD) PG_KEYWORD("delimiters", DELIMITERS, UNRESERVED_KEYWORD) PG_KEYWORD("desc", DESC, RESERVED_KEYWORD) PG_KEYWORD("dictionary", DICTIONARY, UNRESERVED_KEYWORD) +PG_KEYWORD("direct", DIRECT, UNRESERVED_KEYWORD) PG_KEYWORD("disable", DISABLE_P, UNRESERVED_KEYWORD) PG_KEYWORD("discard", DISCARD, UNRESERVED_KEYWORD) PG_KEYWORD("distinct", DISTINCT, RESERVED_KEYWORD) +#ifdef PGXC +PG_KEYWORD("distribute", DISTRIBUTE, UNRESERVED_KEYWORD) +#endif PG_KEYWORD("do", DO, RESERVED_KEYWORD) PG_KEYWORD("document", DOCUMENT_P, UNRESERVED_KEYWORD) PG_KEYWORD("domain", DOMAIN_P, UNRESERVED_KEYWORD) @@ -169,6 +175,9 @@ PG_KEYWORD("granted", GRANTED, UNRESERVED_KEYWORD) PG_KEYWORD("greatest", GREATEST, COL_NAME_KEYWORD) PG_KEYWORD("group", GROUP_P, RESERVED_KEYWORD) PG_KEYWORD("handler", HANDLER, UNRESERVED_KEYWORD) +#ifdef PGXC +PG_KEYWORD("hash", HASH, UNRESERVED_KEYWORD) +#endif PG_KEYWORD("having", HAVING, RESERVED_KEYWORD) PG_KEYWORD("header", HEADER_P, UNRESERVED_KEYWORD) PG_KEYWORD("hold", HOLD, UNRESERVED_KEYWORD) @@ -243,6 +252,7 @@ PG_KEYWORD("no", NO, UNRESERVED_KEYWORD) PG_KEYWORD("nocreatedb", NOCREATEDB, UNRESERVED_KEYWORD) PG_KEYWORD("nocreaterole", NOCREATEROLE, UNRESERVED_KEYWORD) PG_KEYWORD("nocreateuser", NOCREATEUSER, UNRESERVED_KEYWORD) +PG_KEYWORD("node", NODE, UNRESERVED_KEYWORD) PG_KEYWORD("noinherit", NOINHERIT, UNRESERVED_KEYWORD) PG_KEYWORD("nologin", NOLOGIN_P, UNRESERVED_KEYWORD) PG_KEYWORD("none", NONE, COL_NAME_KEYWORD) @@ -308,6 +318,9 @@ PG_KEYWORD("rename", RENAME, UNRESERVED_KEYWORD) PG_KEYWORD("repeatable", REPEATABLE, UNRESERVED_KEYWORD) PG_KEYWORD("replace", REPLACE, UNRESERVED_KEYWORD) PG_KEYWORD("replica", REPLICA, UNRESERVED_KEYWORD) +#ifdef PGXC +PG_KEYWORD("replication", REPLICATION, UNRESERVED_KEYWORD) +#endif PG_KEYWORD("reset", RESET, UNRESERVED_KEYWORD) PG_KEYWORD("restart", RESTART, UNRESERVED_KEYWORD) PG_KEYWORD("restrict", RESTRICT, UNRESERVED_KEYWORD) @@ -315,8 +328,14 @@ PG_KEYWORD("returning", RETURNING, RESERVED_KEYWORD) PG_KEYWORD("returns", RETURNS, UNRESERVED_KEYWORD) PG_KEYWORD("revoke", REVOKE, UNRESERVED_KEYWORD) PG_KEYWORD("right", RIGHT, TYPE_FUNC_NAME_KEYWORD) +#ifdef PGXC +PG_KEYWORD("robin", ROBIN, UNRESERVED_KEYWORD) +#endif PG_KEYWORD("role", ROLE, UNRESERVED_KEYWORD) PG_KEYWORD("rollback", ROLLBACK, UNRESERVED_KEYWORD) +#ifdef PGXC +PG_KEYWORD("round", ROUND, UNRESERVED_KEYWORD) +#endif PG_KEYWORD("row", ROW, COL_NAME_KEYWORD) PG_KEYWORD("rows", ROWS, UNRESERVED_KEYWORD) PG_KEYWORD("rule", RULE, UNRESERVED_KEYWORD) diff --git a/src/include/parser/parse_utilcmd.h b/src/include/parser/parse_utilcmd.h index 089c907c0e..319699381d 100644 --- a/src/include/parser/parse_utilcmd.h +++ b/src/include/parser/parse_utilcmd.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/parser/parse_utilcmd.h,v 1.4 2009/01/01 17:24:00 momjian Exp $ * @@ -24,5 +25,8 @@ extern IndexStmt *transformIndexStmt(IndexStmt *stmt, const char *queryString); extern void transformRuleStmt(RuleStmt *stmt, const char *queryString, List **actions, Node **whereClause); extern List *transformCreateSchemaStmt(CreateSchemaStmt *stmt); +#ifdef PGXC +extern bool CheckLocalIndexColumn (char loctype, char *partcolname, char *indexcolname); +#endif #endif /* PARSE_UTILCMD_H */ diff --git a/src/include/pgxc/combiner.h b/src/include/pgxc/combiner.h new file mode 100644 index 0000000000..8c02627b57 --- /dev/null +++ b/src/include/pgxc/combiner.h @@ -0,0 +1,63 @@ +/*------------------------------------------------------------------------- + * + * combiner.h + * + * Combine responses from multiple Data Nodes + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group ? + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $$ + * + *------------------------------------------------------------------------- + */ + +#ifndef COMBINER_H +#define COMBINER_H + +#include "postgres.h" +#include "tcop/dest.h" + +typedef enum +{ + COMBINE_TYPE_NONE, /* it is known that no row count, do not parse */ + COMBINE_TYPE_SUM, /* sum row counts (partitioned, round robin) */ + COMBINE_TYPE_AVG /* calculate average (replicated) */ +} CombineType; + +typedef enum +{ + REQUEST_TYPE_NOT_DEFINED, /* not determined yet */ + REQUEST_TYPE_COMMAND, /* OK or row count response */ + REQUEST_TYPE_QUERY, /* Row description response */ + REQUEST_TYPE_COPY_IN, /* Copy In response */ + REQUEST_TYPE_COPY_OUT /* Copy Out response */ +} RequestType; + + +typedef struct +{ + int node_count; + CombineType combine_type; + CommandDest dest; + int command_complete_count; + int row_count; + RequestType request_type; + int description_count; + List *simple_aggregates; +} ResponseCombinerData; + + +typedef ResponseCombinerData *ResponseCombiner; + +extern ResponseCombiner CreateResponseCombiner(int node_count, + CombineType combine_type, CommandDest dest); +extern int CombineResponse(ResponseCombiner combiner, char msg_type, + char *msg_body, size_t len); +extern bool ValidateAndCloseCombiner(ResponseCombiner combiner); +extern bool ValidateAndResetCombiner(ResponseCombiner combiner); +extern void AssignCombinerAggregates(ResponseCombiner combiner, List *simple_aggregates); + +#endif /* COMBINER_H */ diff --git a/src/include/pgxc/datanode.h b/src/include/pgxc/datanode.h new file mode 100644 index 0000000000..e140445a28 --- /dev/null +++ b/src/include/pgxc/datanode.h @@ -0,0 +1,76 @@ +/*------------------------------------------------------------------------- + * + * datanode.h + * + * Utility functions to communicate to Data Node + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group ? + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $$ + * + *------------------------------------------------------------------------- + */ + +#ifndef DATANODE_H +#define DATANODE_H +#include "combiner.h" +#include "nodes/pg_list.h" +#include "utils/snapshot.h" +#include <unistd.h> + +/* Connection to data node maintained by Pool Manager */ +typedef struct PGconn NODE_CONNECTION; + +/* Helper structure to access data node from Session */ +typedef enum +{ + DN_CONNECTION_STATE_IDLE, + DN_CONNECTION_STATE_BUSY, + DN_CONNECTION_STATE_COMPLETED, + DN_CONNECTION_STATE_ERROR + +} DNConnectionState; + +struct data_node_handle +{ + /* fd of the connection */ + int sock; + /* Connection state */ + char transaction_status; + DNConnectionState state; + char *error; + /* Output buffer */ + char *outBuffer; + size_t outSize; + size_t outEnd; + /* Input buffer */ + char *inBuffer; + size_t inSize; + size_t inStart; + size_t inEnd; + size_t inCursor; +}; +typedef struct data_node_handle DataNodeHandle; + +extern void InitMultinodeExecutor(void); + +/* Open/close connection routines (invoked from Pool Manager) */ +extern char *DataNodeConnStr(char *host, char *port, char *dbname, char *user, + char *password); +extern NODE_CONNECTION *DataNodeConnect(char *connstr); +extern void DataNodeClose(NODE_CONNECTION * conn); +extern int DataNodeConnected(NODE_CONNECTION * conn); +extern int DataNodeConnClean(NODE_CONNECTION * conn); +extern void DataNodeCleanAndRelease(int code, Datum arg); + +/* Multinode Executor */ +extern void DataNodeBegin(void); +extern int DataNodeCommit(CommandDest dest); +extern int DataNodeRollback(CommandDest dest); + +extern int DataNodeExec(const char *query, List *nodelist, CommandDest dest, Snapshot snapshot, bool force_autocommit, List *simple_aggregates, bool is_read_only); + +#endif diff --git a/src/include/pgxc/locator.h b/src/include/pgxc/locator.h new file mode 100644 index 0000000000..1320b3c6f6 --- /dev/null +++ b/src/include/pgxc/locator.h @@ -0,0 +1,66 @@ +/*------------------------------------------------------------------------- + * + * locator.h + * Externally declared locator functions + * + * + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * + * IDENTIFICATION + * $$ + * + *------------------------------------------------------------------------- + */ +#ifndef LOCATOR_H +#define LOCATOR_H + +#define LOCATOR_TYPE_REPLICATED 'R' +#define LOCATOR_TYPE_HASH 'H' +#define LOCATOR_TYPE_RANGE 'G' +#define LOCATOR_TYPE_SINGLE 'S' +#define LOCATOR_TYPE_RROBIN 'N' +#define LOCATOR_TYPE_CUSTOM 'C' + +#define HASH_SIZE 4096 +#define HASH_MASK 0x00000FFF; + +#include "utils/relcache.h" + + +typedef int PartAttrNumber; + +typedef struct +{ + Oid relid; + char locatorType; + PartAttrNumber partAttrNum; /* if partitioned */ + char *partAttrName; /* if partitioned */ + int nodeCount; + List *nodeList; + ListCell *roundRobinNode; /* points to next one to use */ +} RelationLocInfo; + + +extern char *PreferredDataNodes; + +extern void InitRelationLocInfo(); +extern char GetLocatorType(Oid relid); +extern char ConvertToLocatorType(int disttype); + +extern char *GetRelationHashColumn(RelationLocInfo * rel_loc_info); +extern RelationLocInfo *GetRelationLocInfo(Oid relid); +extern RelationLocInfo *CopyRelationLocInfo(RelationLocInfo * src_info); +extern List *GetRelationNodes(RelationLocInfo * rel_loc_info, long *partValue, + int isRead); +extern bool IsHashColumn(RelationLocInfo * rel_loc_info, char *part_col_name); +extern bool IsHashColumnForRelId(Oid relid, char *part_col_name); +extern int GetRoundRobinNode(Oid relid); + +extern bool IsHashDistributable(Oid col_type); +extern List *GetAllNodes(void); +extern int GetAnyDataNode(void); +extern void RelationBuildLocator(Relation rel); +extern void FreeRelationLocInfo(RelationLocInfo * relationLocInfo); + +#endif /* LOCATOR_H */ diff --git a/src/include/pgxc/pgxc.h b/src/include/pgxc/pgxc.h new file mode 100644 index 0000000000..09ff2c0ada --- /dev/null +++ b/src/include/pgxc/pgxc.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * pgxc.h + * PG-XC + * + * + * Portions Copyright (c) 1996-2010 PostgreSQL Global Development Group + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $$ + * + *------------------------------------------------------------------------- + */ +#ifdef PGXC + +extern bool isPGXCCoordinator; +extern bool isPGXCDataNode; + +#define IS_PGXC_COORDINATOR isPGXCCoordinator +#define IS_PGXC_DATANODE isPGXCDataNode + +#endif /* PGXC */ diff --git a/src/include/pgxc/planner.h b/src/include/pgxc/planner.h new file mode 100644 index 0000000000..eda25a72bb --- /dev/null +++ b/src/include/pgxc/planner.h @@ -0,0 +1,86 @@ +/*------------------------------------------------------------------------- + * + * planner.h + * Externally declared locator functions + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group ? + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $$ + * + *------------------------------------------------------------------------- + */ +#ifndef PGXCPLANNER_H +#define PGXCPLANNER_H + +/* for Query_Plan.exec_loc_type can have these OR'ed*/ +#define EXEC_ON_COORD 0x1 +#define EXEC_ON_DATA_NODES 0x2 + +/* Contains instructions on processing a step of a query. + * In the prototype this will be simple, but it will eventually + * evolve into a GridSQL-style QueryStep. + */ +typedef struct +{ + char *sql_statement; + List *nodelist; + List *simple_aggregates; /* simple aggregate to combine on this + * step */ +} Query_Step; + + +/* + * The PGXC plan to execute. + * In the prototype this will be simple, and queryStepList will + * contain just one step. + */ +typedef struct +{ + int exec_loc_type; + bool force_autocommit; /* For CREATE DATABASE */ + List *query_step_list; /* List of QuerySteps */ +} Query_Plan; + + +/* For handling simple aggregates (no group by present) + * For now, only MAX will be supported. + */ +typedef enum +{ + AGG_TYPE_MAX, + AGG_TYPE_MIN, + AGG_TYPE_COUNT, + AGG_TYPE_SUM, + AGG_TYPE_AVG +} SimpleAggType; + + +/* For handling simple aggregates */ +/* For now, only support int/long types */ +typedef struct +{ + int agg_type; /* SimpleAggType enum */ + int column_pos; /* Only use 1 for now */ + unsigned long ulong_value; + /* Datum agg_value; PGXCTODO - use Datum, support more types */ + int data_len; + int agg_data_type; + int response_count; +} SimpleAgg; + +/* forbid SQL if unsafe, useful to turn off for development */ +extern bool StrictStatementChecking; + +/* forbid SELECT even multi-node ORDER BY */ +extern bool StrictSelectChecking; + +extern Query_Plan * + GetQueryPlan(Node *parsetree, const char *sql_statement, List *querytree_list); +extern void + FreeQueryPlan(Query_Plan * query_plan); +extern bool IsHashDistributable(Oid col_type); + +#endif /* PGXCPLANNER_H */ diff --git a/src/include/pgxc/poolcomm.h b/src/include/pgxc/poolcomm.h new file mode 100644 index 0000000000..3c62f0662e --- /dev/null +++ b/src/include/pgxc/poolcomm.h @@ -0,0 +1,49 @@ +/*------------------------------------------------------------------------- + * + * poolcomm.h + * + * Definitions for the Pooler-Seesion communications. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $$ + * + *------------------------------------------------------------------------- + */ +#ifndef POOLCOMM_H +#define POOLCOMM_H + +#include "lib/stringinfo.h" + +#define POOL_BUFFER_SIZE 1024 +#define Socket(port) (port).fdsock + +typedef struct +{ + /* file descriptors */ + int fdsock; + /* receive buffer */ + int RecvLength; + int RecvPointer; + char RecvBuffer[POOL_BUFFER_SIZE]; + /* send buffer */ + int SendPointer; + char SendBuffer[POOL_BUFFER_SIZE]; +} PoolPort; + +extern int pool_listen(unsigned short port, const char *unixSocketName); +extern int pool_connect(unsigned short port, const char *unixSocketName); +extern int pool_getbyte(PoolPort * port); +extern int pool_pollbyte(PoolPort * port); +extern int pool_getmessage(PoolPort * port, StringInfo s, int maxlen); +extern int pool_getbytes(PoolPort * port, char *s, size_t len); +extern int pool_putmessage(PoolPort * port, char msgtype, const char *s, size_t len); +extern int pool_putbytes(PoolPort * port, const char *s, size_t len); +extern int pool_flush(PoolPort * port); +extern int pool_sendfds(PoolPort * port, int *fds, int count); +extern int pool_recvfds(PoolPort * port, int *fds, int count); + +#endif /* POOLCOMM_H */ diff --git a/src/include/pgxc/poolmgr.h b/src/include/pgxc/poolmgr.h new file mode 100644 index 0000000000..6e88fca3bc --- /dev/null +++ b/src/include/pgxc/poolmgr.h @@ -0,0 +1,130 @@ +/*------------------------------------------------------------------------- + * + * poolmgr.h + * + * Definitions for the data nodes connection pool. + * + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation + * + * IDENTIFICATION + * $$ + * + *------------------------------------------------------------------------- + */ + +#ifndef POOLMGR_H +#define POOLMGR_H +#include <sys/time.h> +#include "datanode.h" +#include "poolcomm.h" +#include "storage/pmsignal.h" + +#define MAX_IDLE_TIME 60 + +/* TODO move? */ +typedef struct +{ + char *host; + char *port; + char *uname; + char *password; +} DataNodeConnectionInfo; + +/* Connection pool entry */ +typedef struct +{ + struct timeval released; + NODE_CONNECTION *conn; +} DataNodePoolSlot; + +/* Pool of connections to specified data nodes */ +typedef struct +{ + char *connstr; + int freeSize; /* available connections */ + int size; /* total pool size */ + DataNodePoolSlot **slot; +} DataNodePool; + +/* All pools for specified database */ +typedef struct databasepool +{ + Oid databaseId; + char *database; + DataNodePool **nodePools; /* one for each data node */ + struct databasepool *next; +} DatabasePool; + +/* Agent of client session (Pool Manager side) + * Acts as a session manager, grouping connections together + */ +typedef struct +{ + /* communication channel */ + PoolPort port; + DatabasePool *pool; + DataNodePoolSlot **connections; /* one for each data node */ +} PoolAgent; + +/* Handle to the pool manager (Session's side) */ +typedef struct +{ + /* communication channel */ + PoolPort port; +} PoolHandle; + +extern int NumDataNodes; +extern int MinPoolSize; +extern int MaxPoolSize; +extern int PoolerPort; + +extern bool PersistentConnections; + +extern char *DataNodeHosts; +extern char *DataNodePorts; +extern char *DataNodeUsers; +extern char *DataNodePwds; + +/* Initialize internal structures */ +extern int PoolManagerInit(void); + +/* Destroy internal structures */ +extern int PoolManagerDestroy(void); + +/* + * Get handle to pool manager. This function should be called just before + * forking off new session. It creates PoolHandle, PoolAgent and a pipe between + * them. PoolAgent is stored within Postmaster's memory context and Session + * closes it later. PoolHandle is returned and should be store in a local + * variable. After forking off it can be stored in global memory, so it will + * only be accessible by the process running the session. + */ +extern PoolHandle *GetPoolManagerHandle(void); + +/* + * Called from Postmaster(Coordinator) after fork. Close one end of the pipe and + * free memory occupied by PoolHandler + */ +extern void PoolManagerCloseHandle(PoolHandle * handle); + +/* + * Gracefully close connection to the PoolManager + */ +extern void PoolManagerDisconnect(PoolHandle * handle); + +/* + * Called from Session process after fork(). Associate handle with session + * for subsequent calls. Associate session with specified database and + * initialize respective connection pool + */ +extern void PoolManagerConnect(PoolHandle * handle, const char *database, List *nodes); + +/* Get pooled connections */ +extern int *PoolManagerGetConnections(List *nodelist); + +/* Retun connections back to the pool */ +extern void PoolManagerReleaseConnections(void); + +#endif diff --git a/src/include/postgres.h b/src/include/postgres.h index c1e4f77386..e8bfd5a391 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -9,6 +9,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1995, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/postgres.h,v 1.92 2009/01/01 17:23:55 momjian Exp $ * @@ -693,4 +694,7 @@ extern int ExceptionalCondition(const char *conditionName, const char *errorType, const char *fileName, int lineNumber); +//#define PGXC_COORD // for PGXC coordinator compiling +//#define PGXC_DATANODE // for PGXC data node compiling + #endif /* POSTGRES_H */ diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h index 3175487af3..952291bcb0 100644 --- a/src/include/postmaster/autovacuum.h +++ b/src/include/postmaster/autovacuum.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/postmaster/autovacuum.h,v 1.15 2009/01/01 17:24:01 momjian Exp $ * @@ -60,4 +61,8 @@ extern void AutovacuumLauncherIAm(void); extern Size AutoVacuumShmemSize(void); extern void AutoVacuumShmemInit(void); +#ifdef PGXC /* PGXC_DATANODE */ +bool IsAutoVacuumWorkerProcess(void); +#endif + #endif /* AUTOVACUUM_H */ diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h index b250d3f0f2..66a920ded0 100644 --- a/src/include/storage/proc.h +++ b/src/include/storage/proc.h @@ -143,8 +143,9 @@ typedef struct PROC_HDR * normal operation. Startup process also consumes one slot, but WAL * writer and autovacuum launcher are launched only after it has * exited. + * Also pool manager process is added */ -#define NUM_AUXILIARY_PROCS 3 +#define NUM_AUXILIARY_PROCS 4 /* configurable options */ diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h index fab84ee1a0..4431e1bc54 100644 --- a/src/include/storage/procarray.h +++ b/src/include/storage/procarray.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/storage/procarray.h,v 1.26 2009/06/11 14:49:12 momjian Exp $ * @@ -26,6 +27,10 @@ extern void ProcArrayRemove(PGPROC *proc, TransactionId latestXid); extern void ProcArrayEndTransaction(PGPROC *proc, TransactionId latestXid); extern void ProcArrayClearTransaction(PGPROC *proc); +#ifdef PGXC /* PGXC_DATANODE */ +extern void SetGlobalSnapshotData(int xmin, int xmax, int xcnt, int *xip); +extern void UnsetGlobalSnapshotData(void); +#endif /* PGXC */ extern Snapshot GetSnapshotData(Snapshot snapshot); extern bool TransactionIdIsInProgress(TransactionId xid); diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h index b50944a547..9c87386288 100644 --- a/src/include/utils/guc_tables.h +++ b/src/include/utils/guc_tables.h @@ -76,7 +76,9 @@ enum config_group COMPAT_OPTIONS_CLIENT, PRESET_OPTIONS, CUSTOM_OPTIONS, - DEVELOPER_OPTIONS + DEVELOPER_OPTIONS, + DATA_NODES, + GTM }; /* diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index ca9913bda3..5f3a482877 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -6,6 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.114 2009/06/11 14:49:13 momjian Exp $ * @@ -20,6 +21,9 @@ #include "catalog/pg_index.h" #include "fmgr.h" #include "nodes/bitmapset.h" +#ifdef PGXC +#include "pgxc/locator.h" +#endif #include "rewrite/prs2lock.h" #include "storage/block.h" #include "storage/relfilenode.h" @@ -205,6 +209,9 @@ typedef struct RelationData /* use "struct" here to avoid needing to include pgstat.h: */ struct PgStat_TableStatus *pgstat_info; /* statistics collection area */ +#ifdef PGXC + RelationLocInfo *rd_locator_info; +#endif } RelationData; /* diff --git a/src/include/utils/snapshot.h b/src/include/utils/snapshot.h index e5003b669a..835ba95291 100644 --- a/src/include/utils/snapshot.h +++ b/src/include/utils/snapshot.h @@ -5,6 +5,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/utils/snapshot.h,v 1.5 2009/06/11 14:49:13 momjian Exp $ * @@ -46,7 +47,11 @@ typedef struct SnapshotData */ TransactionId xmin; /* all XID < xmin are visible to me */ TransactionId xmax; /* all XID >= xmax are invisible to me */ + TransactionId recent_global_xmin; uint32 xcnt; /* # of xact ids in xip[] */ +#ifdef PGXC /* PGXC_COORD */ + uint32 max_xcnt; /* Max # of xact in xip[] */ +#endif TransactionId *xip; /* array of xact IDs in progress */ /* note: all ids in xip[] satisfy xmin <= xip[i] < xmax */ int32 subxcnt; /* # of xact ids in subxip[], -1 if overflow */ diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index 1428b28d15..e038041519 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -8,6 +8,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2010 Nippon Telegraph and Telephone Corporation * * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.74 2009/01/01 17:24:02 momjian Exp $ * @@ -64,6 +65,9 @@ enum SysCacheIdentifier OPEROID, OPFAMILYAMNAMENSP, OPFAMILYOID, +#ifdef PGXC + PGXCCLASSRELID, +#endif PROCNAMEARGSNSP, PROCOID, RELNAMENSP, |
