Beispiel #1
0
static void testHashScale(MprTestGroup *gp)
{
    MprHash     *table;
    MprKey      *sp;
    char        *str;
    char        name[80], *address;
    int         i;

    table = mprCreateHash(HASH_COUNT, 0);
    assert(mprGetHashLength(table) == 0);

    /*
        All inserts below will insert allocated strings. We must free before
        deleting the table.
     */
    for (i = 0; i < HASH_COUNT; i++) {
        mprSprintf(name, sizeof(name), "name.%d", i);
        address = sfmt("%d Park Ave", i);
        sp = mprAddKey(table, name, address);
        assert(sp != 0);
    }
    assert(mprGetHashLength(table) == HASH_COUNT);

    /*
        Check data entered into the hash
     */
    for (i = 0; i < HASH_COUNT; i++) {
        mprSprintf(name, sizeof(name), "name.%d", i);
        str = mprLookupKey(table, name);
        assert(str != 0);
        address = sfmt("%d Park Ave", i);
        assert(strcmp(str, address) == 0);
    }
}
Beispiel #2
0
/*
    grid = ediMakeGrid("[ \
        { id: '1', country: 'Australia' }, \
        { id: '2', country: 'China' }, \
    ]");
 */
EdiGrid *ediMakeGrid(cchar *json)
{
    MprHash     *obj, *row;
    MprKey      *kp;
    EdiGrid     *grid;
    EdiRec      *rec;
    int         r, nrows, nfields;

    if ((obj = mprDeserialize(json)) == 0) {
        return 0;
    }
    nrows = mprGetHashLength(obj);
    if ((grid = ediCreateBareGrid(NULL, "", nrows)) == 0) {
        return 0;
    }
    for (r = 0, ITERATE_KEYS(obj, kp)) {
        if (kp->type != MPR_JSON_OBJ) {
            continue;
        }
        row = (MprHash*) kp->data;
        nfields = mprGetHashLength(row);
        if ((rec = ediCreateBareRec(NULL, "", nfields)) == 0) {
            return 0;
        }
        if (ediSetFields(rec, row) == 0) {
            return 0;
        }
        grid->records[r++] = rec;
    }
    return 0;
}
Beispiel #3
0
bool mprRemoveCache(MprCache *cache, cchar *key)
{
    CacheItem   *item;
    bool        result;

    mprAssert(cache);
    mprAssert(key && *key);

    if (cache->shared) {
        cache = cache->shared;
        mprAssert(cache == shared);
    }
    lock(cache);
    if (key) {
        if ((item = mprLookupKey(cache->store, key)) != 0) {
            cache->usedMem -= (slen(key) + slen(item->data));
            mprRemoveKey(cache->store, key);
            result = 1;
        } else {
            result = 0;
        }

    } else {
        /* Remove all keys */
        result = mprGetHashLength(cache->store) ? 1 : 0;
        cache->store = mprCreateHash(CACHE_HASH_SIZE, 0);
        cache->usedMem = 0;
    }
    unlock(cache);
    return result;
}
Beispiel #4
0
/*
    rec = ediMakeRec("{ id: 1, title: 'Message One', body: 'Line one' }");
 */
