Example #1
0
/*
    Wait for an event to occur on the dispatcher and service the event. This is not called by mprServiceEvents.
    The dispatcher may be "started" and owned by the thread, or it may be unowned.
    WARNING: the event may have already happened by the time this API is invoked.
    WARNING: this will enable GC while sleeping.
 */
PUBLIC int mprWaitForEvent(MprDispatcher *dispatcher, MprTicks timeout, int64 mark)
{
    MprEventService     *es;
    MprTicks            expires, delay;
    int                 runEvents, changed;

    if (dispatcher == NULL) {
        dispatcher = MPR->dispatcher;
    }
    if (dispatcher->flags & MPR_DISPATCHER_DESTROYED) {
        return 0;
    }
    if ((runEvents = (dispatcher->owner == mprGetCurrentOsThread())) != 0) {
        /* Called from an event on a running dispatcher */
        assert(isRunning(dispatcher) || (dispatcher->flags & MPR_DISPATCHER_DESTROYED));
        if (dispatchEvents(dispatcher)) {
            return 0;
        }
    }
    es = MPR->eventService;
    es->now = mprGetTicks();
    expires = timeout < 0 ? MPR_MAX_TIMEOUT : (es->now + timeout);
    if (expires < 0) {
        expires = MPR_MAX_TIMEOUT;
    }
    delay = expires - es->now;

    lock(es);
    delay = getDispatcherIdleTicks(dispatcher, delay);
    dispatcher->flags |= MPR_DISPATCHER_WAITING;
    changed = dispatcher->mark != mark && mark != -1;
    unlock(es);

    if (changed) {
        return 0;
    }
    mprYield(MPR_YIELD_STICKY);
    mprWaitForCond(dispatcher->cond, delay);
    mprResetYield();
    es->now = mprGetTicks();

    lock(es);
    dispatcher->flags &= ~MPR_DISPATCHER_WAITING;
    unlock(es);

    if (runEvents) {
        dispatchEvents(dispatcher);
        assert(isRunning(dispatcher) || (dispatcher->flags & MPR_DISPATCHER_DESTROYED));
    }
    return 0;
}
Example #2
0
static int doRequest(HttpConn *conn, cchar *url, MprList *files)
{
    MprTicks        mark, remaining;
    HttpLimits      *limits;
    MprFile         *outFile;
    cchar           *path;

    assert(url && *url);
    limits = conn->limits;

    mprTrace(4, "fetch: %s %s", app->method, url);
    mark = mprGetTicks();

    if (issueRequest(conn, url, files) < 0) {
        return MPR_ERR_CANT_CONNECT;
    }
    remaining = limits->requestTimeout;

    if (app->outFilename) {
        path = app->loadThreads > 1 ? sfmt("%s-%s.tmp", app->outFilename, mprGetCurrentThreadName()): app->outFilename;
        if ((outFile = mprOpenFile(path, O_CREAT | O_WRONLY | O_TRUNC | O_TEXT, 0664)) == 0) {
            mprError("Cannot open %s", path);
            return MPR_ERR_CANT_OPEN;
        }
    } else {
        outFile = mprGetStdout();
    }
    mprAddRoot(outFile);
    while (!conn->tx->finalized && conn->state < HTTP_STATE_COMPLETE && remaining > 0) {
        remaining = mprGetRemainingTicks(mark, limits->requestTimeout);
        readBody(conn, outFile);
        httpWait(conn, 0, remaining);
    }
    if (conn->state < HTTP_STATE_COMPLETE && !conn->error) {
        httpError(conn, HTTP_ABORT | HTTP_CODE_REQUEST_TIMEOUT,
            "Inactive request timed out, exceeded request timeout %d", app->timeout);
    } else {
        readBody(conn, outFile);
    }
    if (app->outFilename) {
        mprCloseFile(outFile);
    }
    mprRemoveRoot(outFile);
    reportResponse(conn, url, mprGetTicks() - mark);
    httpDestroyRx(conn->rx);
    httpDestroyTx(conn->tx);
    return 0;
}
Example #3
0
int httpConnect(HttpConn *conn, cchar *method, cchar *url, struct MprSsl *ssl)
{
    mprAssert(conn);
    mprAssert(method && *method);
    mprAssert(url && *url);

    if (conn->endpoint) {
        httpError(conn, HTTP_CODE_BAD_GATEWAY, "Can't call connect in a server");
        return MPR_ERR_BAD_STATE;
    }
    mprLog(4, "Http: client request: %s %s", method, url);

    if (conn->tx == 0 || conn->state != HTTP_STATE_BEGIN) {
        /* WARNING: this will erase headers */
        httpPrepClientConn(conn, 0);
    }
    mprAssert(conn->state == HTTP_STATE_BEGIN);
    httpSetState(conn, HTTP_STATE_CONNECTED);
    conn->setCredentials = 0;
    conn->tx->method = supper(method);

#if BIT_DEBUG
    conn->startTime = conn->http->now;
    conn->startTicks = mprGetTicks();
#endif
    if (openConnection(conn, url, ssl) == 0) {
        return MPR_ERR_CANT_OPEN;
    }
    httpCreateTxPipeline(conn, conn->http->clientRoute);
    if (setClientHeaders(conn) < 0) {
        return MPR_ERR_CANT_INITIALIZE;
    }
    return 0;
}
Example #4
0
static void sml() {
    int     i;
    for (i = 0; i < 1; i++) {
        render("Line: %05d %s", i, "aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccccddddddd<br/>\r\n");
    }
    render("{ when: %Ld, uri: '%s', query: '%s' }\r\n", mprGetTicks(), getUri(), getQuery());
}
Example #5
0
static int join(Ejs *ejs, EjsObj *workers, int timeout)
{
    MprTicks    mark;
    int         result, remaining;

    mprTrace(5, "Worker.join: joining %d", ejs->joining);
    
    mark = mprGetTicks();
    remaining = timeout;
    do {
        ejs->joining = !reapJoins(ejs, workers);
        if (!ejs->joining) {
            break;
        }
        if (mprShouldAbortRequests()) {
            ejsThrowStateError(ejs, "Program instructed to exit");
            break;
        }
        mprWaitForEvent(ejs->dispatcher, remaining);
        remaining = (int) mprGetRemainingTicks(mark, timeout);
    } while (remaining > 0 && !ejs->exception);

    if (ejs->exception) {
        return 0;
    }
    result = (ejs->joining) ? MPR_ERR_TIMEOUT: 0;
    ejs->joining = 0;
    mprTrace(7, "Worker.join: result %d", result);
    return result;
}
Example #6
0
/*  
    static function run(timeout: Number = -1, oneEvent: Boolean = false): Boolean
 */
