forked from EnterpriseDB/mongo_fdw
-
Notifications
You must be signed in to change notification settings - Fork 0
/
connection.c
150 lines (133 loc) · 3.95 KB
/
connection.c
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
/*-------------------------------------------------------------------------
*
* connection.c
* Foreign-data wrapper for remote MongoDB servers
*
* Portions Copyright (c) 2012-2014, PostgreSQL Global Development Group
*
* Portions Copyright (c) 2004-2014, EnterpriseDB Corporation.
*
* Portions Copyright (c) 2012–2014 Citus Data, Inc.
*
* IDENTIFICATION
* connection.c
*
*-------------------------------------------------------------------------
*/
#include <sys/types.h>
#include "postgres.h"
#include "mongo_wrapper.h"
#include "mongo_fdw.h"
#include "access/xact.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
/* Length of host */
#define HOST_LEN 256
/*
* Connection cache hash table entry
*
* The lookup key in this hash table is the foreign server OID plus the user
* mapping OID. (We use just one connection per user per foreign server,
* so that we can ensure all scans use the same snapshot during a query.)
*/
typedef struct ConnCacheKey
{
Oid serverid; /* OID of foreign server */
Oid userid; /* OID of local user whose mapping we use */
} ConnCacheKey;
typedef struct ConnCacheEntry
{
ConnCacheKey key; /* hash key (must be first) */
MONGO_CONN *conn; /* connection to foreign server, or NULL */
} ConnCacheEntry;
/*
* Connection cache (initialized on first use)
*/
static HTAB *ConnectionHash = NULL;
/*
* mongo_get_connection:
* Get a mong connection which can be used to execute queries on
* the remote Mongo server with the user's authorization. A new connection
* is established if we don't already have a suitable one.
*/
MONGO_CONN*
mongo_get_connection(ForeignServer *server, UserMapping *user, MongoFdwOptions *opt)
{
bool found;
ConnCacheEntry *entry;
ConnCacheKey key;
/* First time through, initialize connection cache hashtable */
if (ConnectionHash == NULL)
{
HASHCTL ctl;
MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(ConnCacheKey);
ctl.entrysize = sizeof(ConnCacheEntry);
ctl.hash = tag_hash;
/* allocate ConnectionHash in the cache context */
ctl.hcxt = CacheMemoryContext;
ConnectionHash = hash_create("mongo_fdw connections", 8,
&ctl,
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
}
/* Create hash key for the entry. Assume no pad bytes in key struct */
key.serverid = server->serverid;
key.userid = user->userid;
/*
* Find or create cached entry for requested connection.
*/
entry = hash_search(ConnectionHash, &key, HASH_ENTER, &found);
if (!found)
{
/* initialize new hashtable entry (key is already filled in) */
entry->conn = NULL;
}
if (entry->conn == NULL)
{
#ifdef META_DRIVER
entry->conn = MongoConnect(opt->svr_address, opt->svr_port, opt->svr_database, opt->svr_username, opt->svr_password,
opt->authenticationDatabase, opt->replicaSet, opt->readPreference,
opt->ssl, opt->pem_file, opt->pem_pwd, opt->ca_file, opt->ca_dir, opt->crl_file, opt->weak_cert_validation);
#else
entry->conn = MongoConnect(opt->svr_address, opt->svr_port, opt->svr_database, opt->svr_username, opt->svr_password);
#endif
elog(DEBUG3, "new mongo_fdw connection %p for server \"%s:%d\"",
entry->conn, opt->svr_address, opt->svr_port);
}
return entry->conn;
}
/*
* mongo_cleanup_connection:
* Delete all the cache entries on backend exists.
*/
void
mongo_cleanup_connection()
{
HASH_SEQ_STATUS scan;
ConnCacheEntry *entry;
if (ConnectionHash == NULL)
return;
hash_seq_init(&scan, ConnectionHash);
while ((entry = (ConnCacheEntry *) hash_seq_search(&scan)))
{
if (entry->conn == NULL)
continue;
elog(DEBUG3, "disconnecting mongo_fdw connection %p", entry->conn);
MongoDisconnect(entry->conn);
entry->conn = NULL;
}
}
/*
* Release connection created by calling mongo_get_connection.
*/
void
mongo_release_connection(MONGO_CONN *conn)
{
/*
* We don't close the connection indvisually here, will do all connection
* cleanup on the backend exit.
*/
}