EdiRec *ediMakeRec(cchar *json)
{
    MprHash     *obj;
    MprKey      *kp;
    EdiRec      *rec;
    EdiField    *fp;
    int         f, nfields;

    if ((obj = mprDeserialize(json)) == 0) {
        return 0;
    }
    nfields = mprGetHashLength(obj);
    if ((rec = ediCreateBareRec(NULL, "", nfields)) == 0) {
        return 0;
    }
    for (f = 0, ITERATE_KEYS(obj, kp)) {
        if (kp->type == MPR_JSON_ARRAY || kp->type == MPR_JSON_OBJ) {
            continue;
        }
        fp = &rec->fields[f++];
        fp->valid = 1;
        fp->name = kp->key;
        fp->value = kp->data;
        fp->type = EDI_TYPE_STRING;
        fp->flags = 0;
    }
    return rec;
}
Beispiel #5
0
static void testIsTableEmpty(MprTestGroup *gp)
{
    MprHash     *table;

    table = mprCreateHash(0, 0);
    assert(table != 0);

    assert(mprGetHashLength(table) == 0);
    assert(mprGetFirstKey(table) == 0);
    assert(mprLookupKey(table, "") == 0);
}
Beispiel #6
0
static void finalizeFlash(HttpConn *conn)
{
    EspReq  *req;

    req = conn->reqData;
    if (req->flash && mprGetHashLength(req->flash) > 0) {
        /*
            If the session does not exist, this will create one. However, must not have
            emitted the headers, otherwise cannot inform the client of the session cookie.
        */
        httpSetSessionObj(conn, ESP_FLASH_VAR, req->flash);
    }
}
Beispiel #7
0
/*
    Map options to an attribute string. Remove all internal control specific options and transparently handle URI link options.
    WARNING: this returns a non-cloned reference and relies on no GC yield until the returned value is used or cloned.
    This is done as an optimization to reduce memeory allocations.
 */