static EjsObj *app_run(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv)
{
    MprTicks    mark, remaining;
    int64       dispatcherMark;
    int         rc, oneEvent, timeout;

    timeout = (argc > 0) ? ejsGetInt(ejs, argv[0]) : MAXINT;
    oneEvent = (argc > 1) ? ejsGetInt(ejs, argv[1]) : 0;

    if (ejs->hosted) {
        return ESV(true);
    }
    if (timeout < 0) {
        timeout = MAXINT;
    }
    mark = mprGetTicks();
    remaining = timeout;
    dispatcherMark = mprGetEventMark(ejs->dispatcher);
    do {
        rc = mprWaitForEvent(ejs->dispatcher, remaining, dispatcherMark); 
        remaining = mprGetRemainingTicks(mark, timeout);
        dispatcherMark = mprGetEventMark(ejs->dispatcher);
    } while (!ejs->exception && !oneEvent && !ejs->exiting && remaining > 0 && !mprIsStopping());
    return (rc == 0) ? ESV(true) : ESV(false);
}
Example #7
0
/*
    This is called when unloading a view or controller module
    All of ESP must be quiesced.
 */
static bool espUnloadModule(cchar *module, MprTicks timeout)
{
    MprModule   *mp;
    MprTicks    mark;

    if ((mp = mprLookupModule(module)) != 0) {
        mark = mprGetTicks();
        esp->reloading = 1;
        do {
            lock(esp);
            /* Own request will count as 1 */
            if (esp->inUse <= 1) {
                if (mprUnloadModule(mp) < 0) {
                    mprLog("error esp", 0, "Cannot unload module %s", mp->name);
                    unlock(esp);
                }
                esp->reloading = 0;
                unlock(esp);
                return 1;
            }
            unlock(esp);
            mprSleep(10);

        } while (mprGetRemainingTicks(mark, timeout) > 0);
        esp->reloading = 0;
    }
    return 0;
}
Example #8
0
PUBLIC MprModule *mprCreateModule(cchar *name, cchar *path, cchar *entry, void *data)
{
    MprModuleService    *ms;
    MprModule           *mp;
    int                 index;

    ms = MPR->moduleService;
    assert(ms);

    if ((mp = mprAllocObj(MprModule, manageModule)) == 0) {
        return 0;
    }
    mp->name = sclone(name);
    if (path && *path) {
        mp->path = sclone(path);
    }
    if (entry && *entry) {
        mp->entry = sclone(entry);
    }
    mp->moduleData = data;
    mp->lastActivity = mprGetTicks();
    index = mprAddItem(ms->modules, mp);
    if (index < 0 || mp->name == 0) {
        return 0;
    }
    return mp;
}
Example #9
0
/*
    function waitForMessage(timeout: Number = -1): Boolean
 */
