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

version» Context lines:

pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:49:   final void throwdelayederror(object parent) {    if(mixed err=parent._delayederror) {    parent._delayederror=UNDEFINED;    if(stringp(err))    err=({err,backtrace()[..<2]});    throw(err);    }   }      protected sctype mergemode(PGassist realbuffer,sctype mode) { -  switch(realbuffer->stashflushmode) { -  case sendout: -  if(mode!=flushsend) { -  mode=sendout; -  break; +  if(mode>realbuffer->stashflushmode) +  realbuffer->stashflushmode=mode; +  return realbuffer->stashflushmode;   } -  case flushsend: -  mode=flushsend; -  } -  return realbuffer->stashflushmode=mode; - } +       //! Some pgsql utility functions      class PGplugbuffer {    inherit Stdio.Buffer;       protected PGassist realbuffer;       final void create(PGassist _realbuffer) {    realbuffer=_realbuffer;
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:86:    error("pgsql.PGplugbuffer not allowed here\n");   #endif    return this;    }       final    void sendcmd(void|sctype mode,void|object portal) {    Thread.MutexKey lock=realbuffer->stashupdate->lock();    if(portal)    realbuffer->stashqueue->write(portal); +  if(mode==flushlogsend) +  mode=flushsend, realbuffer->stashqueue->write(1);    realbuffer->stash->add(this);    mode=mergemode(realbuffer,mode);    if(!--realbuffer->stashcount)    realbuffer->stashavail.signal();    lock=0;    this->clear();    if(lock=realbuffer->nostash->trylock(1)) {    realbuffer->started=lock; lock=0;    realbuffer->sendcmd(sendout);    }
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:120:    final function(:void) gottimeout;    final int timeout;    Thread.Mutex nostash;    Thread.MutexKey started;    Thread.Mutex stashupdate;    Thread.Queue stashqueue;    Thread.Condition stashavail;    Stdio.Buffer stash;    int stashflushmode;    int stashcount; +  int synctransact;   #ifdef PG_DEBUG    int queueoutidx;    int queueinidx;   #endif    -  +  inline void queueup(pgsql_result portal) { +  qportals->write(portal); portal->_synctransact=synctransact; +  PD(">%O %d %d Queue portal %d bytes\n",portal._portalname,++queueoutidx, +  synctransact,sizeof(this)); +  } +     final PGassist|PGplugbuffer start(void|int waitforreal) {    Thread.MutexKey lock;    if(lock=(waitforreal?nostash->lock:nostash->trylock)(1)) {    started=lock;    lock=stashupdate->lock(); -  if(stashcount) { +  if(stashcount)    stashavail.wait(lock);    add(stash); stash->clear(); -  foreach(stashqueue->try_read_array();;pgsql_result qp) { -  qportals->write(qp); -  PD(">%O %d Queue portal %d bytes\n",qp._portalname,++queueoutidx, -  sizeof(this)); -  } -  } +  foreach(stashqueue->try_read_array();;pgsql_result portal) +  queueup(portal);    lock=0;    return this;    }    stashcount++;    return PGplugbuffer(this);    }       protected final bool range_error(int howmuch) {    if(!howmuch)    return false;
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:191:    inline final string read(int w) { return i::read(w); }    inline final object read_buffer(int w) { return i::read_buffer(w); }    inline final int read_sint(int w) { return i::read_sint(w); }    inline final int read_int8() { return i::read_int8(); }    inline final int read_int16() { return i::read_int16(); }    inline final int read_int32() { return i::read_int32(); }    inline final string read_cstring() { return i::read_cstring(); }       final    void sendcmd(void|sctype mode,void|pgsql_result portal) { -  if(portal) { -  qportals->write(portal); -  PD(">%O %d Queue portal %d bytes\n",portal._portalname,++queueoutidx, -  sizeof(this)); +  if(portal) +  queueup(portal); +  if(mode==flushlogsend) { +  mode=flushsend; qportals->write(synctransact++); +  PD(">%O %d Queue simplequery %d bytes\n",portal._portalname, +  ++queueoutidx,sizeof(this));    }    if(started) {    Thread.MutexKey lock=stashupdate->lock();    if(sizeof(stash)) {    add(stash); stash->clear(); -  foreach(stashqueue->try_read_array();;pgsql_result qp) { -  qportals->write(qp); -  PD(">%O %d Queue portal %d bytes\n",qp._portalname,++queueoutidx, -  sizeof(this)); +  foreach(stashqueue->try_read_array();;pgsql_result portal) +  queueup(portal);    } -  } +     mode=mergemode(this,mode);    stashflushmode=keep;    lock=0;    } -  + outer: +  do {    switch(mode) { -  +  default: +  break outer; +  case syncsend: +  PD(">Sync %d %d Queue\n",synctransact,++queueoutidx); +  qportals->write(synctransact++); add(PGSYNC); +  break;    case flushsend: -  add(PGFLUSH); +     PD("Flush\n"); -  case sendout: -  if(towrite+=sizeof(this)) { +  add(PGFLUSH); +  case sendout:; +  } +  if(towrite=sizeof(this)) {    PD(">Sendcmd %O\n",((string)this)[..towrite-1]);    towrite-=output_to(socket,towrite);    } -  } +  } while(0);    started=0;    }       final void sendterminate() {    destruct(condition); // Delayed close() after flushing the output buffer    }       final int close() {    return socket->close();    }
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:281:    socket->set_nonblocking(read_cb,write_cb,0);    Thread.Thread(pgsqlsess->_processloop,this);    return;    };    pgsqlsess->_connectfail(err);    }       void create(object pgsqlsess,Thread.Queue _qportals,int nossl) {    i::create(); o::create();    qportals = _qportals; +  synctransact = 1;    condition=Thread.Condition();    mux=Thread.Mutex();    gottimeout=sendcmd; // Preset it with a NOP    timeout=128; // Just a reasonable amount    socket=Stdio.File();    nostash=Thread.Mutex();    stashupdate=Thread.Mutex();    stashqueue=Thread.Queue();    stashavail=Thread.Condition();    stash=Stdio.Buffer();
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:318:    int _fetchlimit;    int _alltext;    int _forcetext;       string _portalname;       int _bytesreceived;    int _rowsreceived;    int _inflight;    int _portalbuffersize; +  int _synctransact;    Thread.MutexKey _unnamedportalkey,_unnamedstatementkey;    protected Thread.Mutex closemux;    array _params;    string _statuscmdcomplete;    string _query;    Thread.Queue _datarows;    array(mapping(string:mixed)) _datarowdesc=({});    int _oldpbpos;    object _plugbuffer;    string _preparedname;
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:434:    }       void _openportal() {    _pgsqlsess->_portalsinflight++;    Thread.MutexKey lock=closemux->lock();    _state=bound;    lock=0;    _statuscmdcomplete=UNDEFINED;    }    -  int _closeportal(PGplugbuffer plugbuffer) { -  int retval=0; +  sctype _closeportal(void|PGplugbuffer plugbuffer) { +  sctype retval=keep;    PD("%O Try Closeportal %d\n",_portalname,_state);    Thread.MutexKey lock=closemux->lock();    _fetchlimit=0; // disables further Executes    switch(_state) {    case copyinprogress: -  +  if(plugbuffer) {    PD("CopyDone\n");    plugbuffer->add("c\0\0\0\4"); -  +  }    case bound:    _state=closed;    lock=0;    PD("Close portal %O\n",_portalname);    if(sizeof(_portalname)) { -  +  if(plugbuffer) {    plugbuffer->add_int8('C')->add_hstring(({'P',_portalname,0}),4,4); -  retval=1; +  retval=flushsend; +  }    } else    _unnamedportalkey=0; -  if(!--_pgsqlsess->_portalsinflight) { -  PD("Sync\n"); -  plugbuffer->add(PGSYNC); +  if(!--_pgsqlsess->_portalsinflight && plugbuffer) { +  _pgsqlsess->_readyforquerycount++;    _pgsqlsess->_pportalcount=0; -  retval=2; +  retval=syncsend;    }    }    lock=0;    return retval;    }       final void _processdataready(int gfetchlimit) {    _rowsreceived++;    if(_rowsreceived==1)    PD("<%O _fetchlimit %d=min(%d||1,%d), _inflight %d\n",_portalname,    _fetchlimit,(_portalbuffersize>>1)*_rowsreceived/_bytesreceived,    gfetchlimit,_inflight);    if(_fetchlimit) {    _fetchlimit=    min((_portalbuffersize>>1)*_rowsreceived/_bytesreceived||1,gfetchlimit); - #if STREAMEXECUTES +     Thread.MutexKey lock=closemux->lock();    if(_fetchlimit && _inflight<=_fetchlimit-1)    _sendexecute(_fetchlimit); - #ifdef PG_DEBUG +     else if(!_fetchlimit)    PD("<%O _fetchlimit %d, _inflight %d, skip execute\n",    _portalname,_fetchlimit,_inflight); - #endif +     lock=0; - #endif +     }    }       void _releasesession() {    _inflight=0;    _datarows->write(1);    object plugbuffer=c->start(1);    plugbuffer->sendcmd(_closeportal(plugbuffer));    _pgsqlsess=UNDEFINED;    }
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:507:    };    }       final void _sendexecute(int fetchlimit,void|PGplugbuffer plugbuffer) {    int flushmode;    PD("Execute portal %O fetchlimit %d\n",_portalname,fetchlimit);    if(!plugbuffer)    plugbuffer=c->start(1);    plugbuffer->add_int8('E')->add_hstring(_portalname,4,8+1)    ->add_int8(0)->add_int32(fetchlimit); -  if(!fetchlimit) { -  _closeportal(plugbuffer); -  flushmode=sendout; -  } else +  if(!fetchlimit) +  flushmode=_closeportal(plugbuffer)==syncsend?syncsend:flushsend; +  else    _inflight+=fetchlimit, flushmode=flushsend;    plugbuffer->sendcmd(flushmode,this);    }       //! @returns    //! One result row at a time.    //!    //! When using COPY FROM STDOUT, this method returns one row at a time    //! as a single string containing the entire row.    //!    //! @seealso    //! @[eof()], @[send_row()]    array(mixed) fetch_row() {    int|array datarow;    if(arrayp(datarow=_datarows->try_read()))    return datarow;    if(!datarow && !eoffound -  && ( - #ifdef PG_DEBUG -  PD("%O Block for datarow\n",_portalname), - #endif +  && (PD("%O Block for datarow\n",_portalname),    arrayp(datarow=_datarows->read())))    return datarow;    trydelayederror();    eoffound=1;    return 0;    }       //! @returns    //! Multiple result rows at a time (at least one).    //!