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

version» Context lines:

pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:78:   #else   #define MUTEX Thread.Mutex   #endif      //! The instance of the pgsql dedicated backend.   final Pike.Backend local_backend;      private Pike.Backend cb_backend;   private Result qalreadyprinted;   private Thread.Mutex backendmux = Thread.Mutex(); - private Thread.ResourceCount clientsregistered = Thread.ResourceCount(); + final multiset(proxy) clients = set_weak_flag((<>), Pike.WEAK);      constant emptyarray = ({});   constant describenodata    = (["datarowdesc":emptyarray, "datarowtypes":emptyarray,    "datatypeoid":emptyarray]);   private constant censoroptions = (<"use_ssl", "force_ssl",    "cache_autoprepared_statements", "reconnect", "text_query", "is_superuser",    "server_encoding", "server_version", "integer_datetimes",    "session_authorization">);   
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:141:    * tradeoff.    */   private Regexp execfetchlimit    = iregexp("^\a*((UPDA|DELE)TE|INSERT)\a|\aLIMIT\a+[1-9][; \t\f\r\n]*$");      private void default_backend_runs() { // Runs as soon as the    cb_backend = Pike.DefaultBackend; // DefaultBackend has started   }      private void create() { +  atexit(_destruct);    // Run callbacks from our local_backend until DefaultBackend has started    cb_backend = local_backend = Pike.SmallBackend();    call_out(default_backend_runs, 0);   }    -  + private void _destruct() { +  foreach (clients; proxy client; ) +  destruct(client); + } +    private Regexp iregexp(string expr) {    Stdio.Buffer ret = Stdio.Buffer();    foreach (expr; ; int c)    if (c >= 'A' && c <= 'Z')    ret->add('[', c, c + 'a' - 'A', ']');    else if (c == '\a') // Replace with generic whitespace    ret->add("[ \t\f\r\n]");    else    ret->add_int8(c);    return Regexp(ret->read());
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:172:    }   }      private void run_local_backend() {    Thread.MutexKey lock;    int looponce;    do {    looponce = 0;    if (lock = backendmux->trylock()) {    PD("Starting local backend\n"); -  while (!clientsregistered->drained() // Autoterminate when not needed +  while (sizeof(clients) // Autoterminate when not needed    || sizeof(local_backend->call_out_info())) {    mixed err;    if (err = catch(local_backend(4096.0)))    master()->handle_error(err);    }    PD("Terminating local backend\n");    lock = 0; -  looponce = !clientsregistered->drained(); +  looponce = sizeof(clients);    }    } while (looponce);   }      //! Registers yourself as a user of this backend. If the backend   //! has not been started yet, it will be spawned automatically. - final Thread.ResourceCountKey register_backend() { -  int startbackend = clientsregistered->drained(); -  Thread.ResourceCountKey key = clientsregistered->acquire(); + final void register_backend(proxy client) { +  int startbackend = !sizeof(clients); +  clients[client] = 1;    if (startbackend)    Thread.Thread(run_local_backend); -  return key; +    }      final void throwdelayederror(Result|proxy parent) {    if (mixed err = parent->delayederror) {    if (!objectp(parent->pgsqlsess))    parent->untolderror = 0;    else if (parent->pgsqlsess)    parent->pgsqlsess->untolderror = 0;    parent.delayederror = 0;    if (stringp(err))
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:1893:    Thread.Thread(run_result_array_cb, callback, args);    }      };      class proxy {    final int _fetchlimit = FETCHLIMIT;    final MUTEX unnamedportalmux;    final MUTEX unnamedstatement;    private Thread.MutexKey termlock; -  private Thread.ResourceCountKey backendreg; +     final Thread.ResourceCount portalsinflight, statementsinflight;    final int(0..1) wasparallelisable;    final int(0..1) intransaction;       final conxion c;    private string cancelsecret;    private int backendpid;    final int(-128..127) backendstatus;    final mapping(string:mixed) options;    private array(string) lastmessage = emptyarray;
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:1958:    this::database = database;    this::options = options;       if (!host) host = PGSQL_DEFAULT_HOST;    if (has_value(host,":") && sscanf(host,"%s:%d", host, port) != 2)    error("Error in parsing the hostname argument\n");    this::host = host;       if (!port)    port = PGSQL_DEFAULT_PORT; -  backendreg = register_backend(); +  register_backend(this);    shortmux = MUTEX();    PD("Connect\n");    waitforauthready = Thread.Condition();    qportals = Thread.Queue();    readyforquerycount = 1;    qportals->write(1);    if (!(c = conxion(this, qportals, 0)))    error("Couldn't connect to database on %s:%d\n", host, port);    runtimeparameter = ([]);    unnamedportalmux = MUTEX();
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:2719:    break;    case NOERROR:    continue; // Normal production loop    }    error(a2nls(lastmessage += ({msg})));    }    }; // We only get here if there is an error    if (err == MAGICTERMINATE) { // Announce connection termination to server    catch {    void|bufcon|conxsess cs = ci->start(); -  CHAIN(cs)->add("X\0\0\0\4"); +  CHAIN(cs)->add(PGSYNC)->add("X\0\0\0\4");    cs->sendcmd(SENDOUT);    };    terminating = 1;    err = 0;    } else if (stringp(err)) {    Result or;    if (!objectp(or = portal))    or = this;    if (!or.delayederror)    or.delayederror = err;
pike.git/lib/modules/Sql.pmod/pgsql_util.pmod:2787:    lock = unnamedstatement->lock(1);    if (c)    c->purge();    }    destruct(waitforauthready);    }       private void _destruct() {    string errstring;    mixed err = catch(close()); -  backendreg = 0; +  clients[this] = 0;    if (untolderror) {    /*    * Flush out any asynchronously reported errors to stderr; because we are    * inside a destructor, throwing an error will not work anymore.    * Warnings will be silently discarded at this point.    */    lastmessage = filter(lastmessage, lambda(string val) {    return has_prefix(val, "ERROR ") || has_prefix(val, "FATAL "); });    if (err || (err = catch(errstring = geterror(1))))    werror(describe_backtrace(err));