static EjsBoolean *workerWaitForMessage(Ejs *ejs, EjsWorker *worker, int argc, EjsObj **argv)
{
    MprTicks    mark, remaining;
    int         timeout;

    timeout = (argc > 0) ? ejsGetInt(ejs, argv[0]): MAXINT;
    if (timeout < 0) {
        timeout = MAXINT;
    }
    mark = mprGetTicks();
    remaining = timeout;

    worker->gotMessage = 0;
    do {
        mprWaitForEvent(ejs->dispatcher, (int) remaining);
        remaining = mprGetRemainingTicks(mark, timeout);
    } while (!worker->gotMessage && remaining > 0 && !ejs->exception);

    if (worker->gotMessage) {
        worker->gotMessage = 0;
        return ESV(true);
    } else {
        return ESV(true);
    }
}
Example #10
0
PUBLIC bool httpConfigure(HttpConfigureProc proc, void *data, MprTicks timeout)
{
    Http        *http;
    MprTicks    mark;

    http = HTTP;
    mark = mprGetTicks();
    if (timeout < 0) {
        timeout = http->serverLimits->requestTimeout;
    } else if (timeout == 0) {
        timeout = MAXINT;
    }
    do {
        lock(http->connections);
        /* Own request will count as 1 */
        if (mprGetListLength(http->connections) == 0) {
            (proc)(data);
            unlock(http->connections);
            return 1;
        }
        unlock(http->connections);
        mprSleep(10);
        /* Defaults to 10 secs */
    } while (mprGetRemainingTicks(mark, timeout) > 0);
    return 0;
}
Example #11
0
/*
    Test if the http service (including MPR) is idle with no running requests
 */
static bool isIdle(bool traceRequests)
{
    HttpConn        *conn;
    Http            *http;
    MprTicks        now;
    int             next;
    static MprTicks lastTrace = 0;

    if ((http = MPR->httpService) != 0) {
        now = http->now;
        lock(http->connections);
        for (next = 0; (conn = mprGetNextItem(http->connections, &next)) != 0; ) {
            if (conn->state != HTTP_STATE_BEGIN && conn->state != HTTP_STATE_COMPLETE) {
                if (traceRequests && lastTrace < now) {
                    if (conn->rx) {
                        mprLog("info http", 2, "Request for \"%s\" is still active", 
                            conn->rx->uri ? conn->rx->uri : conn->rx->pathInfo);
                    }
                    lastTrace = now;
                }
                unlock(http->connections);
                return 0;
            }
        }
        unlock(http->connections);
    } else {
        now = mprGetTicks();
    }
    return mprServicesAreIdle(traceRequests);
}
Example #12
0
static void manual() { 
    if (smatch(getQuery(), "send")) {
        setHeader("X-SendCache", "true");
        finalize();
    } else if (!espRenderCached(getConn())) {
        render("{ when: %Ld, uri: '%s', query: '%s' }\r\n", mprGetTicks(), getUri(), getQuery());
    }
}
Example #13
0
static void huge() { 
    int     i;
    //  This will emit ~762K (over the item limit)
    for (i = 0; i < 10000; i++) {
        render("Line: %05d %s", i, "aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbccccccccccccccccccddddddd<br/>\r\n");
    }
    render("{ when: %Ld, uri: '%s', query: '%s' }\r\n", mprGetTicks(), getUri(), getQuery());
}
Example #14
0
static int reportResponse(HttpConn *conn, cchar *url)
{
    HttpRx      *rx;
    MprOff      bytesRead;
    char        *responseHeaders;
    int         status;

    if (mprShouldAbortRequests(conn)) {
        return 0;
    }
    app->status = status = httpGetStatus(conn);
    bytesRead = httpGetContentLength(conn);
    if (bytesRead < 0 && conn->rx) {
        bytesRead = conn->rx->bytesRead;
    }
    mprDebug("http", 6, "Response status %d, elapsed %lld", status, mprGetTicks() - conn->started);
    if (conn->error) {
        app->success = 0;
    }
    if (conn->rx) {
        if (app->showHeaders) {
            responseHeaders = httpGetHeaders(conn);
            rx = conn->rx;
            mprPrintf("%s %d %s\n", conn->protocol, status, rx->statusMessage);
            if (responseHeaders) {
                mprPrintf("%s\n", responseHeaders);
            }
        } else if (app->showStatus) {
            mprPrintf("%d\n", status);
        }
    }
    if (status < 0) {
        mprLog("error http", 0, "Cannot process request for \"%s\" %s", url, httpGetError(conn));
        return MPR_ERR_CANT_READ;

    } else if (status == 0 && conn->protocol == 0) {
        /* Ignore */;

    } else if (!(200 <= status && status <= 206) && !(301 <= status && status <= 304)) {
        if (!app->zeroOnErrors) {
            app->success = 0;
        }
        if (!app->showStatus) {
            mprLog("error http", 0, "Cannot process request for \"%s\" (%d) %s", url, status, httpGetError(conn));
            return MPR_ERR_CANT_READ;
        }
    }
    mprLock(app->mutex);
    app->fetchCount++;
    if (app->verbose && app->noout) {
        trace(conn, url, app->fetchCount, app->method, status, bytesRead);
    }
    mprUnlock(app->mutex);
    return 0;
}
Example #15
0
/*
    Wait for the event to be triggered when there may be multiple waiters. This routine may return early due to
    other signals or events. The caller must verify if the signalled condition truly exists. If the event is already
    triggered, then it will return immediately. This call will not reset cp->triggered and must be reset manually.
    A timeout of -1 means wait forever. Timeout of 0 means no wait.  Returns 0 if the event was signalled.
    Returns < 0 for a timeout.

    WARNING: On unix, the pthread_cond_timedwait uses an absolute time (Ugh!). So time-warps for daylight-savings may
    cause waits to prematurely return.
 */
