Branch: Tag:

2017-06-27

2017-06-27 10:31:31 by Stephen R. van den Berg <srb@cuci.nl>

pgsql: Trim in-flight portal stack aware of transactions in progress.

68:   final int _portalsinflight;   final int _statementsinflight;   final int _wasparallelisable; + final int _intransaction;      private .pgsql_util.conxion c;   private string cancelsecret;
641: Inside #if defined(PG_DEBUG)
  #ifdef PG_DEBUG    PD("Processloop\n");    + #ifdef PG_DEBUGMORE +  void showportalstack(string label) { +  PD(sprintf(">>>>>>>>>>> Portalstack %s: %O\n", label, portal)); +  foreach(qportals->peek_array();;int|.pgsql_util.sql_result qp) +  PD(" =========== Portal: %O\n",qp); +  PD("<<<<<<<<<<<<<< Portalstack end\n"); +  }; + #endif    void showportal(int msgtype) {    if(objectp(portal))    PD("%d<%O %d %c switch portal\n",
658: Inside #if defined(PG_DEBUG)
   datarowdebug=0; datarowdebugcount=0;    }   #endif + #ifdef PG_DEBUGMORE +  showportalstack("LOOPTOP"); + #endif    if(!sizeof(cr)) { // Preliminary check, fast path    Thread.MutexKey lock=cr->fillreadmux->lock();    if(!sizeof(cr)) { // Check for real
826:    msglen-=4;   #endif    break; -  case 'Z': +  case 'Z': {    backendstatus=cr->read_int8();   #ifdef PG_DEBUG    msglen-=4+1;    PD("ReadyForQuery %c\n",backendstatus);   #endif -  for(;objectp(portal);portal=qportals->read()) { + #ifdef PG_DEBUGMORE +  showportalstack("READYFORQUERY"); + #endif +  int keeplooking; +  do +  for(keeplooking = 0; objectp(portal); portal = qportals->read()) {   #ifdef PG_DEBUG    showportal(msgtype);   #endif -  +  if (backendstatus == 'I' && _intransaction +  && portal->transtype != TRANSEND) +  keeplooking = 1;    portal->_purgeportal();    } -  +  while (keeplooking && (portal = qportals->read())); +  if (backendstatus == 'I') +  _intransaction = 0;    foreach(qportals->peek_array();;.pgsql_util.sql_result qp) {    if(objectp(qp) && qp._synctransact && qp._synctransact<=portal) {    PD("Checking portal %O %d<=%d\n",
846:    }    }    portal=0; + #ifdef PG_DEBUGMORE +  showportalstack("AFTER READYFORQUERY"); + #endif    _readyforquerycount--;    if(readyforquery_cb)    readyforquery_cb(),readyforquery_cb=0;    destruct(waitforauthready);    break; -  +  }    case '1':   #ifdef PG_DEBUG -  PD("ParseComplete\n"); +  PD("ParseComplete portal %O\n", portal);    msglen-=4;   #endif    break;
944: Inside #if defined(PG_DEBUG)
   msglen-=4;    PD("%O BindComplete\n",portal._portalname);   #endif -  if(tp=portal._tprepared) { -  int tend=gethrtime(); -  int tstart=tp.trun; -  if(tend==tstart) +  if (tp=portal._tprepared) { +  int tend = gethrtime(); +  int tstart = tp.trun; +  if (tend == tstart)    m_delete(_prepareds,portal._query);    else {    tp.hits++;    totalhits++; -  if(!tp.preparedname) { -  if(sizeof(portal._preparedname)) -  tp.preparedname=portal._preparedname; -  tstart=tend-tstart; -  if(!tp.tparse || tp.tparse>tstart) -  tp.tparse=tstart; +  if (!tp.preparedname) { +  if (sizeof(portal._preparedname)) { +  PD("Finalising stored statement %s\n", portal._preparedname); +  tp.preparedname = portal._preparedname;    } -  tp.trunstart=tend; +  tstart = tend - tstart; +  if (!tp.tparse || tp.tparse>tstart) +  tp.tparse = tstart;    } -  +  tp.trunstart = tend;    } -  +  }    break;    }    case 'D':
971: Inside #if defined(PG_DEBUG)
   PD("%O DataRow %d bytes\n",portal._portalname,msglen);   #endif    datarowdebugcount++; -  if(!datarowdebug) -  datarowdebug=sprintf( +  if (!datarowdebug) +  datarowdebug = sprintf(    "%O DataRow %d bytes",portal._portalname,msglen);   #endif   #ifdef PG_DEBUG
1003:   #else    cr->consume(1);   #endif + #ifdef PG_DEBUGMORE +  showportalstack("COMMANDCOMPLETE"); + #endif    portal->_releasesession(s);    portal=0;    break;
1012: Inside #if defined(PG_DEBUG)
   PD("EmptyQueryResponse %O\n",portal._portalname);    msglen-=4;   #endif + #ifdef PG_DEBUGMORE +  showportalstack("EMPTYQUERYRESPONSE"); + #endif    portal->_releasesession();    portal=0;    break;
1042:    portal=0;    break;    case 'E': { -  if (_portalsinflight <= 1 && !_readyforquerycount) + #ifdef PG_DEBUGMORE +  showportalstack("ERRORRESPONSE"); + #endif +  if (!_portalsinflight && !_readyforquerycount)    sendsync();    PD("%O ErrorResponse %O\n",    objectp(portal)&&(portal._portalname||portal._preparedname),
1081:    switch(msgresponse.S) {    case "PANIC":werror(a2nls(lastmessage));    } -  case "25P02": // Preserve last error message -  USERERROR(a2nls(lastmessage)); +  case "25P02": // Preserve last error message +  USERERROR(a2nls(lastmessage)); // Implicitly closed portal    }    break;    }
1179:    or=this;    if(!or._delayederror)    or._delayederror=err; + #ifdef PG_DEBUGMORE +  showportalstack("THROWN"); + #endif    if(objectp(portal))    portal->_releasesession();    portal=0;
1876:    ERROR("Querystring %O contains invalid literal nul-characters\n",q);    mapping(string:mixed) tp;    int tstart; +  /* +  * FIXME What happens with regards to this detection when presented with +  * multistatement text-queries? +  */ +  int transtype = .pgsql_util.transendprefix->match(q) ? TRANSEND +  : .pgsql_util.transbeginprefix->match(q) ? TRANSBEGIN : NOTRANS;    if(!forcetext && forcecache==1    || forcecache!=0 -  && (sizeof(q)>=MINPREPARELENGTH || .pgsql_util.cachealways[q])) { +  && (sizeof(q)>=MINPREPARELENGTH || transtype != NOTRANS)) {    object plugbuffer;    while(catch(plugbuffer=c->start()))    reconnect();
1926:    } else // sql_result autoassigns to portal    tp=UNDEFINED;    .pgsql_util.sql_result portal; -  portal=.pgsql_util.sql_result(this,c,q, -  portalbuffersize, _alltyped, from, forcetext, timeout, syncparse); +  portal=.pgsql_util.sql_result(this,c,q, portalbuffersize, _alltyped, from, +  forcetext, timeout, syncparse, transtype);    portal._tprepared=tp;   #ifdef PG_STATS    portalsopened++;
1965:    ->add(PGFLUSH)   #endif    ; -  } +  } else +  PD("Using prepared statement for %O\n", q);    portal._preparedname=preparedname;    if(!tp || !tp.datatypeoid) {    PD("Describe statement %O\n",preparedname);