pike.git / lib / modules / Sql.pmod / pgsql_util.pmod

version» Context lines:

pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:423:    final int _state;    final int _fetchlimit;    private int alltext;    final int _forcetext;       final string _portalname;       private int rowsreceived;    private int inflight;    private int portalbuffersize; -  private Stdio.Buffer prepbuffer; -  private Thread.Condition prepbufferready; -  private Thread.Mutex prepbuffermux; +     private Thread.Mutex closemux;    private Thread.Queue datarows;    private array(mapping(string:mixed)) datarowdesc; -  +  private array(int) datarowtypes; // cached types from datarowdesc    private string statuscmdcomplete;    private int bytesreceived;    final int _synctransact;    final Thread.Condition _ddescribe;    final Thread.Mutex _ddescribemux;    final Thread.MutexKey _unnamedportalkey,_unnamedstatementkey;    final array _params;    final string _query;    final string _preparedname;    final mapping(string:mixed) _tprepared;
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:450:    private string _sprintf(int type, void|mapping flags) {    string res=UNDEFINED;    switch(type) {    case 'O':    res=sprintf("sql_result state: %d numrows: %d eof: %d inflight: %d\n"    "query: %O\n"    "fd: %O portalname: %O datarows: %d"    " laststatus: %s\n",    _state,rowsreceived,eoffound,inflight,    _query,c?->socket?->query_fd(), -  _portalname,datarowdesc&&sizeof(datarowdesc), +  _portalname,datarowtypes&&sizeof(datarowtypes),    statuscmdcomplete||(_unnamedstatementkey?"*parsing*":""));    break;    }    return res;    }       protected void create(object _pgsqlsess,conxion _c,string query,    int _portalbuffersize,int alltyped,array params,int forcetext) {    pgsqlsess = _pgsqlsess;    cr = (c = _c)->i;    _query = query;    datarows = Thread.Queue();    _ddescribe=Thread.Condition();    _ddescribemux=Thread.Mutex();    closemux=Thread.Mutex(); -  prepbufferready=Thread.Condition(); -  prepbuffermux=Thread.Mutex(); +     portalbuffersize=_portalbuffersize;    alltext = !alltyped;    _params = params;    _forcetext = forcetext;    _state = PORTALINIT;    }       //! Returns the command-complete status for this query.    //!    //! @seealso
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:512:    final void _storetiming() {    if(_tprepared) {    _tprepared.trun=gethrtime()-_tprepared.trunstart;    m_delete(_tprepared,"trunstart");    _tprepared = UNDEFINED;    }    }       private void waitfordescribe() {    Thread.MutexKey lock=_ddescribemux->lock(); -  if(!datarowdesc) +  if(!datarowtypes)    _ddescribe->wait(lock);    lock=0;    }       //! @seealso    //! @[Sql.sql_result()->num_fields()]    int num_fields() { -  if(!datarowdesc) +  if(!datarowtypes)    waitfordescribe();    trydelayederror(); -  return sizeof(datarowdesc); +  return sizeof(datarowtypes);    }       //! @seealso    //! @[Sql.sql_result()->num_rows()]    int num_rows() {    trydelayederror();    return rowsreceived;    }       private inline void trydelayederror() {
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:548:    //! @seealso    //! @[Sql.sql_result()->eof()]    int eof() {    trydelayederror();    return eoffound;    }       //! @seealso    //! @[Sql.sql_result()->fetch_fields()]    array(mapping(string:mixed)) fetch_fields() { -  if(!datarowdesc) +  if(!datarowtypes)    waitfordescribe();    trydelayederror();    return datarowdesc+({});    }      #ifdef PG_DEBUG    final int   #else    final void   #endif    _decodedata(int msglen,string cenc) {    _storetiming();    string serror;    bytesreceived+=msglen;    int cols=cr->read_int16();    array a=allocate(cols,!alltext&&Val.null);   #ifdef PG_DEBUG    msglen-=2+4*cols;   #endif -  foreach(datarowdesc;int i;mapping m) { +  foreach(datarowtypes;int i;int typ) {    int collen=cr->read_sint(4);    if(collen>0) {   #ifdef PG_DEBUG    msglen-=collen;   #endif    mixed value; -  switch(int typ=m.type) { +  switch(typ) {    case FLOAT4OID:   #if SIZEOF_FLOAT>=8    case FLOAT8OID:   #endif    if(!alltext) {    value=(float)cr->read(collen);    break;    }    default:value=cr->read(collen);    break;
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:640:    _processdataready(a);    if(serror)    error(serror);   #ifdef PG_DEBUG    return msglen;   #endif    }       final void _setrowdesc(array(mapping(string:mixed)) drowdesc) {    Thread.MutexKey lock=_ddescribemux->lock(); -  datarowdesc=drowdesc; +  datarowtypes=map(datarowdesc=drowdesc,lambda(mapping m){return m.type;});    _ddescribe->broadcast();    lock=0;    }       final void _preparebind(array dtoid) {    array(string|int) paramValues=_params?_params[2]:({});    if(sizeof(dtoid)!=sizeof(paramValues))    SUSERERROR("Invalid number of bindings, expected %d, got %d\n",    sizeof(dtoid),sizeof(paramValues)); -  Thread.MutexKey lock=prepbuffermux->lock(); +  Thread.MutexKey lock=_ddescribemux->lock();    if(!_portalname) {    _portalname=(_unnamedportalkey=pgsqlsess._unnamedportalmux->trylock(1))    ? "" : PORTALPREFIX   #ifdef PG_DEBUG    +(string)(c->socket->query_fd())+"_"   #endif    +int2hex(pgsqlsess._pportalcount++);    lock=0;   #ifdef PG_DEBUGMORE    PD("ParamValues to bind: %O\n",paramValues);
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:781:    break;    case OIDOID:    case INT4OID:    plugbuffer->add_int32(4)->add_int32((int)value);    break;    case INT2OID:    plugbuffer->add_int32(2)->add_int16((int)value);    break;    }    } -  if(_tprepared) -  if(_tprepared.datarowdesc) -  gotdatarowdesc(plugbuffer); -  else if(dontcacheprefix->match(_query)) // Don't cache FETCH/COPY +  if(!datarowtypes) { +  if(_tprepared && dontcacheprefix->match(_query))    m_delete(pgsqlsess->_prepareds,_query),_tprepared=0; -  if(prepbufferready) { -  lock=prepbuffermux->lock(); -  prepbuffer=plugbuffer; -  if(prepbufferready) -  prepbufferready->signal(); +  waitfordescribe();    } -  } -  lock=0; -  } -  -  final void _processrowdesc(array(mapping(string:mixed)) datarowdesc) { -  _setrowdesc(datarowdesc); -  if(_tprepared) -  _tprepared.datarowdesc=datarowdesc; -  if(prepbufferready) -  Thread.Thread(gotdatarowdesc); // Do not use callout, it deadlocks -  } -  -  private void gotdatarowdesc(void|Stdio.Buffer plugbuffer) { -  Thread.MutexKey lock=prepbuffermux->lock(); -  if(!plugbuffer) { -  if(!prepbuffer && prepbufferready) -  prepbufferready->wait(lock); -  plugbuffer=prepbuffer; -  prepbuffer=0; // Free memory when plugbuffer leaves scope -  } -  if(!prepbufferready || _state>=CLOSING) +  if(_state>=CLOSING)    lock=_unnamedstatementkey=0;    else { -  prepbufferready->signal(); -  prepbufferready=0; // Make sure we do this exactly once -  lock=0; -  plugbuffer->add_int16(sizeof(datarowdesc)); -  if(sizeof(datarowdesc)) -  foreach(datarowdesc;;mapping col) -  plugbuffer->add_int16(oidformat(col.type)); +  plugbuffer->add_int16(sizeof(datarowtypes)); +  if(sizeof(datarowtypes)) +  foreach(datarowtypes;;int typ) +  plugbuffer->add_int16(oidformat(typ));    else if(commitprefix->match(_query)) { -  +     lock=pgsqlsess->_shortmux->lock();    if(pgsqlsess->_portalsinflight) {    pgsqlsess->_waittocommit++;    PD("Commit waiting for portals to finish\n");    pgsqlsess->_readyforcommit->wait(lock);    pgsqlsess->_waittocommit--;    } -  lock=0; +     } -  +  lock=0;    PD("Bind portal %O statement %O\n",_portalname,_preparedname);    _fetchlimit=pgsqlsess->_fetchlimit;    _openportal();    conxion bindbuffer=c->start(1);    _unnamedstatementkey=0;    bindbuffer->add_int8('B')->add_hstring(plugbuffer,4,4);    if(!_tprepared && sizeof(_preparedname))    closestatement(bindbuffer,_preparedname);    _sendexecute(_fetchlimit    && !(cachealways[_query]    || sizeof(_query)>=MINPREPARELENGTH &&    execfetchlimit->match(_query))    && _fetchlimit,bindbuffer);    } -  +  } else +  lock=0;    }    -  +  final void _processrowdesc(array(mapping(string:mixed)) datarowdesc) { +  _setrowdesc(datarowdesc); +  if(_tprepared) +  _tprepared.datarowdesc=datarowdesc; +  } +     final void _openportal() {    pgsqlsess->_portalsinflight++;    Thread.MutexKey lock=closemux->lock();    _state=BOUND;    lock=0;    statuscmdcomplete=UNDEFINED;    }       final void _purgeportal() {    _unnamedportalkey=_unnamedstatementkey=0;
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:939:    _sendexecute(_fetchlimit);    else if(!_fetchlimit)    PD("<%O _fetchlimit %d, inflight %d, skip execute\n",    _portalname,_fetchlimit,inflight);    lock=0;    }    }       private void releaseconditions() {    pgsqlsess=0; -  Thread.MutexKey lock; -  if(prepbufferready) { -  lock=prepbuffermux->lock(); -  if(prepbufferready) -  prepbufferready->signal(); -  } -  if(!datarowdesc) { -  lock=_ddescribemux->lock(); -  datarowdesc=({}); +  if(!datarowtypes) { +  Thread.MutexKey lock=_ddescribemux->lock(); +  datarowtypes=datarowdesc=({});    _ddescribe->broadcast(); -  } +     lock=0;    } -  +  }       final void _releasesession(void|string statusccomplete) {    if(statusccomplete && !statuscmdcomplete)    statuscmdcomplete=statusccomplete;    inflight=0;    conxion plugbuffer=c->start(1);    plugbuffer->sendcmd(_closeportal(plugbuffer));    _state=CLOSED;    datarows->write(1); // Signal EOF    releaseconditions();