Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit44d85ba

Browse files
Copy and store addrinfo in libpq-owned private memory
This refactors libpq to copy addrinfos returned by getaddrinfo tomemory owned by libpq such that future improvements can alter forexample the order of entries.As a nice side effect of this refactor the mechanism for iterationover addresses in PQconnectPoll is now identical to its iterationover hosts.Author: Jelte Fennema <postgres@jeltef.nl>Reviewed-by: Aleksander Alekseev <aleksander@timescale.com>Reviewed-by: Michael Banck <mbanck@gmx.net>Reviewed-by: Andrey Borodin <amborodin86@gmail.com>Discussion:https://postgr.es/m/PR3PR83MB04768E2FF04818EEB2179949F7A69@PR3PR83MB0476.EURPRD83.prod.outlook.com
1 parent8e5eef5 commit44d85ba

File tree

4 files changed

+92
-34
lines changed

4 files changed

+92
-34
lines changed

‎src/include/libpq/pqcomm.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ typedef struct
2727
socklen_tsalen;
2828
}SockAddr;
2929

30+
typedefstruct
31+
{
32+
intfamily;
33+
SockAddraddr;
34+
}AddrInfo;
35+
3036
/* Configure the UNIX socket location for the well known port. */
3137

3238
#defineUNIXSOCK_PATH(path,port,sockdir) \

‎src/interfaces/libpq/fe-connect.c

Lines changed: 81 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions);
389389
staticvoidfreePGconn(PGconn*conn);
390390
staticvoidclosePGconn(PGconn*conn);
391391
staticvoidrelease_conn_addrinfo(PGconn*conn);
392+
staticintstore_conn_addrinfo(PGconn*conn,structaddrinfo*addrlist);
392393
staticvoidsendTerminateConn(PGconn*conn);
393394
staticPQconninfoOption*conninfo_init(PQExpBuffererrorMessage);
394395
staticPQconninfoOption*parse_connection_string(constchar*connstr,
@@ -2295,7 +2296,7 @@ connectDBComplete(PGconn *conn)
22952296
time_tfinish_time= ((time_t)-1);
22962297
inttimeout=0;
22972298
intlast_whichhost=-2;/* certainly different from whichhost */
2298-
structaddrinfo*last_addr_cur=NULL;
2299+
intlast_whichaddr=-2;/* certainly different from whichaddr */
22992300

23002301
if (conn==NULL||conn->status==CONNECTION_BAD)
23012302
return0;
@@ -2339,11 +2340,11 @@ connectDBComplete(PGconn *conn)
23392340
if (flag!=PGRES_POLLING_OK&&
23402341
timeout>0&&
23412342
(conn->whichhost!=last_whichhost||
2342-
conn->addr_cur!=last_addr_cur))
2343+
conn->whichaddr!=last_whichaddr))
23432344
{
23442345
finish_time=time(NULL)+timeout;
23452346
last_whichhost=conn->whichhost;
2346-
last_addr_cur=conn->addr_cur;
2347+
last_whichaddr=conn->whichaddr;
23472348
}
23482349