PUBLIC int mprWaitForMultiCond(MprCond *cp, MprTicks timeout)
{
    int         rc;
#if ME_UNIX_LIKE
    struct timespec     waitTill;
    struct timeval      current;
    int                 usec;
#else
    MprTicks            now, expire;
#endif

    if (timeout < 0) {
        timeout = MAXINT;
    }
#if ME_UNIX_LIKE
    gettimeofday(&current, NULL);
    usec = current.tv_usec + ((int) (timeout % 1000)) * 1000;
    waitTill.tv_sec = current.tv_sec + ((int) (timeout / 1000)) + (usec / 1000000);
    waitTill.tv_nsec = (usec % 1000000) * 1000;
#else
    now = mprGetTicks();
    expire = now + timeout;
#endif

#if ME_WIN_LIKE
    rc = WaitForSingleObject(cp->cv, (int) (expire - now));
    if (rc == WAIT_OBJECT_0) {
        rc = 0;
    } else if (rc == WAIT_TIMEOUT) {
        rc = MPR_ERR_TIMEOUT;
    } else {
        rc = MPR_ERR;
    }
#elif VXWORKS
    rc = semTake(cp->cv, (int) (expire - now));
    if (rc != 0) {
        if (errno == S_objLib_OBJ_UNAVAILABLE) {
            rc = MPR_ERR_TIMEOUT;
        } else {
            rc = MPR_ERR;
        }
    }
#elif ME_UNIX_LIKE
    mprLock(cp->mutex);
    rc = pthread_cond_timedwait(&cp->cv, &cp->mutex->cs,  &waitTill);
    if (rc == ETIMEDOUT) {
        rc = MPR_ERR_TIMEOUT;
    } else if (rc != 0) {
        rc = MPR_ERR;
    }
    mprUnlock(cp->mutex);
#endif
    return rc;
}
Example #16
0
File: cmd.c Project: embedthis/mpr
/*
    Wait for a command to complete. Return 0 if the command completed, otherwise it will return MPR_ERR_TIMEOUT.
 */
PUBLIC int mprWaitForCmd(MprCmd *cmd, MprTicks timeout)
{
    MprTicks    expires, remaining, delay;
    int64       dispatcherMark;

    assert(cmd);
    if (timeout < 0) {
        timeout = MAXINT;
    }
    if (mprGetDebugMode()) {
        timeout = MAXINT;
    }
    if (cmd->stopped) {
        timeout = 0;
    }
    expires = mprGetTicks() + timeout;
    remaining = timeout;

    /* Add root to allow callers to use mprRunCmd without first managing the cmd */
    mprAddRoot(cmd);
    dispatcherMark = mprGetEventMark(cmd->dispatcher);

    while (!cmd->complete && remaining > 0) {
        if (mprShouldAbortRequests()) {
            break;
        }
        delay = (cmd->eofCount >= cmd->requiredEof) ? 10 : remaining;
        if (!MPR->eventing) {
            mprServiceEvents(delay, MPR_SERVICE_NO_BLOCK);
            delay = 0;
        }
        mprWaitForEvent(cmd->dispatcher, delay, dispatcherMark);
        remaining = (expires - mprGetTicks());
        dispatcherMark = mprGetEventMark(cmd->dispatcher);
    }
    mprRemoveRoot(cmd);
    if (cmd->pid) {
        return MPR_ERR_TIMEOUT;
    }
    return 0;
}
Example #17
0
static void updateCurrentDate()
{
    Http        *http;
    MprTicks    diff;

    http = HTTP;
    http->now = mprGetTicks();
    diff = http->now - http->currentTime;
    if (diff <= TPS || diff >= TPS) {
        /*
            Optimize and only update the string date representation once per second
         */
        http->currentTime = http->now;
        http->currentDate = httpGetDateString(NULL);
    }
}
Example #18
0
/*  
    Pause the application. This services events while asleep.
    static function sleep(delay: Number = -1): void
    MOB - sleep currently throws if an exception is generated in an event callback (worker).
    It should not.
 */
