/* * Start the host timer. This may create multiple timers -- no worry. maAddConn does its best to only schedule one. */ static void startTimer(MaHost *host) { if (mprGetDebugMode(host)) { return; } mprCreateTimerEvent(host, (MprEventProc) hostTimer, MA_TIMER_PERIOD, MPR_NORMAL_PRIORITY, host, MPR_EVENT_CONTINUOUS); }
/* This clones a database to give a private view per user. */ static int cloneDatabase(HttpConn *conn) { Esp *esp; EspRoute *eroute; EspReq *req; cchar *id; req = conn->reqData; eroute = conn->rx->route->eroute; assert(eroute->edi); assert(eroute->edi->flags & EDI_PRIVATE); esp = req->esp; if (!esp->databases) { lock(esp); if (!esp->databases) { esp->databases = mprCreateHash(0, 0); esp->databasesTimer = mprCreateTimerEvent(NULL, "esp-databases", 60 * 1000, pruneDatabases, esp, 0); } unlock(esp); } /* If the user is logging in or out, this will create a redundant session here. */ httpGetSession(conn, 1); id = httpGetSessionID(conn); if ((req->edi = mprLookupKey(esp->databases, id)) == 0) { if ((req->edi = ediClone(eroute->edi)) == 0) { mprLog("error esp", 0, "Cannot clone database: %s", eroute->edi->path); return MPR_ERR_CANT_OPEN; } mprAddKey(esp->databases, id, req->edi); } return 0; }
PUBLIC void httpSetTimestamp(MprTicks period) { Http *http; http = HTTP; if (period < (10 * TPS)) { period = (10 * TPS); } if (http->timestamp) { mprRemoveEvent(http->timestamp); } if (period > 0) { http->timestamp = mprCreateTimerEvent(NULL, "httpTimestamp", period, timestamp, NULL, MPR_EVENT_CONTINUOUS | MPR_EVENT_QUICK); } }
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); }
/* Start the command to run (stdIn and stdOut are named from the client's perspective). This is the lower-level way to run a command. The caller needs to do code like mprRunCmd() themselves to wait for completion and to send/receive data. The routine does not wait. Callers must call mprWaitForCmd to wait for the command to complete. */ PUBLIC int mprStartCmd(MprCmd *cmd, int argc, cchar **argv, cchar **envp, int flags) { MprPath info; cchar *pair; int rc, next, i; assert(cmd); assert(argv); if (argc <= 0 || argv == NULL || argv[0] == NULL) { return MPR_ERR_BAD_ARGS; } resetCmd(cmd, 0); cmd->flags = flags; cmd->argc = argc; cmd->argv = mprAlloc((argc + 1) * sizeof(char*)); for (i = 0; i < argc; i++) { cmd->argv[i] = sclone(argv[i]); } cmd->argv[i] = 0; prepWinProgram(cmd); if ((cmd->program = mprSearchPath(cmd->argv[0], MPR_SEARCH_EXE, cmd->searchPath, NULL)) == 0) { mprLog("error mpr cmd", 0, "Cannot access %s, errno %d", cmd->argv[0], mprGetOsError()); return MPR_ERR_CANT_ACCESS; } if (mprGetPathInfo(cmd->program, &info) == 0 && info.isDir) { mprLog("error mpr cmd", 0, "Program \"%s\", is a directory", cmd->program); return MPR_ERR_CANT_ACCESS; } mprLog("info mpr cmd", 6, "Program: %s", cmd->program); cmd->argv[0] = cmd->program; prepWinCommand(cmd); if (envp == 0) { envp = cmd->defaultEnv; } if (blendEnv(cmd, envp, flags) < 0) { return MPR_ERR_MEMORY; } for (i = 0; i < cmd->argc; i++) { mprLog("info mpr cmd", 6, " arg[%d]: %s", i, cmd->argv[i]); } for (ITERATE_ITEMS(cmd->env, pair, next)) { mprLog("info mpr cmd", 6, " env[%d]: %s", next, pair); } slock(cmd); if (makeCmdIO(cmd) < 0) { sunlock(cmd); return MPR_ERR_CANT_OPEN; } /* Determine how many end-of-files will be seen when the child dies */ cmd->requiredEof = 0; if (cmd->flags & MPR_CMD_OUT) { cmd->requiredEof++; } if (cmd->flags & MPR_CMD_ERR) { cmd->requiredEof++; } if (addCmdHandlers(cmd) < 0) { mprLog("error mpr cmd", 0, "Cannot open command handlers - insufficient I/O handles"); return MPR_ERR_CANT_OPEN; } rc = startProcess(cmd); cmd->originalPid = cmd->pid; mprAddItem(MPR->cmdService->cmds, cmd); sunlock(cmd); #if ME_WIN_LIKE if (!rc) { mprCreateTimerEvent(cmd->dispatcher, "pollWinTimer", 10, pollWinTimer, cmd, 0); } #endif return rc; }
/* Do a performance benchmark */ static void doBenchmark(void *thread) { MprTime start; MprList *list; int count, i; MprMutex *lock; MprSpin *spin; mprPrintf("Group\t%-30s\t%13s\t%12s\n", "Benchmark", "Microsec", "Elapsed-sec"); testMalloc(); if (!app->testAllocOnly) { /* Locking primitives */ mprPrintf("Lock Benchmarks\n"); lock = mprCreateLock(); count = 5000000 * app->iterations; start = startMark(); for (i = 0; i < count; i++) { mprLock(lock); mprUnlock(lock); } endMark(start, count, "Mutex lock|unlock"); /* Locking primitives */ mprPrintf("Lock Benchmarks\n"); spin = mprCreateSpinLock(); count = 5000000 * app->iterations; start = startMark(); for (i = 0; i < count; i++) { mprSpinLock(spin); mprSpinUnlock(spin); } endMark(start, count, "Spin lock|unlock"); /* Condition signal / wait */ mprPrintf("Cond Benchmarks\n"); count = 1000000 * app->iterations; start = startMark(); mprResetCond(app->complete); for (i = 0; i < count; i++) { mprSignalCond(app->complete); mprWaitForCond(app->complete, -1); } endMark(start, count, "Cond signal|wait"); /* List */ mprPrintf("List Benchmarks\n"); count = 2000000 * app->iterations; list = mprCreateList(count, 0); start = startMark(); for (i = 0; i < count; i++) { mprAddItem(list, (void*) (long) i); mprRemoveItem(list, (void*) (long) i); } endMark(start, count, "Link insert|remove"); /* Events */ mprPrintf("Event Benchmarks\n"); mprResetCond(app->complete); count = 30000 * app->iterations; app->markCount = count; start = startMark(); for (i = 0; i < count; i++) { mprCreateEvent(NULL, "eventBenchmark", 0, eventCallback, ITOP(i), MPR_EVENT_QUICK); } mprWaitForCond(app->complete, -1); endMark(start, count, "Event (create|run|delete)"); /* Test timer creation, run and remove These create a new dispatcher and run a worker thread. */ mprPrintf("Timer\n"); mprResetCond(app->complete); count = 20000 * app->iterations; app->markCount = count; start = startMark(); for (i = 0; i < count; i++) { mprCreateTimerEvent(NULL, "timerBenchmark", 0, timerCallback, (void*) (long) i, 0); } mprWaitForCond(app->complete, -1); endMark(start, count, "Timer (create|delete)"); /* Alloc (1K) */ mprPrintf("Alloc 1K Benchmarks\n"); count = 2000000 * app->iterations; start = startMark(); for (i = 0; i < count; i++) { mprAlloc(1024); if ((i % 128) == 0) { mprGC(0); } } endMark(start, count, "Alloc mprAlloc(1K)"); } testComplete = 1; }
ssize mprWriteCache(MprCache *cache, cchar *key, cchar *value, MprTime modified, MprTime lifespan, int64 version, int options) { CacheItem *item; MprKey *kp; ssize len, oldLen; int exists, add, set, prepend, append, throw; mprAssert(cache); mprAssert(key && *key); mprAssert(value); if (cache->shared) { cache = cache->shared; mprAssert(cache == shared); } exists = add = prepend = append = throw = 0; add = options & MPR_CACHE_ADD; append = options & MPR_CACHE_APPEND; prepend = options & MPR_CACHE_PREPEND; set = options & MPR_CACHE_SET; if ((add + append + prepend) == 0) { set = 1; } lock(cache); if ((kp = mprLookupKeyEntry(cache->store, key)) != 0) { exists++; item = (CacheItem*) kp->data; if (version) { if (item->version != version) { unlock(cache); return MPR_ERR_BAD_STATE; } } } else { if ((item = mprAllocObj(CacheItem, manageCacheItem)) == 0) { unlock(cache); return 0; } mprAddKey(cache->store, key, item); item->key = sclone(key); set = 1; } oldLen = (item->data) ? (slen(item->key) + slen(item->data)) : 0; if (set) { item->data = sclone(value); } else if (add) { if (exists) { return 0; } item->data = sclone(value); } else if (append) { item->data = sjoin(item->data, value, NULL); } else if (prepend) { item->data = sjoin(value, item->data, NULL); } if (lifespan >= 0) { item->lifespan = lifespan; } item->lastAccessed = mprGetTime(); item->lastAccessed = item->lastModified = modified ? modified : item->lastAccessed; item->expires = item->lastAccessed + item->lifespan; item->version++; len = slen(item->key) + slen(item->data); cache->usedMem += (len - oldLen); if (cache->timer == 0) { mprLog(5, "Start Cache pruner with resolution %d", cache->resolution); /* Use the MPR dispatcher incase this VM is destroyed */ cache->timer = mprCreateTimerEvent(MPR->dispatcher, "localCacheTimer", cache->resolution, pruneCache, cache, MPR_EVENT_STATIC_DATA); } unlock(cache); return len; }
/* * Do a performance benchmark */ static void doBenchmark(Mpr *mpr, void *thread) { MprTime start; MprList *list; void *mp; int count, i; #if BLD_FEATURE_MULTITHREAD MprMutex *lock; #endif complete = mprCreateCond(mpr); mprPrintf(mpr, "Group\t%-30s\t%13s\t%12s\n", "Benchmark", "Microsec", "Elapsed-sec"); /* * Alloc (1K) */ mprPrintf(mpr, "Alloc Benchmarks\n"); count = 2000000 * iterations; start = startMark(mpr); for (i = 0; i < count; i++) { mp = mprAlloc(mpr, 1024); memset(mp, 0, 1024); mprFree(mp); } endMark(mpr, start, count, "Alloc mprAlloc(1K)|mprFree"); start = startMark(mpr); #if BLD_FEATURE_MULTITHREAD /* * Locking primitives */ mprPrintf(mpr, "Lock Benchmarks\n"); lock = mprCreateLock(mpr); count = 5000000 * iterations; start = startMark(mpr); for (i = 0; i < count; i++) { mprLock(lock); mprUnlock(lock); } endMark(mpr, start, count, "Mutex lock|unlock"); mprFree(lock); /* * Condition signal / wait */ mprPrintf(mpr, "Cond Benchmarks\n"); count = 1000000 * iterations; start = startMark(mpr); mprResetCond(complete); for (i = 0; i < count; i++) { mprSignalCond(complete); mprWaitForCond(complete, -1); } endMark(mpr, start, count, "Cond signal|wait"); #endif /* * List */ mprPrintf(mpr, "List Benchmarks\n"); count = 500000 * iterations; list = mprCreateList(mpr); start = startMark(mpr); for (i = 0; i < count; i++) { mprAddItem(list, (void*) (long) i); mprRemoveItem(list, (void*) (long) i); } endMark(mpr, start, count, "Link insert|remove"); mprFree(list);; /* * Events */ mprPrintf(mpr, "Event Benchmarks\n"); mprResetCond(complete); count = 200000 * iterations; markCount = count; start = startMark(mpr); for (i = 0; i < count; i++) { mprCreateEvent(mprGetDispatcher(mpr), eventCallback, 0, 0, (void*) (long) i, 0); } endMark(mpr, start, count, "Event (create)"); mprWaitForCondWithService(complete, -1); endMark(mpr, start, count, "Event (run|delete)"); /* * Test timer creation, run and delete (make a million timers!) */ mprPrintf(mpr, "Timer\n"); mprResetCond(complete); count = 50000 * iterations; markCount = count; start = startMark(mpr); for (i = 0; i < count; i++) { mprCreateTimerEvent(mprGetDispatcher(mpr), timerCallback, 0, 0, (void*) (long) i, 0); } endMark(mpr, start, count, "Timer (create)"); mprWaitForCondWithService(complete, -1); endMark(mpr, start, count, "Timer (delete)"); testComplete = 1; }
/* * Start the host timer. This may create multiple timers -- no worry. maAddConn does its best to only schedule one. */ static void startTimer(MaHost *host) { host->timer = mprCreateTimerEvent(mprGetDispatcher(host), (MprEventProc) hostTimer, MA_TIMER_PERIOD, MPR_NORMAL_PRIORITY, host, MPR_EVENT_CONTINUOUS); }