static cchar *map(HttpConn *conn, MprHash *options)
{
    Esp         *esp;
    EspReq      *req;
    MprHash     *params;
    MprKey      *kp;
    MprBuf      *buf;
    cchar       *value;
    char        *pstr;

    if (options == 0 || mprGetHashLength(options) == 0) {
        return MPR->emptyString;
    }
    req = conn->data;
    if (httpGetOption(options, EDATA("refresh"), 0) && !httpGetOption(options, "id", 0)) {
        httpAddOption(options, "id", sfmt("id_%d", req->lastDomID++));
    }
    esp = MPR->espService;
    buf = mprCreateBuf(-1, -1);
    for (kp = 0; (kp = mprGetNextKey(options, kp)) != 0; ) {
        if (kp->type != MPR_JSON_OBJ && kp->type != MPR_JSON_ARRAY && !mprLookupKey(esp->internalOptions, kp->key)) {
            mprPutCharToBuf(buf, ' ');
            value = kp->data;
            /*
                Support link template resolution for these options
             */
            if (smatch(kp->key, EDATA("click")) || smatch(kp->key, EDATA("remote")) || smatch(kp->key, EDATA("refresh"))) {
                value = httpUriEx(conn, value, options);
                if ((params = httpGetOptionHash(options, "params")) != 0) {
                    pstr = (char*) "";
                    for (kp = 0; (kp = mprGetNextKey(params, kp)) != 0; ) {
                        pstr = sjoin(pstr, mprUriEncode(kp->key, MPR_ENCODE_URI_COMPONENT), "=", 
                            mprUriEncode(kp->data, MPR_ENCODE_URI_COMPONENT), "&", NULL);
                    }
                    if (pstr[0]) {
                        /* Trim last "&" */
                        pstr[strlen(pstr) - 1] = '\0';
                    }
                    mprPutToBuf(buf, "%s-params='%s", params);
                }
            }
            mprPutStringToBuf(buf, kp->key);
            mprPutStringToBuf(buf, "='");
            mprPutStringToBuf(buf, value);
            mprPutCharToBuf(buf, '\'');
        }
    }
    mprAddNullToBuf(buf);
    return mprGetBufStart(buf);
}
Beispiel #8
0
static void testIterateHash(MprTestGroup *gp)
{
    MprHash     *table;
    MprKey      *sp;
    char        name[80], address[80];
    cchar       *where;
    int         count, i, check[HASH_COUNT];

    table = mprCreateHash(HASH_COUNT, 0);

    memset(check, 0, sizeof(check));

    /*
        Fill the table
     */
    for (i = 0; i < HASH_COUNT; i++) {
        mprSprintf(name, sizeof(name), "Bit longer name.%d", i);
        mprSprintf(address, sizeof(address), "%d Park Ave", i);
        sp = mprAddKey(table, name, sclone(address));
        assert(sp != 0);
    }
    assert(mprGetHashLength(table) == HASH_COUNT);

    /*
        Check data entered into the table
     */
    sp = mprGetFirstKey(table);
    count = 0;
    while (sp) {
        assert(sp != 0);
        where = sp->data;
        assert(isdigit((int) where[0]) != 0);
        i = atoi(where);
        check[i] = 1;
        sp = mprGetNextKey(table, sp);
        count++;
    }
    assert(count == HASH_COUNT);

    count = 0;
    for (i = 0; i < HASH_COUNT; i++) {
        if (check[i]) {
            count++;
        }
    }
    assert(count == HASH_COUNT);
}
Beispiel #9
0
PUBLIC void espRenderFlash(HttpConn *conn, cchar *kinds)
{
    EspReq      *req;
    MprKey      *kp;
    cchar       *msg;
   
    req = conn->data;
    if (kinds == 0 || req->flash == 0 || mprGetHashLength(req->flash) == 0) {
        return;
    }
    for (kp = 0; (kp = mprGetNextKey(req->flash, kp)) != 0; ) {
        msg = kp->data;
        if (strstr(kinds, kp->key) || strstr(kinds, "all")) {
            espRender(conn, "<span class='flash-%s'>%s</span>", kp->key, msg);
        }
    }
}
Beispiel #10
0
PUBLIC cchar *espGetFeedback(HttpConn *conn, cchar *kind)
{
    EspReq      *req;
    MprKey      *kp;
    cchar       *msg;

    req = conn->reqData;
    if (kind == 0 || req == 0 || req->feedback == 0 || mprGetHashLength(req->feedback) == 0) {
        return 0;
    }
    for (kp = 0; (kp = mprGetNextKey(req->feedback, kp)) != 0; ) {
        msg = kp->data;
        if (smatch(kind, kp->key) || smatch(kind, "all")) {
            return msg;
        }
    }
    return 0;
}
Beispiel #11
0
//  MOB - rethink name espGetFlash
cchar *espGetFlashMessage(HttpConn *conn, cchar *kind)
{
    EspReq      *req;
    MprKey      *kp;
    cchar       *msg;
   
    req = conn->data;
    if (kind == 0 || req->flash == 0 || mprGetHashLength(req->flash) == 0) {
        return 0;
    }
    for (kp = 0; (kp = mprGetNextKey(req->flash, kp)) != 0; ) {
        msg = kp->data;
        if (smatch(kind, kp->key) || smatch(kind, "all")) {
            return msg;
        }
    }
    return 0;
}
Beispiel #12
0
static EdiGrid *hashToGrid(MprHash *hash)
{
    EdiGrid *grid;
    EdiRec  *rec;
    cchar   *data;
    char    key[8];
    int     i, len;

    len = mprGetHashLength(hash);
    grid = ediCreateBareGrid(NULL, "grid", len);
    for (i = 0; i < len; i++) {
        data = mprLookupKey(hash, itosbuf(key, sizeof(key), i, 10));
        grid->records[i] = rec = ediCreateBareRec(NULL, "grid", 1);
        rec->fields[0].name = sclone("value");
        rec->fields[0].type = EDI_TYPE_STRING;
        rec->fields[0].value = data;
    }
    return grid;
}
Beispiel #13
0
static char *hashToString(MprHash *hash, cchar *sep)
{
    MprBuf  *buf;
    cchar   *data;
    char    key[8];
    int     i, len;

    len = mprGetHashLength(hash);
    buf = mprCreateBuf(0, 0);
    mprPutCharToBuf(buf, '{');
    for (i = 0; i < len; ) {
        data = mprLookupKey(hash, itosbuf(key, sizeof(key), i, 10));
        mprPutStringToBuf(buf, data);
        if (++i < len) {
            mprPutStringToBuf(buf, sep ? sep : ",");
        }
    }
    mprPutCharToBuf(buf, '}');
    mprAddNullToBuf(buf);
    return mprGetBufStart(buf);
}
Beispiel #14
0
static void testInsertAndRemoveHash(MprTestGroup *gp)
{
    MprHash     *table;
    MprKey      *sp;
    cchar       *str;
    int         rc;

    table = mprCreateHash(0, MPR_HASH_STATIC_KEYS | MPR_HASH_STATIC_VALUES);
    assert(table != 0);

    /*
        Single insert
     */
    sp = mprAddKey(table, "Peter", "123 Madison Ave");
    assert(sp != 0);

    sp = mprGetFirstKey(table);
    assert(sp != 0);
    assert(sp->key != 0);
    assert(strcmp(sp->key, "Peter") == 0);
    assert(sp->data != 0);
    assert(strcmp(sp->data, "123 Madison Ave") == 0);

    /*
        Lookup
     */
    str = mprLookupKey(table, "Peter");
    assert(str != 0);
    assert(strcmp(str, "123 Madison Ave") == 0);

    rc = mprRemoveKey(table, "Peter");
    assert(rc == 0);

    assert(mprGetHashLength(table) == 0);
    sp = mprGetFirstKey(table);
    assert(sp == 0);

    str = mprLookupKey(table, "Peter");
    assert(str == 0);
}
Beispiel #15
0
static void emitFormErrors(HttpConn *conn, EdiRec *rec, MprHash *options)
{
    MprHash         *errors;
    MprKey          *field;
    char            *msg;
    int             count;
   
    if (!rec->errors || httpGetOption(options, "hideErrors", 0)) {
        return;
    }
    errors = ediGetRecErrors(rec);
    if (errors) {
        count = mprGetHashLength(errors);
        espRender(conn, "<div class='" ESTYLE("form-error") "'><h2>The %s has %s it being saved.</h2>\r\n",
            spascal(rec->tableName), count <= 1 ? "an error that prevents" : "errors that prevent");
        espRender(conn, "    <p>There were problems with the following fields:</p>\r\n");
        espRender(conn, "    <ul>\r\n");
        for (ITERATE_KEY_DATA(errors, field, msg)) {
            espRender(conn, "        <li>%s %s</li>\r\n", field->key, msg);
        }
        espRender(conn, "    </ul>\r\n");
        espRender(conn, "</div>");
    }
}
Beispiel #16
0
static int openFileHandler(HttpQueue *q)
{
    HttpRx      *rx;
    HttpTx      *tx;
    HttpConn    *conn;
    MprPath     *info;
    char        *date, dbuf[16];
    MprHash     *dateCache;

    conn = q->conn;
    tx = conn->tx;
    rx = conn->rx;
    info = &tx->fileInfo;

    if (conn->error) {
        return MPR_ERR_CANT_OPEN;
    }
    if (rx->flags & (HTTP_GET | HTTP_HEAD | HTTP_POST)) {
        if (!(info->valid || info->isDir)) {
            httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot find document");
            return 0;
        } 
        if (!tx->etag) {
            /* Set the etag for caching in the client */
            tx->etag = sfmt("\"%llx-%llx-%llx\"", (int64) info->inode, (int64) info->size, (int64) info->mtime);
        }
        if (info->mtime) {
            dateCache = conn->http->dateCache;
            if ((date = mprLookupKey(dateCache, itosbuf(dbuf, sizeof(dbuf), (int64) info->mtime, 10))) == 0) {
                if (!dateCache || mprGetHashLength(dateCache) > 128) {
                    conn->http->dateCache = dateCache = mprCreateHash(0, 0);
                }
                date = httpGetDateString(&tx->fileInfo);
                mprAddKey(dateCache, itosbuf(dbuf, sizeof(dbuf), (int64) info->mtime, 10), date);
            }
            httpSetHeaderString(conn, "Last-Modified", date);
        }
        if (httpContentNotModified(conn)) {
            httpSetStatus(conn, HTTP_CODE_NOT_MODIFIED);
            httpOmitBody(conn);
            tx->length = -1;
        }
        if (!tx->fileInfo.isReg && !tx->fileInfo.isLink) {
            httpTrace(conn, "request.document.error", "error", "msg: 'Document is not a regular file', filename: '%s'", 
                tx->filename);
            httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot serve document");
            
        } else if (tx->fileInfo.size > conn->limits->transmissionBodySize) {
            httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TOO_LARGE,
                "Http transmission aborted. File size exceeds max body of %'lld bytes",
                    conn->limits->transmissionBodySize);
            
        } else if (!(tx->connector == conn->http->sendConnector)) {
            /*
                If using the net connector, open the file if a body must be sent with the response. The file will be
                automatically closed when the request completes.
             */
            if (!(tx->flags & HTTP_TX_NO_BODY)) {
                tx->file = mprOpenFile(tx->filename, O_RDONLY | O_BINARY, 0);
                if (tx->file == 0) {
                    if (rx->referrer && *rx->referrer) {
                        httpTrace(conn, "request.document.error", "error", 
                            "msg: 'Cannot open document', filename: '%s', referrer: '%s'", 
                            tx->filename, rx->referrer);
                    } else {
                        httpTrace(conn, "request.document.error", "error", 
                            "msg: 'Cannot open document', filename: '%s'", tx->filename);
                    }
                    httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot open document");
                }
            }
        }
    } else if (rx->flags & (HTTP_DELETE | HTTP_OPTIONS | HTTP_PUT)) {
        ;
    } else {
        httpError(conn, HTTP_CODE_BAD_METHOD, "Unsupported method");
    }
    return 0;
}
Beispiel #17
0
/*
    OPT
 */