static EjsObj *app_sleep(Ejs *ejs, EjsObj *unused, int argc, EjsObj **argv)
{
    MprTicks    mark, remaining;
    int         timeout;

    timeout = (argc > 0) ? ejsGetInt(ejs, argv[0]) : MAXINT;
    if (timeout < 0) {
        timeout = MAXINT;
    }
    mark = mprGetTicks();
    remaining = timeout;
    do {
        mprWaitForEvent(ejs->dispatcher, (int) remaining); 
        remaining = mprGetRemainingTicks(mark, timeout);
    } while (!ejs->exiting && remaining > 0 && !mprIsStopping());
    return 0;
}
Example #19
0
File: cmd.c Project: embedthis/mpr
/*
    Windows only routine to wait for I/O on the channels to the gateway and the child process.
    This will queue events on the dispatcher queue when I/O occurs or the process dies.
    NOTE: NamedPipes cannot use WaitForMultipleEvents, so we dedicate a thread to polling.
    WARNING: this should not be called from a dispatcher other than cmd->dispatcher.
 */
static void pollWinCmd(MprCmd *cmd, MprTicks timeout)
{
    MprTicks        mark, delay;
    MprWaitHandler  *wp;
    int             i, rc, nbytes;

    mark = mprGetTicks();
    if (cmd->stopped) {
        timeout = 0;
    }
    slock(cmd);
    for (i = MPR_CMD_STDOUT; i < MPR_CMD_MAX_PIPE; i++) {
        if (cmd->files[i].handle) {
            wp = cmd->handlers[i];
            if (wp && wp->desiredMask & MPR_READABLE) {
                rc = PeekNamedPipe(cmd->files[i].handle, NULL, 0, NULL, &nbytes, NULL);
                if (rc && nbytes > 0 || cmd->process == 0) {
                    wp->presentMask |= MPR_READABLE;
                    mprQueueIOEvent(wp);
                }
            }
        }
    }
    if (cmd->files[MPR_CMD_STDIN].handle) {
        wp = cmd->handlers[MPR_CMD_STDIN];
        if (wp && wp->desiredMask & MPR_WRITABLE) {
            wp->presentMask |= MPR_WRITABLE;
            mprQueueIOEvent(wp);
        }
    }
    if (cmd->process) {
        delay = (cmd->eofCount == cmd->requiredEof && cmd->files[MPR_CMD_STDIN].handle == 0) ? timeout : 0;
        do {
            mprYield(MPR_YIELD_STICKY);
            if (WaitForSingleObject(cmd->process, (DWORD) delay) == WAIT_OBJECT_0) {
                mprResetYield();
                reapCmd(cmd, 0);
                break;
            } else {
                mprResetYield();
            }
            delay = mprGetRemainingTicks(mark, timeout);
        } while (cmd->eofCount == cmd->requiredEof);
    }
    sunlock(cmd);
}
Example #20
0
/*
    This routine does not yield
 */
PUBLIC void mprNap(MprTicks timeout)
{
    MprTicks        remaining, mark;
    struct timespec t;
    int             rc;

    assert(timeout >= 0);

    mark = mprGetTicks();
    remaining = timeout;
    do {
        /* MAC OS X corrupts the timeout if using the 2nd paramater, so recalc each time */
        t.tv_sec = ((int) (remaining / 1000));
        t.tv_nsec = ((int) ((remaining % 1000) * 1000000));
        rc = nanosleep(&t, NULL);
        remaining = mprGetRemainingTicks(mark, timeout);
    } while (rc < 0 && errno == EINTR && remaining > 0);
}
Example #21
0
/*
    Create the overall dispatch service. There may be many event dispatchers.
 */
PUBLIC MprEventService *mprCreateEventService()
{
    MprEventService     *es;

    if ((es = mprAllocObj(MprEventService, manageEventService)) == 0) {
        return 0;
    }
    MPR->eventService = es;
    es->now = mprGetTicks();
    es->mutex = mprCreateLock();
    es->waitCond = mprCreateCond();
    es->runQ = createQhead("running");
    es->readyQ = createQhead("ready");
    es->idleQ = createQhead("idle");
    es->pendingQ = createQhead("pending");
    es->waitQ = createQhead("waiting");
    return es;
}
Example #22
0
/*
    Wait for an event to complete signified by the 'completion' flag being set.
    This will wait for events on the dispatcher.
    The completion flag will be reset on return.
 */
