2014-11-04
2014-11-04 09:55:01 by Stephen R. van den Berg <srb@cuci.nl>
-
3c93de5c4d49c56a3460420f4ac88d33b808749b
(163 lines)
(+88/-75)
[
Show
| Annotate
]
Branch: 8.1
pgsql: Fixed reconnect behaviour, fixed textqueries, eliminated one race.
All issues eliminated. I will run it in production servers as of now.
269:
//! @[ping()]
int is_open() {
catch {
- return c->socket->query_fd()>=0;
+ return c->socket->is_open();
};
return 0;
}
319:
#endif
object plugbuffer=c->start(1);
foreach(qportals->peek_array();;object portal)
+ if(objectp(portal))
portal->_closeportal(plugbuffer);
plugbuffer->sendcmd(sendout);
}
574:
}
final void _processloop(object ci) {
- int die=0,terminating=0;
+ int terminating=0;
int|.pgsql_util.pgsql_result portal;
mixed err;
{
788:
portal->_purgeportal();
}
foreach(qportals->peek_array();;.pgsql_util.pgsql_result qp) {
+ if(objectp(qp) && qp._synctransact && qp._synctransact<=portal) {
PD("Checking portal %O %d<=%d\n",
qp._portalname,qp._synctransact,portal);
- if(qp._synctransact && qp._synctransact<=portal)
+
qp->_purgeportal();
}
-
+ }
portal=0;
_readyforquerycount--;
if(readyforquery_cb)
820:
#endif
if(portal._tprepared)
portal._tprepared.datatypeoid=a;
- portal->_preparebind(a);
+ Thread.Thread(portal->_preparebind,a);
break;
}
case 'T': {
863: Inside #if defined(PG_DEBUGMORE)
#ifdef PG_DEBUGMORE
PD("%O\n",a);
#endif
+ if(portal._forcetext)
+ portal->_setrowdesc(a); // Do not consume queued portal
+ else {
portal->_processrowdesc(a);
portal=0;
-
+ }
break;
}
case 'n': {
913:
string serror;
if(portal._tprepared)
storetiming(portal);
- array a, datarowdesc;
+
portal._bytesreceived+=msglen;
- datarowdesc=portal._datarowdesc;
+ array datarowdesc=portal._datarowdesc;
int cols=ci->read_int16();
#ifdef PG_DEBUG
#ifdef PG_DEBUGMORE
929:
int atext = portal._alltext; // cache locally for speed
int forcetext = portal._forcetext; // cache locally for speed
string cenc=_runtimeparameter[CLIENT_ENCODING];
- a=allocate(cols,UNDEFINED);
+ array a=allocate(cols,UNDEFINED);
msglen-=2+4*cols;
foreach(datarowdesc;int i;mapping m) {
int collen=ci->read_sint(4);
1086:
USERERROR(a2nls(lastmessage
+({pinpointerror(portal._query,msgresponse.P)})
+showbindings(portal)));
- case "57P01":case "57P02":case "57P03":die=1;
+ case "57P01":case "57P02":case "57P03":
preplastmessage(msgresponse);
- PD(a2nls(lastmessage));USERERROR(a2nls(lastmessage));
+ PD(a2nls(lastmessage));throw(0);
case "08P01":case "42P05":
errtype=protocolerror;
case "XX000":case "42883":case "42P01":
1163:
#endif
errtype=protocolunsupported;
} else {
- if(!waitforauthready)
- die=1;
+
lastmessage+=({
sprintf("Connection lost to database %s@%s:%d/%s %d\n",
user,_host,_port,database,backendpid)});
-
+ if(!waitforauthready)
+ throw(0);
USERERROR(a2nls(lastmessage));
}
break;
1199:
}
if(stringp(err)) {
.pgsql_util.pgsql_result or;
- if(!(or=portal))
+ if(!objectp(or=portal))
or=this;
if(!or._delayederror)
or._delayederror=err;
- if(portal)
+ if(objectp(portal))
portal->_releasesession();
portal=0;
continue;
1213:
_delayederror=err;
if(!ci->close() && !terminating && options.reconnect)
_connectfail();
+ if(err)
throw(err);
}
1235:
}
void _connectfail(void|mixed err) {
- if(err)
- _delayederror=err;
+ PD("Connect failed %O reconnectdelay %d\n",err,reconnectdelay);
if(!err || reconnectdelay) {
int tdelay;
switch(tdelay=reconnectdelay) {
1244:
reconnectdelay=RECONNECTDELAY;
break;
default:
+ if(err)
+ _delayederror=err;
if(options.reconnect!=-1)
return;
reconnectdelay=RECONNECTBACKOFF;
1253:
if(!waitforauthready)
waitforauthready=Thread.Condition();
lock=0;
+ PD("Schedule reconnect in %ds\n",tdelay);
+ _delayederror=0;
.pgsql_util.local_backend->call_out(reconnect,tdelay,1);
-
+ } else if(err)
+ _delayederror=err;
}
- }
+
protected int reconnect(void|int force,void|object tt) {
-
+ PD("(Re)connect\n");
if(!force) {
Thread.MutexKey lock=waitforauth->lock();
if(waitforauthready) {
1268:
lock=0;
}
if(c) {
+ PD("Close old connection\n");
reconnected++;
#ifdef PG_STATS
prepstmtused=0;
1277:
else
c->close();
c=0;
+ PD("Flushing old cache\n");
foreach(_prepareds;;mapping tp)
m_delete(tp,"preparedname");
if(!options.reconnect)
return 0;
}
-
+ PD("Actually start to connect\n");
qportals=Thread.Queue();
_readyforquerycount=1;
qportals->write(1);
1712:
return String.int2hex(i);
}
- final void throwdelayederror(object parent) {
+ final inline void throwdelayederror(object parent) {
.pgsql_util.throwdelayederror(parent);
}
1782:
array(string|int) paramValues;
array from;
if(bindings) {
+ if(forcetext)
+ q = .sql_util.emulate_bindings(q, bindings, this), paramValues=({});
+ else {
int pi=0,rep=0;
paramValues=allocate(sizeof(bindings));
from=allocate(sizeof(bindings));
1818:
q=replace(q,from=from[..rep],to=to[..rep]);
paramValues= pi ? paramValues[..pi-1] : ({});
from=({from,to,paramValues});
+ }
} else
- paramValues = ({});
+ paramValues=({});
if(String.width(q)>8)
ERROR("Wide string literals in %O not supported\n",q);
if(has_value(q,"\0"))
1831:
lock=0;
}
int tstart;
- if(forcetext) {
- if(bindings)
- q = .sql_util.emulate_bindings(q, bindings, this);
- } else if(forcecache==1
+ if(!forcetext && forcecache==1
|| forcecache!=0
&& (sizeof(q)>=MINPREPARELENGTH || .pgsql_util.cachealways[q])) {
object plugbuffer=c->start();
1860:
}
}
if(forcecache!=1 && .pgsql_util.createprefix->match(q)) {
- invalidatecache=1; // Flush cache on CREATE
+ invalidatecache=1; // Flush cache on CREATE
tp=UNDEFINED;
} else
_prepareds[q]=tp=([]);
1888:
portalsopened++;
#endif
clearmessage=1;
- object plugbuffer=c;
+
if(forcetext) { // FIXME What happens if portals are still open?
portal._unnamedportalkey=_unnamedportalmux->lock(1);
-
+ portal._portalname="";
portal->_openportal();
_readyforquerycount++;
Thread.MutexKey lock=unnamedstatement->lock(1);
- plugbuffer->start(1)->add_int8('Q')->add_hstring(q,4,4+1)->add_int8(0)
+ c->start(1)->add_int8('Q')->add_hstring(q,4,4+1)->add_int8(0)
->sendcmd(flushlogsend,portal);
lock=0;
PD("Simple query: %O\n",q);
} else {
- object parsebuffer;
+ object plugbuffer;
if(!sizeof(preparedname) || !tp || !tp.preparedname) {
if(!sizeof(preparedname))
preparedname=
1910:
// performance if it is omitted; seems like a flaw in the PostgreSQL
// server v8.3.3
PD("Parse statement %O=%O\n",preparedname,q);
- parsebuffer=plugbuffer->start()->add_int8('P')
+ plugbuffer=c->start()->add_int8('P')
->add_hstring(({preparedname,0,q,"\0\0\0"}),4,4)->add(PGFLUSH);
}
if(!tp || !tp.datatypeoid) {
PD("Describe statement %O\n",preparedname);
- (parsebuffer||plugbuffer->start())->add_int8('D')
+ (plugbuffer||c->start())->add_int8('D')
->add_hstring(({'S',preparedname,0}),4,4)->sendcmd(flushsend,portal);
} else {
- if(parsebuffer)
- parsebuffer->sendcmd();
+ if(plugbuffer)
+ plugbuffer->sendcmd();
#ifdef PG_STATS
skippeddescribe++;
#endif
1928:
portal._preparedname=preparedname;
if((portal._tprepared=tp) && tp.datatypeoid) {
mixed e=catch(portal->_preparebind(tp.datatypeoid));
- if(e && !portal._delayederror) {
- if(!stringp(e))
+ if(e && !portal._delayederror)
throw(e);
- portal._delayederror=e;
+
}
}
- }
+
throwdelayederror(portal);
return portal;
}