bool httpValidateLimits(HttpEndpoint *endpoint, int event, HttpConn *conn)
{
    HttpLimits      *limits;
    Http            *http;
    cchar           *action;
    int             count, level, dir;

    limits = conn->limits;
    dir = HTTP_TRACE_RX;
    action = "unknown";
    mprAssert(conn->endpoint == endpoint);
    http = endpoint->http;

    lock(http);

    switch (event) {
    case HTTP_VALIDATE_OPEN_CONN:
        /*
            This measures active client systems with unique IP addresses.
         */
        if (endpoint->clientCount >= limits->clientMax) {
            unlock(http);
            /*  Abort connection */
            httpError(conn, HTTP_ABORT | HTTP_CODE_SERVICE_UNAVAILABLE, 
                "Too many concurrent clients %d/%d", endpoint->clientCount, limits->clientMax);
            return 0;
        }
        count = (int) PTOL(mprLookupKey(endpoint->clientLoad, conn->ip));
        mprAddKey(endpoint->clientLoad, conn->ip, ITOP(count + 1));
        endpoint->clientCount = (int) mprGetHashLength(endpoint->clientLoad);
        action = "open conn";
        dir = HTTP_TRACE_RX;
        break;

    case HTTP_VALIDATE_CLOSE_CONN:
        count = (int) PTOL(mprLookupKey(endpoint->clientLoad, conn->ip));
        if (count > 1) {
            mprAddKey(endpoint->clientLoad, conn->ip, ITOP(count - 1));
        } else {
            mprRemoveKey(endpoint->clientLoad, conn->ip);
        }
        endpoint->clientCount = (int) mprGetHashLength(endpoint->clientLoad);
        action = "close conn";
        dir = HTTP_TRACE_TX;
        break;
    
    case HTTP_VALIDATE_OPEN_REQUEST:
        mprAssert(conn->rx);
        if (endpoint->requestCount >= limits->requestMax) {
            unlock(http);
            httpError(conn, HTTP_CODE_SERVICE_UNAVAILABLE, "Server overloaded");
            mprLog(2, "Too many concurrent requests %d/%d", endpoint->requestCount, limits->requestMax);
            return 0;
        }
        endpoint->requestCount++;
        conn->rx->flags |= HTTP_LIMITS_OPENED;
        action = "open request";
        dir = HTTP_TRACE_RX;
        break;

    case HTTP_VALIDATE_CLOSE_REQUEST:
        if (conn->rx && conn->rx->flags & HTTP_LIMITS_OPENED) {
            /* Requests incremented only when conn->rx is assigned */
            endpoint->requestCount--;
            mprAssert(endpoint->requestCount >= 0);
            action = "close request";
            dir = HTTP_TRACE_TX;
            conn->rx->flags &= ~HTTP_LIMITS_OPENED;
        }
        break;

    case HTTP_VALIDATE_OPEN_PROCESS:
        if (http->processCount >= limits->processMax) {
            unlock(http);
            httpError(conn, HTTP_CODE_SERVICE_UNAVAILABLE, "Server overloaded");
            mprLog(2, "Too many concurrent processes %d/%d", http->processCount, limits->processMax);
            return 0;
        }
        http->processCount++;
        action = "start process";
        dir = HTTP_TRACE_RX;
        break;

    case HTTP_VALIDATE_CLOSE_PROCESS:
        http->processCount--;
        mprAssert(http->processCount >= 0);
        break;
    }
    if (event == HTTP_VALIDATE_CLOSE_CONN || event == HTTP_VALIDATE_CLOSE_REQUEST) {
        if ((level = httpShouldTrace(conn, dir, HTTP_TRACE_LIMITS, NULL)) >= 0) {
            LOG(4, "Validate request for %s. Active connections %d, active requests: %d/%d, active client IP %d/%d", 
                action, mprGetListLength(http->connections), endpoint->requestCount, limits->requestMax, 
                endpoint->clientCount, limits->clientMax);
        }
    }
    unlock(http);
    return 1;
}
Beispiel #18
0
/*  
    Start the CGI command program. This commences the CGI gateway program. This will be called after content for
    form and upload requests (or if "RunHandler" before specified), otherwise it runs before receiving content data.
 */
