1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
/*-------------------------------------------------------------------------
*
* gtm.h
*
*
* Portions Copyright (c) 2012-2014, TransLattice, Inc.
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 2010-2012 Postgres-XC Development Group
*
* $PostgreSQL$
*
*-------------------------------------------------------------------------
*/
#ifndef _GTM_H
#define _GTM_H
#include <setjmp.h>
#include "gtm/gtm_c.h"
#include "gtm/gtm_common.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,
GTM_THREAD_BACKUP, /* Backup to standby is in progress */
/* Must be the last */
GTM_THREAD_INVALID
} GTM_ThreadStatus;
struct GTM_ConnectionInfo;
#define ERRORDATA_STACK_SIZE 20
typedef struct GTM_ThreadInfo
{
/*
* Initial few members get includes from gtm_common.h. This is to make sure
* that the GTMProxy_ThreadInfo and GTM_ThreadInfo structure can be
* typecasted to each other and these initial members can be safely
* accessed. If you need a member which should be common to both
* structures, consider adding them to GTM_COMMON_THREAD_INFO
*/
GTM_COMMON_THREAD_INFO
GTM_ThreadStatus thr_status;
GTM_ConnectionInfo *thr_conn;
uint32 thr_client_id; /* unique client identifier */
GTM_RWLock thr_lock;
gtm_List *thr_cached_txninfo;
GTM_SnapshotData thr_snapshot;
/*
* Statically allocated XID array for the snapshot. Every thread will need
* a snapshot anyway, and this way we don't have to worry about allocation
* and freeing of the memory at thread exit.
*/
GlobalTransactionId thr_xip[GTM_MAX_GLOBAL_TRANSACTIONS];
} GTM_ThreadInfo;
typedef struct GTM_Threads
{
uint32 gt_thread_count;
uint32 gt_array_size;
bool gt_standby_ready;
GTM_ThreadInfo **gt_threads;
uint32 gt_starting_client_id;
uint32 gt_next_client_id;
GTM_RWLock gt_lock;
} GTM_Threads;
extern GTM_Threads *GTMThreads;
typedef struct GTM_RestoreContext {
int version;
} GTM_RestoreContext;
int GTM_ThreadAdd(GTM_ThreadInfo *thrinfo);
int GTM_ThreadRemove(GTM_ThreadInfo *thrinfo);
void ConnFree(Port *port);
void GTM_DoForAllOtherThreads(void (* process_routine)(GTM_ThreadInfo *));
void GTM_SetInitialAndNextClientIdentifierAtPromote(void);
GTM_ThreadInfo *GTM_ThreadCreate(GTM_ConnectionInfo *conninfo,
void *(* startroutine)(void *));
extern void SaveControlInfo(void);
void GTM_RestoreSeqInfo(FILE *ctlf, struct GTM_RestoreContext *context);
#define CONTROL_INTERVAL 50000
/*
* pthread keys to get thread specific information
*/
extern pthread_key_t threadinfo_key;
extern MemoryContext TopMostMemoryContext;
extern GTM_ThreadID TopMostThreadID;
#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 NumRWLocksHeld (GetMyThreadInfo->thr_num_rwlocks_held)
#define RWLocksHeld (GetMyThreadInfo->thr_rwlocks_held)
#define NumMutexLocksHeld (GetMyThreadInfo->thr_num_mutexlocks_held)
#define MutexLocksHeld (GetMyThreadInfo->thr_mutexlocks_held)
#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 IsMainThread() (GetMyThreadInfo->thr_id == TopMostThreadID)
#define GTM_CachedTransInfo (GetMyThreadInfo->thr_cached_txninfo)
#define GTM_HaveFreeCachedTransInfo() (gtm_list_length(GTM_CachedTransInfo))
#define GTM_MAX_CACHED_TRANSINFO 0
#define GTM_HaveEnoughCachedTransInfo() (gtm_list_length(GTM_CachedTransInfo) >= GTM_MAX_CACHED_TRANSINFO)
#define GTM_CLIENT_ID_EQ(a, b) \
((a) == (b))
#define GTM_CLIENT_ID_LT(a, b) \
(((int32)((a) - (b)) < 0) ? true : false)
#define GTM_CLIENT_ID_GT(a, b) \
(!GTM_CLIENT_ID_LT(a, b) && !GTM_CLIENT_ID_EQ(a, b))
#define GTM_CLIENT_ID_NEXT(a) \
((((a) + 1) == UINT32_MAX) ? 1 : ((a) + 1))
#define GTM_CONTROL_FILE "gtm.control"
#define GTM_CONTROL_VERSION 20160302
#endif
|