PUBLIC bool mprWaitForCompletion(MprDispatcher *dispatcher, MprTicks timeout)
{
    MprTicks    mark;
    bool        success;

    assert(timeout >= 0);

    if (dispatcher == 0) {
        dispatcher = MPR->dispatcher;
    }
    if (mprGetDebugMode()) {
        timeout *= 100;
    }
    for (mark = mprGetTicks(); !(dispatcher->flags & MPR_DISPATCHER_COMPLETE) && mprGetElapsedTicks(mark) < timeout; ) {
        mprWaitForEvent(dispatcher, 10, -1);
    }
    success = (dispatcher->flags & MPR_DISPATCHER_COMPLETE) ? 1 : 0;
    dispatcher->flags &= ~MPR_DISPATCHER_COMPLETE;
    return success;
}
Example #23
0
/*
    Create and queue a new event for service. Period is used as the delay before running the event and as the period
    between events for continuous events.

    WARNING: this routine is unique in that it may be called from a non-MPR thread. This means it may run in parallel with
    the GC. So memory must be held until safely queued.
 */
PUBLIC MprEvent *mprCreateEvent(MprDispatcher *dispatcher, cchar *name, MprTicks period, void *proc, void *data, int flags)
{
    MprEvent    *event;

    /*
        Create and hold the event object (immune from GC for foreign threads)
     */
    if ((event = mprAllocMem(sizeof(MprEvent), MPR_ALLOC_MANAGER | MPR_ALLOC_ZERO | MPR_ALLOC_HOLD)) == 0) {
        return 0;
    }
    mprSetManager(event, (MprManager) manageEvent);

    if (dispatcher == 0 || (dispatcher->flags & MPR_DISPATCHER_DESTROYED)) {
        dispatcher = (flags & MPR_EVENT_QUICK) ? MPR->nonBlock : MPR->dispatcher;
    }
    dispatcher->service->now = mprGetTicks();
    event->name = name;
    event->timestamp = dispatcher->service->now;
    event->proc = proc;
    event->period = period;
    event->due = event->timestamp + period;
    event->data = data;
    event->dispatcher = dispatcher;
    event->next = event->prev = 0;
    event->flags = flags;

    if (!(flags & MPR_EVENT_DONT_QUEUE)) {
        mprQueueEvent(dispatcher, event);
    }
    /* Unset eternal */
    if (!(flags & MPR_EVENT_HOLD)) {
        mprRelease(event);
    }
    /*
        Warning: if invoked from a foreign (non-mpr) thread, the event may be collected prior to return
     */
    return event;
}
Example #24
0
/*
    This is called when unloading a view or controller module
 */
PUBLIC bool espUnloadModule(cchar *module, MprTicks timeout)
{
    MprModule   *mp;
    MprTicks    mark;
    Esp         *esp;

    if ((mp = mprLookupModule(module)) != 0) {
        esp = MPR->espService;
        mark = mprGetTicks();
        do {
            lock(esp);
            /* Own request will count as 1 */
            if (esp->inUse <= 1) {
                mprUnloadModule(mp);
                unlock(esp);
                return 1;
            }
            unlock(esp);
            mprSleep(10);
            /* Defaults to 10 secs */
        } while (mprGetRemainingTicks(mark, timeout) > 0);
    }
    return 0;
}
Example #25
0
PUBLIC void httpAddConn(HttpConn *conn)
{
    Http    *http;

    http = HTTP;
    http->now = mprGetTicks();
    assert(http->now >= 0);
    conn->started = http->now;
    mprAddItem(http->connections, conn);
    updateCurrentDate();

    lock(http);
    conn->seqno = (int) ++http->totalConnections;
    if (!http->timer) {
#if ME_DEBUG
        if (!mprGetDebugMode())
#endif
        {
            http->timer = mprCreateTimerEvent(NULL, "httpTimer", HTTP_TIMER_PERIOD, httpTimer, http, 
                MPR_EVENT_CONTINUOUS | MPR_EVENT_QUICK);
        }
    }
    unlock(http);
}
Example #26
0
static void update() { 
    cchar   *data = sfmt("{ when: %Ld, uri: '%s', query: '%s' }\r\n", mprGetTicks(), getUri(), getQuery());
    espUpdateCache(getConn(), "/cache/manual", data, 86400);
    render("done");
}
Example #27
0
File: cmd.c Project: embedthis/mpr
static int makeChannel(MprCmd *cmd, int index)
{
    SECURITY_ATTRIBUTES clientAtt, serverAtt, *att;
    HANDLE              readHandle, writeHandle;
    MprCmdFile          *file;
    MprTicks            now;
    char                *pipeName;
    int                 openMode, pipeMode, readFd, writeFd;
    static int          tempSeed = 0;

    memset(&clientAtt, 0, sizeof(clientAtt));
    clientAtt.nLength = sizeof(SECURITY_ATTRIBUTES);
    clientAtt.bInheritHandle = 1;

    /*
        Server fds are not inherited by the child
     */
    memset(&serverAtt, 0, sizeof(serverAtt));
    serverAtt.nLength = sizeof(SECURITY_ATTRIBUTES);
    serverAtt.bInheritHandle = 0;

    file = &cmd->files[index];
    now = ((int) mprGetTicks() & 0xFFFF) % 64000;

    lock(MPR->cmdService);
    pipeName = sfmt("\\\\.\\pipe\\MPR_%d_%d_%d.tmp", getpid(), (int) now, ++tempSeed);
    unlock(MPR->cmdService);

    /*
        Pipes are always inbound. The file below is outbound. we swap whether the client or server
        inherits the pipe or file. MPR_CMD_STDIN is the clients input pipe.
        Pipes are blocking since both ends share the same blocking mode. Client must be blocking.
     */
    openMode = PIPE_ACCESS_INBOUND;
    pipeMode = 0;

    att = (index == MPR_CMD_STDIN) ? &clientAtt : &serverAtt;
    readHandle = CreateNamedPipe(wide(pipeName), openMode, pipeMode, 1, 0, 256 * 1024, 1, att);
    if (readHandle == INVALID_HANDLE_VALUE) {
        mprLog("error mpr cmd", 0, "Cannot create stdio pipes %s. Err %d", pipeName, mprGetOsError());
        return MPR_ERR_CANT_CREATE;
    }
    readFd = _open_osfhandle((intptr_t) readHandle, 0);

    att = (index == MPR_CMD_STDIN) ? &serverAtt: &clientAtt;
    writeHandle = CreateFile(wide(pipeName), GENERIC_WRITE, 0, att, OPEN_EXISTING, openMode, 0);
    writeFd = _open_osfhandle((intptr_t) writeHandle, 0);

    if (readFd < 0 || writeFd < 0) {
        mprLog("error mpr cmd", 0, "Cannot create stdio pipes %s. Err %d", pipeName, mprGetOsError());
        return MPR_ERR_CANT_CREATE;
    }
    if (index == MPR_CMD_STDIN) {
        file->clientFd = readFd;
        file->fd = writeFd;
        file->handle = writeHandle;
    } else {
        file->clientFd = writeFd;
        file->fd = readFd;
        file->handle = readHandle;
    }
    return 0;
}
Example #28
0
/*
    Wait for the event to be triggered. Should only be used when there are single waiters. If the event is already
    triggered, then it will return immediately. Timeout of -1 means wait forever. Timeout of 0 means no wait.
    Returns 0 if the event was signalled. Returns < 0 for a timeout.

    WARNING: On unix, the pthread_cond_timedwait uses an absolute time (Ugh!). So time-warps for daylight-savings may
    cause waits to prematurely return.
 */