static void startCgi(HttpQueue *q)
{
    HttpRx          *rx;
    HttpTx          *tx;
    HttpRoute       *route;
    HttpConn        *conn;
    MprCmd          *cmd;
    Cgi             *cgi;
    cchar           *baseName, **argv, *fileName, **envv;
    ssize           varCount;
    int             argc, count;

    argv = 0;
    argc = 0;
    cgi = q->queueData;
    conn = q->conn;
    rx = conn->rx;
    route = rx->route;
    tx = conn->tx;

    /*
        The command uses the conn dispatcher. This serializes all I/O for both the connection and the CGI gateway.
     */
    if ((cmd = mprCreateCmd(conn->dispatcher)) == 0) {
        return;
    }
    cgi->cmd = cmd;

    if (conn->http->forkCallback) {
        cmd->forkCallback = conn->http->forkCallback;
        cmd->forkData = conn->http->forkData;
    }
    argc = 1;                                   /* argv[0] == programName */
    buildArgs(conn, cmd, &argc, &argv);
    fileName = argv[0];
    baseName = mprGetPathBase(fileName);
    
    /*
        nph prefix means non-parsed-header. Don't parse the CGI output for a CGI header
     */
    if (strncmp(baseName, "nph-", 4) == 0 || 
            (strlen(baseName) > 4 && strcmp(&baseName[strlen(baseName) - 4], "-nph") == 0)) {
        /* Pretend we've seen the header for Non-parsed Header CGI programs */
        cgi->seenHeader = 1;
        tx->flags |= HTTP_TX_USE_OWN_HEADERS;
    }
    /*  
        Build environment variables
     */
    varCount = mprGetHashLength(rx->headers) + mprGetHashLength(rx->svars) + mprGetJsonLength(rx->params);
    if ((envv = mprAlloc((varCount + 1) * sizeof(char*))) != 0) {
        count = copyParams(conn, envv, 0, rx->params, route->envPrefix);
        count = copyVars(conn, envv, count, rx->svars, "");
        count = copyVars(conn, envv, count, rx->headers, "HTTP_");
        assert(count <= varCount);
    }
#if !VXWORKS
    /*
        This will be ignored on VxWorks because there is only one global current directory for all tasks
     */
    mprSetCmdDir(cmd, mprGetPathDir(fileName));
#endif
    mprSetCmdCallback(cmd, cgiCallback, cgi);

    if (mprStartCmd(cmd, argc, argv, envv, MPR_CMD_IN | MPR_CMD_OUT | MPR_CMD_ERR) < 0) {
        httpError(conn, HTTP_CODE_NOT_FOUND, "Cannot run CGI process: %s, URI %s", fileName, rx->uri);
        return;
    }
#if ME_WIN_LIKE
    mprCreateEvent(conn->dispatcher, "cgi-win", 10, waitForCgi, cgi, MPR_EVENT_CONTINUOUS);
#endif
}
Beispiel #19
0
/*
    Grid is modified. Columns are removed and sorted as required.
 */