23492350
/*
@@ -2490,9 +2491,9 @@ PQconnectPoll(PGconn *conn)
24902491
/* Time to advance to next address, or next host if no more addresses? */
24912492
if (conn->try_next_addr)
24922493
{
2493-
if (conn->addr_cur&&conn->addr_cur->ai_next)
2494+
if (conn->whichaddr<conn->naddr)
24942495
{
2495-
conn->addr_cur=conn->addr_cur->ai_next;
2496+
conn->whichaddr++;
24962497
reset_connection_state_machine= true;
24972498
}
24982499
else
@@ -2505,6 +2506,7 @@ PQconnectPoll(PGconn *conn)
25052506
{
25062507
pg_conn_host*ch;
25072508
structaddrinfohint;
2509+
structaddrinfo*addrlist;
25082510
intthisport;
25092511
intret;
25102512
charportstr[MAXPGPATH];
@@ -2545,7 +2547,7 @@ PQconnectPoll(PGconn *conn)
25452547
/* Initialize hint structure */
25462548
MemSet(&hint,0,sizeof(hint));
25472549
hint.ai_socktype=SOCK_STREAM;
2548-
conn->addrlist_family=hint.ai_family=AF_UNSPEC;
2550+
hint.ai_family=AF_UNSPEC;
25492551

25502552
/* Figure out the port number we're going to use. */
25512553
if (ch->port==NULL||ch->port[0]=='\0')
@@ -2568,8 +2570,8 @@ PQconnectPoll(PGconn *conn)
25682570
{
25692571
caseCHT_HOST_NAME:
25702572
ret=pg_getaddrinfo_all(ch->host,portstr,&hint,
2571-
&conn->addrlist);
2572-
if (ret|| !conn->addrlist)
2573+
&addrlist);
2574+
if (ret|| !addrlist)
25732575
{
25742576
libpq_append_conn_error(conn,"could not translate host name \"%s\" to address: %s",
25752577
ch->host,gai_strerror(ret));
@@ -2580,8 +2582,8 @@ PQconnectPoll(PGconn *conn)
25802582
caseCHT_HOST_ADDRESS:
25812583
hint.ai_flags=AI_NUMERICHOST;
25822584
ret=pg_getaddrinfo_all(ch->hostaddr,portstr,&hint,
2583-
&conn->addrlist);
2584-
if (ret|| !conn->addrlist)
2585+
&addrlist);
2586+
if (ret|| !addrlist)
25852587
{
25862588
libpq_append_conn_error(conn,"could not parse network address \"%s\": %s",
25872589
ch->hostaddr,gai_strerror(ret));
@@ -2590,7 +2592,7 @@ PQconnectPoll(PGconn *conn)
25902592
break;
25912593

25922594
caseCHT_UNIX_SOCKET:
2593-
conn->addrlist_family=hint.ai_family=AF_UNIX;
2595+
hint.ai_family=AF_UNIX;
25942596
UNIXSOCK_PATH(portstr,thisport,ch->host);
25952597
if (strlen(portstr) >=UNIXSOCK_PATH_BUFLEN)
25962598
{
@@ -2605,8 +2607,8 @@ PQconnectPoll(PGconn *conn)
26052607
* name as a Unix-domain socket path.
26062608
*/
26072609
ret=pg_getaddrinfo_all(NULL,portstr,&hint,
2608-
&conn->addrlist);
2609-
if (ret|| !conn->addrlist)
2610+
&addrlist);
2611+
if (ret|| !addrlist)
26102612
{
26112613
libpq_append_conn_error(conn,"could not translate Unix-domain socket path \"%s\" to address: %s",
26122614
portstr,gai_strerror(ret));
@@ -2615,8 +2617,15 @@ PQconnectPoll(PGconn *conn)
26152617
break;
26162618
}
26172619

2618-
/* OK, scan this addrlist for a working server address */
2619-
conn->addr_cur=conn->addrlist;
2620+
/*
2621+
* Store a copy of the addrlist in private memory so we can perform
2622+
* randomization for load balancing.
2623+
*/
2624+
ret=store_conn_addrinfo(conn,addrlist);
2625+
pg_freeaddrinfo_all(hint.ai_family,addrlist);
2626+
if (ret)
2627+
gotoerror_return;/* message already logged */
2628+
26202629
reset_connection_state_machine= true;
26212630
conn->try_next_host= false;
26222631
}
@@ -2673,31 +2682,30 @@ PQconnectPoll(PGconn *conn)
26732682
{
26742683
/*
26752684
* Try to initiate a connection to one of the addresses
2676-
* returned by pg_getaddrinfo_all(). conn->addr_cur is the
2685+
* returned by pg_getaddrinfo_all(). conn->whichaddr is the
26772686
* next one to try.
26782687
*
26792688
* The extra level of braces here is historical. It's not
26802689
* worth reindenting this whole switch case to remove 'em.
26812690
*/
26822691
{
2683-
structaddrinfo*addr_cur=conn->addr_cur;
26842692
charhost_addr[NI_MAXHOST];
26852693
intsock_type;
2694+
AddrInfo*addr_cur;
26862695

26872696
/*
26882697
* Advance to next possible host, if we've tried all of
26892698
* the addresses for the current host.
26902699
*/
2691-
if (addr_cur==NULL)
2700+
if (conn->whichaddr==conn->naddr)
26922701
{
26932702
conn->try_next_host= true;
26942703
gotokeep_going;
26952704
}
2705+
addr_cur=&conn->addr[conn->whichaddr];
26962706

26972707
/* Remember current address for possible use later */
2698-
memcpy(&conn->raddr.addr,addr_cur->ai_addr,
2699-
addr_cur->ai_addrlen);
2700-
conn->raddr.salen=addr_cur->ai_addrlen;
2708+
memcpy(&conn->raddr,&addr_cur->addr,sizeof(SockAddr));
27012709

27022710
/*
27032711
* Set connip, too. Note we purposely ignore strdup
@@ -2732,7 +2740,7 @@ PQconnectPoll(PGconn *conn)
27322740
*/
27332741
sock_type |=SOCK_NONBLOCK;
27342742
#endif
2735-
conn->sock=socket(addr_cur->ai_family,sock_type,0);
2743+
conn->sock=socket(addr_cur->family,sock_type,0);
27362744
if (conn->sock==PGINVALID_SOCKET)
27372745
{
27382746
interrorno=SOCK_ERRNO;
@@ -2743,7 +2751,7 @@ PQconnectPoll(PGconn *conn)
27432751
* cases where the address list includes both IPv4 and
27442752
* IPv6 but kernel only accepts one family.
27452753
*/
2746-
if (addr_cur->ai_next!=NULL||
2754+
if (conn->whichaddr<conn->naddr||
27472755
conn->whichhost+1<conn->nconnhost)
27482756
{
27492757
conn->try_next_addr= true;
@@ -2769,7 +2777,7 @@ PQconnectPoll(PGconn *conn)
27692777
* TCP sockets, nonblock mode, close-on-exec. Try the
27702778
* next address if any of this fails.
27712779
*/
2772-
if (addr_cur->ai_family!=AF_UNIX)
2780+
if (addr_cur->family!=AF_UNIX)
27732781
{
27742782
if (!connectNoDelay(conn))
27752783
{
@@ -2800,7 +2808,7 @@ PQconnectPoll(PGconn *conn)
28002808
#endif/* F_SETFD */
28012809
#endif
28022810

2803-
if (addr_cur->ai_family!=AF_UNIX)
2811+
if (addr_cur->family!=AF_UNIX)
28042812
{
28052813
#ifndefWIN32
28062814
inton=1;
@@ -2892,8 +2900,8 @@ PQconnectPoll(PGconn *conn)
28922900
* Start/make connection. This should not block, since we
28932901
* are in nonblock mode. If it does, well, too bad.
28942902
*/
2895-
if (connect(conn->sock,addr_cur->ai_addr,
2896-
addr_cur->ai_addrlen)<0)
2903+
if (connect(conn->sock,(structsockaddr*)&addr_cur->addr.addr,
2904+
addr_cur->addr.salen)<0)
28972905
{
28982906
if (SOCK_ERRNO==EINPROGRESS||
28992907
#ifdefWIN32
@@ -4318,18 +4326,60 @@ freePGconn(PGconn *conn)
43184326
free(conn);
43194327
}
43204328

4329+
/*
4330+
* store_conn_addrinfo
4331+
* - copy addrinfo to PGconn object
4332+
*
4333+
* Copies the addrinfos from addrlist to the PGconn object such that the
4334+
* addrinfos can be manipulated by libpq. Returns a positive integer on
4335+
* failure, otherwise zero.
4336+
*/
4337+
staticint
4338+
store_conn_addrinfo(PGconn*conn,structaddrinfo*addrlist)
4339+
{
4340+
structaddrinfo*ai=addrlist;
4341+
4342+
conn->whichaddr=0;
4343+
4344+
conn->naddr=0;
4345+
while (ai)
4346+
{
4347+
ai=ai->ai_next;
4348+
conn->naddr++;
4349+
}
4350+
4351+
conn->addr=calloc(conn->naddr,sizeof(AddrInfo));
4352+
if (conn->addr==NULL)
4353+
{
4354+
libpq_append_conn_error(conn,"out of memory");
4355+
return1;
4356+
}
4357+
4358+
ai=addrlist;
4359+
for (inti=0;i<conn->naddr;i++)
4360+
{
4361+
conn->addr[i].family=ai->ai_family;
4362+
4363+
memcpy(&conn->addr[i].addr.addr,ai->ai_addr,
4364+
ai->ai_addrlen);
4365+
conn->addr[i].addr.salen=ai->ai_addrlen;
4366+
ai=ai->ai_next;
4367+
}
4368+
4369+
return0;
4370+
}
4371+
43214372
/*
43224373
* release_conn_addrinfo
43234374
* - Free any addrinfo list in the PGconn.
43244375
*/
43254376
staticvoid
43264377
release_conn_addrinfo(PGconn*conn)
43274378
{
4328-
if (conn->addrlist)
4379+
if (conn->addr)
43294380
{
4330-
pg_freeaddrinfo_all(conn->addrlist_family,conn->addrlist);
4331-
conn->addrlist=NULL;
4332-
conn->addr_cur=NULL;/* for safety */
4381+
free(conn->addr);
4382+
conn->addr=NULL;
43334383
}
43344384
}
43354385

‎src/interfaces/libpq/libpq-int.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,10 @@ struct pg_conn
471471
PGTargetServerTypetarget_server_type;/* desired session properties */
472472
booltry_next_addr;/* time to advance to next address/host? */
473473
booltry_next_host;/* time to advance to next connhost[]? */
474-
structaddrinfo*addrlist;/* list of addresses for current connhost */
475-
structaddrinfo*addr_cur;/* the one currently being tried */
476-
intaddrlist_family;/* needed to know how to free addrlist */
474+
intnaddr;/* number of addresses returned by getaddrinfo */
475+
intwhichaddr;/* the address currently being tried */
476+
AddrInfo*addr;/* the array of addresses for the currently
477+
* tried host */
477478
boolsend_appname;/* okay to send application_name? */
478479

479480
/* Miscellaneous stuff */

‎src/tools/pgindent/typedefs.list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ AcquireSampleRowsFunc
2626
ActionList
2727
ActiveSnapshotElt
2828
AddForeignUpdateTargets_function
29+
AddrInfo
2930
AffixNode
3031
AffixNodeData
3132
AfterTriggerEvent

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp