2017-11-10
2017-11-10 00:27:26 by Stephen R. van den Berg <srb@cuci.nl>
-
67879d254614050553bd0d039280cb1121462d46
(129 lines)
(+42/-87)
[
Show
| Annotate
]
Branch: 8.1
pgsql: Simplify and bolster the code by using Thread.ResourceCount.
23:
final Pike.Backend local_backend = Pike.SmallBackend();
private Thread.Mutex backendmux = Thread.Mutex();
- private int clientsregistered;
+ private Thread.ResourceCount clientsregistered = Thread.ResourceCount();
constant emptyarray = ({});
constant describenodata
108:
looponce=0;
if(lock=backendmux->trylock()) {
PD("Starting local backend\n");
- while (clientsregistered) { // Autoterminate when not needed
+ while (!clientsregistered->drained()) { // Autoterminate when not needed
mixed err;
if (err = catch(local_backend(4096.0)))
werror(describe_backtrace(err));
}
PD("Terminating local backend\n");
lock=0;
- looponce=clientsregistered;
+ looponce = !clientsregistered->drained();
}
} while(looponce);
}
//! Registers yourself as a user of this backend. If the backend
//! has not been started yet, it will be spawned automatically.
- final void register_backend() {
- if(!clientsregistered++)
+ final Thread.ResourceCountKey register_backend() {
+ int startbackend = clientsregistered->drained();
+ Thread.ResourceCountKey key = clientsregistered->acquire();
+ if (startbackend)
Thread.Thread(run_local_backend);
-
+ return key;
}
- //! Unregisters yourself as a user of this backend. If there are
- //! no longer any registered users, the backend will be terminated.
- final void unregister_backend() {
- --clientsregistered;
- }
-
+
final void throwdelayederror(object parent) {
if(mixed err=parent._delayederror) {
parent._delayederror=UNDEFINED;
172:
class bufcon {
inherit Stdio.Buffer;
- private int dirty;
+ private Thread.ResourceCountKey dirty;
#ifdef PG_DEBUGRACE
final bufcon `chain() {
182:
private conxion realbuffer;
- protected void create(conxion _realbuffer) {
+ private void create(conxion _realbuffer) {
realbuffer=_realbuffer;
}
- final int `stashcount() {
+ final Thread.ResourceCount `stashcount() {
return realbuffer->stashcount;
}
final bufcon start(void|int waitforreal) {
- dirty = 1;
- realbuffer->stashcount++;
- dirty = 2;
+ dirty = realbuffer->stashcount->acquire();
#ifdef PG_DEBUG
if(waitforreal)
error("pgsql.bufcon not allowed here\n");
215:
realbuffer->socket->query_fd(), mode, realbuffer->stashflushmode);
if (mode > realbuffer->stashflushmode)
realbuffer->stashflushmode = mode;
- dirty = 1;
- if(!--realbuffer->stashcount)
- dirty = 0, realbuffer->stashavail.signal();
- else
+
dirty = 0;
- lock=0;
+
this->clear();
if(lock=realbuffer->nostash->trylock(1)) {
#ifdef PG_DEBUGRACE
235:
#endif
}
}
-
- protected void _destruct() {
- switch (dirty) {
- case 1:
- werror("FIXME: Race condition detected %s\n",
- describe_backtrace(({"", backtrace()[..<1]})));
- if (!realbuffer->stashcount)
- break;
- case 2:
- Thread.MutexKey lock = realbuffer->shortmux->lock(2);
- if (!--realbuffer->stashcount)
- realbuffer->stashavail.signal();
- lock = 0;
- }
- }
+
};
class conxiin {
260:
final int procmsg;
private int didreadcb;
- protected bool range_error(int howmuch) {
+ protected final bool range_error(int howmuch) {
#ifdef PG_DEBUG
if(howmuch<=0)
error("Out of range %d\n",howmuch);
291:
return 0;
}
- protected void create() {
+ private void create() {
i::create();
fillreadmux=Thread.Mutex();
fillread=Thread.Condition();
300:
class sfile {
inherit Stdio.File;
- int query_fd() {
+ final int query_fd() {
return is_open() ? ::query_fd() : -1;
}
};
324:
final Thread.Condition stashavail;
final Stdio.Buffer stash;
final int stashflushmode;
- final int stashcount;
+ final Thread.ResourceCount stashcount;
final int synctransact;
#ifdef PG_DEBUGRACE
final mixed nostrack;
349:
#endif
started = lock;
lock=shortmux->lock();
- if(stashcount)
- PT(stashavail.wait(lock));
+ stashcount->wait_till_drained(lock);
mode = getstash(KEEP);
lock=0;
if (mode > KEEP)
457:
return -1;
}
- protected void _destruct() {
+ private void _destruct() {
PD("%d>Close conxion %d\n", socket ? socket->query_fd() : -1, !!nostash);
int|.pgsql_util.sql_result portal;
if (qportals) // CancelRequest does not use qportals
538:
catch(fd=socket->query_fd());
res=predef::sprintf("conxion fd: %d input queue: %d/%d "
"queued portals: %d output queue: %d/%d\n"
- "started: %d stashcount: %d\n",
+ "started: %d\n",
fd,sizeof(i),i->_size_object(),
qportals && qportals->size(), sizeof(this), _size_object(),
- !!started, stashcount);
+ !!started);
break;
}
return res;
}
- protected void create(object pgsqlsess,Thread.Queue _qportals,int nossl) {
+ private void create(object pgsqlsess,Thread.Queue _qportals,int nossl) {
o::create();
qportals = _qportals;
synctransact = 1;
559:
stashavail=Thread.Condition();
stashqueue=Thread.Queue();
stash=Stdio.Buffer();
+ stashcount = Thread.ResourceCount();
Thread.Thread(connectloop,pgsqlsess,nossl);
}
};
567: Inside #if defined(PG_DEBUGRACE)
class conxsess {
final conxion chain;
- protected void create(conxion parent) {
+ private void create(conxion parent) {
if (parent->started)
werror("Overwriting conxsess %s %s\n",
describe_backtrace(({"new ", backtrace()[..<1]})),
581: Inside #if defined(PG_DEBUGRACE)
chain = 0;
}
- protected void _destruct() {
+ private void _destruct() {
if (chain)
werror("Untransmitted conxsess %s\n",
describe_backtrace(({"", backtrace()[..<1]})));
617:
private int portalbuffersize;
private Thread.Mutex closemux;
private Thread.Queue datarows;
+ private Thread.ResourceCountKey stmtifkey, portalsifkey;
private array(mapping(string:mixed)) datarowdesc;
private array(int) datarowtypes; // types from datarowdesc
private string statuscmdcomplete;
632:
private function(:void) gottimeout;
private int timeout;
- private string _sprintf(int type) {
+ protected string _sprintf(int type) {
string res=UNDEFINED;
switch(type) {
case 'O':
1014:
if(sizeof(datarowtypes))
plugbuffer->add_ints(map(datarowtypes,oidformat),2);
else if (syncparse < 0 && !pgsqlsess->_wasparallelisable
- && pgsqlsess->_statementsinflight > 1) {
- lock=pgsqlsess->_shortmux->lock();
- // Decrement temporarily to account for ourselves
- if(--pgsqlsess->_statementsinflight) {
- pgsqlsess->_waittocommit++;
+ && !pgsqlsess->_statementsinflight->drained(1)) {
+ lock = pgsqlsess->_shortmux->lock();
PD("Commit waiting for statements to finish\n");
- catch(PT(pgsqlsess->_readyforcommit->wait(lock)));
- pgsqlsess->_waittocommit--;
+ catch(PT(pgsqlsess->_statementsinflight->wait_till_drained(lock, 1)));
}
- // Increment again to account for ourselves
- pgsqlsess->_statementsinflight++;
- }
+
lock=0;
PD("Bind portal %O statement %O\n",_portalname,_preparedname);
_fetchlimit=pgsqlsess->_fetchlimit;
1059:
_state=PARSING;
Thread.MutexKey lockc = pgsqlsess->_shortmux->lock();
if (syncparse || syncparse < 0 && pgsqlsess->_wasparallelisable) {
- if(pgsqlsess->_statementsinflight) {
- pgsqlsess->_waittocommit++;
+
PD("Commit waiting for statements to finish\n");
- // Do NOT put this in a function, it would require passing a lock
- // variable on the argumentstack to the function, which will cause
- // unpredictable lock release issues due to the extra copy on the stack
- catch(PT(pgsqlsess->_readyforcommit->wait(lockc)));
- pgsqlsess->_waittocommit--;
+ catch(PT(pgsqlsess->_statementsinflight->wait_till_drained(lockc)));
}
- }
- pgsqlsess->_statementsinflight++;
+ stmtifkey = pgsqlsess->_statementsinflight->acquire();
lockc = 0;
lock=0;
statuscmdcomplete=UNDEFINED;
1082:
lock = closemux->lock();
if (_state <= BOUND) {
_state = COMMITTED;
- lock = pgsqlsess->_shortmux->lock();
- if (!--pgsqlsess->_statementsinflight && pgsqlsess->_waittocommit) {
- PD("Signal no statements in flight\n");
- catch(pgsqlsess->_readyforcommit->signal());
+ stmtifkey = 0;
}
- }
+
lock = 0;
}
final void _bindportal() {
Thread.MutexKey lock = closemux->lock();
_state=BOUND;
- Thread.MutexKey lockc = pgsqlsess->_shortmux->lock();
- pgsqlsess->_portalsinflight++;
- lockc = 0;
+ portalsifkey = pgsqlsess->_portalsinflight->acquire();
lock=0;
}
1109:
case COPYINPROGRESS:
case COMMITTED:
case BOUND:
- --pgsqlsess->_portalsinflight;
+ portalsifkey = 0;
}
switch(_state) {
case BOUND:
case PARSING:
- --pgsqlsess->_statementsinflight;
+ stmtifkey = 0;
}
_state=CLOSED;
lock=0;
1151:
retval=FLUSHSEND;
} else
_unnamedportalkey=0;
- Thread.MutexKey lockc=pgsqlsess->_shortmux->lock();
- if(!--pgsqlsess->_portalsinflight) {
- if(!pgsqlsess->_waittocommit && !plugbuffer->stashcount
- && transtype != TRANSBEGIN)
+ portalsifkey = 0;
+ if (pgsqlsess->_portalsinflight->drained()) {
+ if (plugbuffer->stashcount->drained() && transtype != TRANSBEGIN)
/*
* stashcount will be non-zero if a parse request has been queued
* before the close was initiated.
1163:
pgsqlsess->_readyforquerycount++, retval=SYNCSEND;
pgsqlsess->_pportalcount=0;
}
- lockc=0;
+
}
lock=0;
return retval;