static void filterCols(EdiGrid *grid, MprHash *options, MprHash *colOptions)
{
    MprList     *gridCols;
    MprHash     *cp;
    EdiRec      *rec;
    EdiField    f;
    cchar       *columnName;
    char        key[8];
    int         ncols, r, fnum, currentPos, c, index, *desired, *location, pos, t;

    gridCols = ediGetGridColumns(grid);

    if (colOptions) {
        /*
            Sort grid record columns into the order specified by the column options
         */
        ncols = grid->records[0]->nfields;
        location = mprAlloc(sizeof(int) * ncols);
        for (c = 0; c < ncols; c++) {
            location[c] = c;
        }
        ncols = mprGetHashLength(colOptions);
        desired = mprAlloc(sizeof(int) * ncols);
        for (c = 0; c < ncols; c++) {
            cp = mprLookupKey(colOptions, itosbuf(key, sizeof(key), c, 10));
            if ((columnName = mprLookupKey(cp, "name")) == 0) {
                mprError("Cannot locate \"name\" field for column in table");
                return;
            }
            pos = mprLookupStringItem(gridCols, columnName);
            if (pos < 0) {
                mprError("Cannot find column \"%s\", columns: %s", columnName, mprListToString(gridCols, ", "));
            } else {
                desired[c] = pos;
                location[c] = c;
            }
        }
        for (c = 0; c < ncols; c++) {
            fnum = c;
            for (r = 0; r < grid->nrecords; r++) {
                rec = grid->records[r];
                rec->nfields = ncols;
                fnum = desired[c];
                if (fnum < 0) {
                    continue;
                }
                currentPos = location[fnum];

                f = rec->fields[c];
                rec->fields[c] = rec->fields[currentPos];
                rec->fields[currentPos] = f;
            }
            t = location[c];
            location[c] = location[fnum];
            location[fnum] = t;
        }
        
    } else {
        /*
            If showId is false, remove the "id" column
         */
        if (httpOption(options, "showId", "false", 0) && (index = mprLookupStringItem(gridCols, "id")) >= 0) {
            for (r = 0; r < grid->nrecords; r++) {
                rec = grid->records[r];
                rec->nfields--;
                mprMemcpy(rec->fields, sizeof(EdiField) * rec->nfields, &rec->fields[index],
                    sizeof(EdiField) * (rec->nfields - 1));
            }
        }
    }
}
Beispiel #20
0
static void pruneCache(MprCache *cache, MprEvent *event)
{
    MprTime         when, factor;
    MprKey          *kp;
    CacheItem       *item;
    ssize           excessKeys;

    if (!cache) {
        cache = shared;
        if (!cache) {
            return;
        }
    }
    if (event) {
        when = mprGetTime();
    } else {
        /* Expire all items by setting event to NULL */
        when = MAXINT64;
    }
    if (mprTryLock(cache->mutex)) {
        /*
            Check for expired items
         */
        for (kp = 0; (kp = mprGetNextKey(cache->store, kp)) != 0; ) {
            item = (CacheItem*) kp->data;
            mprLog(6, "Cache: \"%s\" lifespan %d, expires in %d secs", item->key, 
                    item->lifespan / 1000, (item->expires - when) / 1000);
            if (item->expires && item->expires <= when) {
                mprLog(5, "Cache prune expired key %s", kp->key);
                removeItem(cache, item);
            }
        }
        mprAssert(cache->usedMem >= 0);

        /*
            If too many keys or too much memory used, prune keys that expire soonest.
         */
        if (cache->maxKeys < MAXSSIZE || cache->maxMem < MAXSSIZE) {
            /*
                Look for those expiring in the next 5 minutes, then 20 mins, then 80 ...
             */
            excessKeys = mprGetHashLength(cache->store) - cache->maxKeys;
            factor = 5 * 60 * MPR_TICKS_PER_SEC; 
            when += factor;
            while (excessKeys > 0 || cache->usedMem > cache->maxMem) {
                for (kp = 0; (kp = mprGetNextKey(cache->store, kp)) != 0; ) {
                    item = (CacheItem*) kp->data;
                    if (item->expires && item->expires <= when) {
                        mprLog(5, "Cache too big execess keys %Ld, mem %Ld, prune key %s", 
                                excessKeys, (cache->maxMem - cache->usedMem), kp->key);
                        removeItem(cache, item);
                    }
                }
                factor *= 4;
                when += factor;
            }
        }
        mprAssert(cache->usedMem >= 0);

        if (mprGetHashLength(cache->store) == 0) {
            if (event) {
                mprRemoveEvent(event);
                cache->timer = 0;
            }
        }
        unlock(cache);
    }
}
Beispiel #21
0
/*
    Accept a new client connection on a new socket.
    This will come in on a worker thread with a new dispatcher dedicated to this connection.
 */