PUBLIC int mprWaitForCond(MprCond *cp, MprTicks timeout)
{
    MprTicks            now, expire;
    int                 rc;
#if ME_UNIX_LIKE
    struct timespec     waitTill;
    struct timeval      current;
    int                 usec;
#endif
    /*
        Avoid doing a mprGetTicks() if timeout is < 0
     */
    rc = 0;
    if (timeout >= 0) {
        if (timeout > MAXINT) {
            timeout = MAXINT;
        }
        now = mprGetTicks();
        expire = now + timeout;
        if (expire < 0) {
            expire = MPR_MAX_TIMEOUT;
        }
#if ME_UNIX_LIKE
        gettimeofday(&current, NULL);
        usec = current.tv_usec + ((int) (timeout % 1000)) * 1000;
        waitTill.tv_sec = current.tv_sec + ((int) (timeout / 1000)) + (usec / 1000000);
        waitTill.tv_nsec = (usec % 1000000) * 1000;
#endif
    } else {
        expire = -1;
        now = 0;
    }
    mprLock(cp->mutex);
    /*
        NOTE: The WaitForSingleObject and semTake APIs keeps state as to whether the object is signalled.
        WaitForSingleObject and semTake will not block if the object is already signalled. However, pthread_cond_
        is different and does not keep such state. If it is signalled before pthread_cond_wait, the thread will
        still block. Consequently we need to keep our own state in cp->triggered. This also protects against
        spurious wakeups which can happen (on windows).
     */
    do {
#if ME_WIN_LIKE
        /*
            Regardless of the state of cp->triggered, we must call WaitForSingleObject to consume the signalled
            internal state of the object.
         */
        mprUnlock(cp->mutex);
        rc = WaitForSingleObject(cp->cv, (int) (expire - now));
        mprLock(cp->mutex);
        if (rc == WAIT_OBJECT_0) {
            rc = 0;
            ResetEvent(cp->cv);
        } else if (rc == WAIT_TIMEOUT) {
            rc = MPR_ERR_TIMEOUT;
        } else {
            rc = MPR_ERR;
        }
#elif VXWORKS
        /*
            Regardless of the state of cp->triggered, we must call semTake to consume the semaphore signalled state
         */
        mprUnlock(cp->mutex);
        rc = semTake(cp->cv, (int) (expire - now));
        mprLock(cp->mutex);
        if (rc != 0) {
            if (errno == S_objLib_OBJ_UNAVAILABLE) {
                rc = MPR_ERR_TIMEOUT;
            } else {
                rc = MPR_ERR;
            }
        }

#elif ME_UNIX_LIKE
        /*
            The pthread_cond_wait routines will atomically unlock the mutex before sleeping and will relock on awakening.
            WARNING: pthreads may do spurious wakeups without being triggered
         */
        if (!cp->triggered) {
            do {
                if (now) {
                    rc = pthread_cond_timedwait(&cp->cv, &cp->mutex->cs,  &waitTill);
                } else {
                    rc = pthread_cond_wait(&cp->cv, &cp->mutex->cs);
                }
            } while ((rc == 0 || rc == EAGAIN) && !cp->triggered);
            if (rc == ETIMEDOUT) {
                rc = MPR_ERR_TIMEOUT;
            } else if (rc == EAGAIN) {
                rc = 0;
            } else if (rc != 0) {
                mprLog("error mpr thread", 0, "pthread_cond_timedwait error rc %d", rc);
                rc = MPR_ERR;
            }
        }
#endif
    } while (!cp->triggered && rc == 0 && (!now || (now = mprGetTicks()) < expire));

    if (cp->triggered) {
        cp->triggered = 0;
        rc = 0;
    } else if (rc == 0) {
        rc = MPR_ERR_TIMEOUT;
    }
    mprUnlock(cp->mutex);
    return rc;
}
Example #29
0
//  This is configured for caching by API below
static void api() {
    render("{ when: %Ld, uri: '%s', query: '%s' }\r\n", mprGetTicks(), getUri(), getQuery());
}
Example #30
0
/*
    Schedule events.
    This routine will service events until the timeout expires or if MPR_SERVICE_NO_BLOCK is specified in flags,
    until there are no more events to service. This routine will also return when the MPR is stopping. This will
    service all enabled non-running dispatcher queues and pending I/O events.
    An app should dedicate only one thread to be an event service thread.
    @param timeout Time in milliseconds to wait. Set to zero for no wait. Set to -1 to wait forever.
    @param flags Set to MPR_SERVICE_NO_BLOCK for non-blocking.
    @returns Number of events serviced.
 */
PUBLIC int mprServiceEvents(MprTicks timeout, int flags)
{
    MprEventService     *es;
    MprDispatcher       *dp;
    MprTicks            expires, delay;
    int                 beginEventCount, eventCount;

    if (MPR->eventing) {
        mprLog("warn mpr event", 0, "mprServiceEvents called reentrantly");
        return 0;
    }
    mprAtomicBarrier();
    if (mprIsDestroying()) {
        return 0;
    }
    MPR->eventing = 1;
    es = MPR->eventService;
    beginEventCount = eventCount = es->eventCount;
    es->now = mprGetTicks();
    expires = timeout < 0 ? MPR_MAX_TIMEOUT : (es->now + timeout);
    if (expires < 0) {
        expires = MPR_MAX_TIMEOUT;
    }
    mprSetWindowsThread(0);

    while (es->now <= expires) {
        eventCount = es->eventCount;
        mprServiceSignals();

        while ((dp = getNextReadyDispatcher(es)) != NULL) {
            assert(!isRunning(dp));
            queueDispatcher(es->runQ, dp);
            if (dp->flags & MPR_DISPATCHER_IMMEDIATE) {
                dispatchEventsWorker(dp);
            } else {
                if (mprStartWorker((MprWorkerProc) dispatchEventsWorker, dp) < 0) {
                    /* Should not get here */
                    queueDispatcher(es->pendingQ, dp);
                    break;
                }
            }
        }
        if (flags & MPR_SERVICE_NO_BLOCK) {
            expires = 0;
            /* But still service I/O events below */
        }
        if (es->eventCount == eventCount) {
            lock(es);
            delay = getIdleTicks(es, expires - es->now);
            es->willAwake = es->now + delay;
            es->waiting = 1;
            unlock(es);
            /*
                Service IO events
             */
            mprWaitForIO(MPR->waitService, delay);
        }
        es->now = mprGetTicks();
        if (flags & MPR_SERVICE_NO_BLOCK) {
            break;
        }
        if (mprIsStopping()) {
            break;
        }
    }
    MPR->eventing = 0;
    mprSignalCond(MPR->cond);
    return abs(es->eventCount - beginEventCount);
}