PUBLIC HttpConn *httpAcceptConn(HttpEndpoint *endpoint, MprEvent *event)
{
    Http        *http;
    HttpConn    *conn;
    HttpAddress *address;
    MprSocket   *sock;
    int64       value;

    assert(event);
    assert(event->dispatcher);
    assert(endpoint);

    sock = event->sock;
    http = endpoint->http;

    if (mprShouldDenyNewRequests()) {
        mprCloseSocket(sock, 0);
        return 0;
    }
    if ((conn = httpCreateConn(endpoint, event->dispatcher)) == 0) {
        mprCloseSocket(sock, 0);
        return 0;
    }
    conn->notifier = endpoint->notifier;
    conn->async = endpoint->async;
    conn->endpoint = endpoint;
    conn->sock = sock;
    conn->port = sock->port;
    conn->ip = sclone(sock->ip);

    if ((value = httpMonitorEvent(conn, HTTP_COUNTER_ACTIVE_CONNECTIONS, 1)) > conn->limits->connectionsMax) {
        httpTrace(conn, "connection.accept.error", "error", "msg:'Too many concurrent connections',active:%d,max:%d", 
            (int) value, conn->limits->connectionsMax);
        httpDestroyConn(conn);
        return 0;
    }
    if (mprGetHashLength(http->addresses) > conn->limits->clientMax) {
        httpTrace(conn, "connection.accept.error", "error", "msg:'Too many concurrent clients',active:%d,max:%d", 
            mprGetHashLength(http->addresses), conn->limits->clientMax);
        httpDestroyConn(conn);
        return 0;
    }
    address = conn->address;
    if (address && address->banUntil) {
        if (address->banUntil < http->now) {
            httpTrace(conn, "monitor.ban.stop", "context", "client:'%s'", conn->ip);
            address->banUntil = 0;
        } else {
            if (address->banStatus) {
                httpError(conn, HTTP_CLOSE | address->banStatus,
                    "Connection refused, client banned: %s", address->banMsg ? address->banMsg : "");
            } else {
                httpDestroyConn(conn);
                return 0;
            }
        }
    }
    if (endpoint->ssl) {
        if (mprUpgradeSocket(sock, endpoint->ssl, 0) < 0) {
            httpDisconnect(conn);
            httpTrace(conn, "connection.upgrade.error", "error", "msg:'Cannot upgrade socket. %s'", sock->errorMsg);
            httpMonitorEvent(conn, HTTP_COUNTER_SSL_ERRORS, 1);
            httpDestroyConn(conn);
            return 0;
        }
    }
    assert(conn->state == HTTP_STATE_BEGIN);
    httpSetState(conn, HTTP_STATE_CONNECTED);

    httpTrace(conn, "connection.accept.new", "context", "peer:'%s',endpoint:'%s:%d'", 
        conn->ip, sock->acceptIp, sock->acceptPort);
    
    event->mask = MPR_READABLE;
    event->timestamp = conn->http->now;
    (conn->ioCallback)(conn, event);
    return conn;
}