Пример #1
0
static int createEndpoints(int argc, char **argv)
{
    cchar   *endpoint;
    char    *ip;
    int     argind, port, secure;

    ip = 0;
    port = -1;
    endpoint = 0;
    argind = 0;

    if ((app->appweb = maCreateAppweb()) == 0) {
        mprLog("error appweb", 0, "Cannot create HTTP service");
        return MPR_ERR_CANT_CREATE;
    }
    if ((app->server = maCreateServer(app->appweb, "default")) == 0) {
        mprLog("error appweb", 0, "Cannot create HTTP server");
        return MPR_ERR_CANT_CREATE;
    }
    loadStaticModules();
    mprGC(MPR_GC_FORCE | MPR_GC_COMPLETE);

    if (argind == argc) {
        if (maParseConfig(app->server, app->configFile, 0) < 0) {
            return MPR_ERR_CANT_CREATE;
        }
    } else {
        app->documents = sclone(argv[argind++]);
        if (argind == argc) {
            if (maConfigureServer(app->server, NULL, app->home, app->documents, NULL, ME_HTTP_PORT, 0) < 0) {
                return MPR_ERR_CANT_CREATE;
            }
        } else while (argind < argc) {
            endpoint = argv[argind++];
            mprParseSocketAddress(endpoint, &ip, &port, &secure, 80);
            if (maConfigureServer(app->server, NULL, app->home, app->documents, ip, port, 0) < 0) {
                return MPR_ERR_CANT_CREATE;
            }
        }
    }
    if (app->workers >= 0) {
        mprSetMaxWorkers(app->workers);
    }
    /*
        Call any ESP initializers from slink.c
     */
    appwebStaticInitialize();
    
#if ME_WIN_LIKE
    writePort(app->server);
#elif ME_UNIX_LIKE
    addSignals();
#endif
    mprGC(MPR_GC_FORCE | MPR_GC_COMPLETE);
    return 0;
}
Пример #2
0
static void endMark(MprTime start, int count, char *msg)
{
    MprTime     elapsed;

    elapsed = mprGetElapsedTime(start);
    mprPrintf("\t%-30s\t%13.2f\t%12.2f\n", msg, elapsed * 1000.0 / count, elapsed / 1000.0);
    mprGC(MPR_GC_FORCE | MPR_GC_COMPLETE);
}
Пример #3
0
static int createEndpoints(int argc, char **argv)
{
    HttpHost    *host;
    HttpRoute   *route;

    host = httpCreateHost();
    httpSetDefaultHost(host);
    route = httpCreateRoute(host);
    httpSetHostDefaultRoute(host, route);
    httpFinalizeRoute(route);

    httpInitConfig(route);
    if (httpLoadConfig(route, app->configFile) < 0) {
        return MPR_ERR_CANT_CREATE;
    }
    mprGC(MPR_GC_FORCE | MPR_GC_COMPLETE);
    return 0;
}
Пример #4
0
MAIN(ejsMain, int argc, char **argv, char **envp)
{
    Mpr             *mpr;
    EcCompiler      *cp;
    Ejs             *ejs;
    cchar           *cmd, *className, *method, *homeDir, *logSpec, *traceSpec;
    char            *argp, *searchPath, *modules, *name, *tok, *extraFiles;
    int             nextArg, err, ecFlags, stats, merge, bind, noout, debug, optimizeLevel, warnLevel, strict, i, next;

    /*  
        Initialize Multithreaded Portable Runtime (MPR)
     */
    mpr = mprCreate(argc, argv, 0);
    app = mprAllocObj(App, manageApp);
    mprAddRoot(app);
    mprAddStandardSignals();

    if (mprStart(mpr) < 0) {
        mprLog("ejs", 0, "Cannot start mpr services");
        return EJS_ERR;
    }
    err = 0;
    className = 0;
    cmd = 0;
    method = 0;
    searchPath = 0;
    stats = 0;
    merge = 0;
    bind = 1;
    noout = 1;
    debug = 1;
    warnLevel = 1;
    optimizeLevel = 9;
    strict = 0;
    logSpec = 0;
    traceSpec = 0;

    app->files = mprCreateList(-1, 0);
    app->iterations = 1;
    argc = mpr->argc;
    argv = (char**) mpr->argv;

    for (nextArg = 1; nextArg < argc; nextArg++) {
        argp = argv[nextArg];
        if (*argp != '-') {
            break;
        }
        if (smatch(argp, "--bind")) {
            bind = 1;

        } else if (smatch(argp, "--class")) {
            if (nextArg >= argc) {
                err++;
            } else {
                className = argv[++nextArg];
            }

        } else if (smatch(argp, "--chdir") || smatch(argp, "--home") || smatch(argp, "-C")) {
            if (nextArg >= argc) {
                err++;
            } else {
                homeDir = argv[++nextArg];
                if (chdir((char*) homeDir) < 0) {
                    mprLog("ejs", 0, "Cannot change directory to %s", homeDir);
                }
            }

#if ME_UNIX_LIKE
        } else if (smatch(argp, "--chroot")) {
            /* Not documented or supported */
            if (nextArg >= argc) {
                err++;
            } else {
                homeDir = mprGetAbsPath(argv[++nextArg]);
                if (chroot(homeDir) < 0) {
                    if (errno == EPERM) {
                        mprEprintf("%s: Must be super user to use the --chroot option", mprGetAppName(mpr));
                    } else {
                        mprEprintf("%s: Cannot change change root directory to %s, errno %d",
                            mprGetAppName(), homeDir, errno);
                    }
                    return 4;
                }
            }
#endif

        } else if (smatch(argp, "--cmd") || smatch(argp, "-c")) {
            if (nextArg >= argc) {
                err++;
            } else {
                cmd = argv[++nextArg];
            }

#if ME_WIN_LIKE
        } else if (smatch(argp, "--cygroot")) {
            if (nextArg >= argc) {
                err++;
            } else {
                app->cygroot = sclone(argv[++nextArg]);
            }
#endif
        } else if (smatch(argp, "--debug")) {
            debug = 1;

        } else if (smatch(argp, "--debugger") || smatch(argp, "-D")) {
            mprSetDebugMode(1);

        } else if (smatch(argp, "--files") || smatch(argp, "-f")) {
            /* Compatibility with mozilla shell */
            if (nextArg >= argc) {
                err++;
            } else {
                extraFiles = sclone(argv[++nextArg]);
                name = stok(extraFiles, " \t", &tok);
                while (name != NULL) {
                    mprAddItem(app->files, sclone(name));
                    name = stok(NULL, " \t", &tok);
                }
            }

        } else if (smatch(argp, "--iterations") || smatch(argp, "-i")) {
            if (nextArg >= argc) {
                err++;
            } else {
                app->iterations = atoi(argv[++nextArg]);
            }

        } else if (smatch(argp, "--log")) {
            if (nextArg >= argc) {
                err++;
            } else {
                logSpec = argv[++nextArg];
            }

        } else if (smatch(argp, "--method")) {
            if (nextArg >= argc) {
                err++;
            } else {
                method = argv[++nextArg];
            }

        } else if (smatch(argp, "--name")) {
            /* Just ignore. Used to tag commands with a unique command line */ 
            nextArg++;

        } else if (smatch(argp, "--nobind")) {
            bind = 0;

        } else if (smatch(argp, "--nodebug")) {
            debug = 0;

        } else if (smatch(argp, "--optimize")) {
            if (nextArg >= argc) {
                err++;
            } else {
                optimizeLevel = atoi(argv[++nextArg]);
            }

        } else if (smatch(argp, "--require")) {
            if (nextArg >= argc) {
                err++;
            } else {
                if (app->modules == 0) {
                    app->modules = mprCreateList(-1, 0);
                }
                modules = sclone(argv[++nextArg]);
                name = stok(modules, " \t", &tok);
                while (name != NULL) {
                    require(name);
                    name = stok(NULL, " \t", &tok);
                }
            }

        } else if (smatch(argp, "-s")) {
            /* Compatibility with mozilla shell. Just ignore */

        } else if (smatch(argp, "--search") || smatch(argp, "--searchpath")) {
            if (nextArg >= argc) {
                err++;
            } else {
                searchPath = argv[++nextArg];
            }

        } else if (smatch(argp, "--standard")) {
            strict = 0;

        } else if (smatch(argp, "--stats")) {
            stats = 1;

        } else if (smatch(argp, "--strict")) {
            strict = 1;

        } else if (smatch(argp, "--trace") || smatch(argp, "-t")) {
            if (nextArg >= argc) {
                err++;
            } else {
                traceSpec = argv[++nextArg];
            }

        } else if (smatch(argp, "--verbose") || smatch(argp, "-v")) {
            logSpec = "stderr:2";

        } else if (smatch(argp, "--version") || smatch(argp, "-V")) {
            mprPrintf("%s\n", EJS_VERSION);
            return 0;

        } else if (smatch(argp, "--warn")) {
            if (nextArg >= argc) {
                err++;
            } else {
                warnLevel = atoi(argv[++nextArg]);
            }

        } else if (*argp == '-' && isdigit((uchar) argp[1])) {
            if (!logSpec) {
                logSpec = sfmt("stderr:%d", (int) stoi(&argp[1]));
            }
            if (!traceSpec) {
                traceSpec = sfmt("stderr:%d", (int) stoi(&argp[1]));
            }

        } else {
            err++;
            break;
        }
    }

    if (err) {
        /*  
            If --method or --class is specified, then the named class.method will be run (method defaults to "main", class
            defaults to first class with a "main").

            Examples:
                ejs
                ejs script.es arg1 arg2 arg3
                ejs --class "Customer" --method "start" --files "script1.es script2.es" main.es
         */
        mprEprintf("Usage: %s [options] script.es [arguments] ...\n"
            "  Ejscript shell program options:\n"
            "  --class className        # Name of class containing method to run\n"
            "  --cmd ejscriptCode       # Literal ejscript statements to execute\n"
            "  --cygroot path           # Set cygwin root for resolving script paths\n"
            "  --debug                  # Use symbolic debugging information (default)\n"
            "  --debugger               # Disable timeouts to make using a debugger easier\n"
            "  --files \"files..\"        # Extra source to compile\n"
            "  --log logSpec            # Internal compiler diagnostics logging\n"
            "  --method methodName      # Name of method to run. Defaults to main\n"
            "  --nodebug                # Omit symbolic debugging information\n"
            "  --optimize level         # Set the optimization level (0-9 default is 9)\n"
            "  --require 'module,...'   # Required list of modules to pre-load\n"
            "  --search ejsPath         # Module search path\n"
            "  --standard               # Default compilation mode to standard (default)\n"
            "  --stats                  # Print memory stats on exit\n"
            "  --strict                 # Default compilation mode to strict\n"
            "  --trace traceSpec        # HTTP request tracing\n"
            "  --verbose | -v           # Same as --log stderr:2 \n"
            "  --version                # Emit the compiler version information\n"
            "  --warn level             # Set the warning message level (0-9 default is 0)\n\n",
            mpr->name);
        return -1;
    }
    if (logSpec) {
        mprStartLogging(logSpec, MPR_LOG_CMDLINE);
    }
    if (traceSpec) {
        httpCreate(HTTP_CLIENT_SIDE | HTTP_SERVER_SIDE);
        httpStartTracing(traceSpec);
    }
    if ((ejs = ejsCreateVM(argc - nextArg, (cchar **) &argv[nextArg], 0)) == 0) {
        return MPR_ERR_MEMORY;
    }
    mprStartDispatcher(ejs->dispatcher);
    app->ejs = ejs;

    if (ejsLoadModules(ejs, searchPath, app->modules) < 0) {
        return MPR_ERR_CANT_READ;
    }
    mprGC(MPR_GC_FORCE);
    ecFlags = 0;
    ecFlags |= (merge) ? EC_FLAGS_MERGE: 0;
    ecFlags |= (bind) ? EC_FLAGS_BIND: 0;
    ecFlags |= (noout) ? EC_FLAGS_NO_OUT: 0;
    ecFlags |= (debug) ? EC_FLAGS_DEBUG: 0;

    cp = app->compiler = ecCreateCompiler(ejs, ecFlags);
    if (cp == 0) {
        return MPR_ERR_MEMORY;
    }
    ecSetRequire(cp, app->modules);

    ecSetOptimizeLevel(cp, optimizeLevel);
    ecSetWarnLevel(cp, warnLevel);
    ecSetStrictMode(cp, strict);
    if (nextArg < argc) {
        mprAddItem(app->files, sclone(argv[nextArg]));
    }
    if (app->cygroot) {
        /*  
            When cygwin invokes a script with shebang, it passes a cygwin path to the script
            The ejs --cygroot option permits ejscript to conver this to a native path
         */
        for (next = 0; (name = mprGetNextItem(app->files, &next)) != 0; ) {
            if (*name == '/' || *name == '\\') {
                mprSetItem(app->files, next - 1, sjoin(app->cygroot, name, NULL));
            }
        }
    }
    for (i = 0; !err && i < app->iterations; i++) {
        if (cmd) {
            if (interpretCommands(cp, cmd) < 0) {
                err++;
            }
        } else if (mprGetListLength(app->files) > 0) {
            if (interpretFiles(cp, app->files, argc - nextArg, &argv[nextArg], className, method) < 0) {
                err++;
            }
        } else {
            /*  
                No args - run as an interactive shell
             */
            if (interpretCommands(cp, NULL) < 0) {
                err++;
            }
        }
    }
    if (stats) {
#if ME_DEBUG
        mprSetLogLevel(1);
        mprPrintMem("Memory Usage", 1);
#endif
    }
    if (err) {
        mprSetExitStatus(err);
    }
    app->ejs = 0;
    app->compiler = 0;
    ejsDestroy(ejs);
    mprDestroy();
    return mprGetExitStatus();
}
Пример #5
0
static void testMalloc()
{
    MprTime     start;
    char        *ptr;
    int         count, i, pin;
#if KEEP
    ssize    base;
#endif

    mprPrintf("Alloc/Malloc overhead\n");
    count = 2000000 * app->iterations;
    pin = 0;
    mprGC(MPR_GC_FORCE);
    
#if MALLOC
    /*
        malloc(1)
     */

    base = mprGetMem();
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = malloc(1);
        if (pin) memset(ptr, 0, 1);
    }
    endMark(start, count, "Alloc malloc(1)");
    mprPrintf("\tMalloc overhead per block %d\n\n", ((mprGetMem() - base) / count) - 1);

    /*
        malloc(8)
     */
    base = mprGetMem();
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = malloc(8);
        if (pin) memset(ptr, 0, 8);
    }
    endMark(start, count, "Alloc malloc(8)");
    mprPrintf("\tMalloc overhead per block %d (approx)\n\n", ((mprGetMem() - base) / count) - 8);

    /*
        malloc(16)
     */
    base = mprGetMem();
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = malloc(16);
        if (pin) memset(ptr, 0, 16);
    }
    endMark(start, count, "Alloc malloc(16)");
    mprPrintf("\tMalloc overhead per block %d (approx)\n\n", ((mprGetMem() - base) / count) - 16);

    /*
        malloc(32)
     */
    base = mprGetMem();
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = malloc(32);
        if (pin) memset(ptr, 0, 32);
    }
    endMark(start, count, "Alloc malloc(32)");
    mprPrintf("\tMalloc overhead per block %d (approx)\n\n", ((mprGetMem() - base) / count) - 32);

    /*
        malloc+free(8)
     */
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = malloc(8);
        if (pin) memset(ptr, 0, 8);
        mprNop(ptr);
        free(ptr);
    }
    endMark(start, count, "Alloc malloc+free(8)");
    mprPrintf("\n");
#endif

    /*
        mprAlloc(1)
     */
    // base = mprGetMem();
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = mprAlloc(1);
        if (pin) memset(ptr, 0, 1);
    }
    endMark(start, count, "Alloc mprAlloc(1)");
    // mprPrintf("\tMpr overhead per block %d (approx)\n\n", ((mprGetMem() - base) / count) - 1);

    /*
        mprAlloc(8)
     */
    // base = mprGetMem();
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = mprAlloc(8);
        if (pin) memset(ptr, 0, 8);
    }
    endMark(start, count, "Alloc mprAlloc(8)");
    // mprPrintf("\tMpr overhead per block %d (approx)\n\n", ((mprGetMem() - base) / count) - 8);

    /*
        mprAlloc(16)
     */
    // base = mprGetMem();
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = mprAlloc(16);
        if (pin) memset(ptr, 0, 16);
    }
    endMark(start, count, "Alloc mprAlloc(16)");
    // mprPrintf("\tMpr overhead per block %d (approx)\n\n", ((mprGetMem() - base) / count) - 16);

    /*
        mprAlloc(32)
     */
    // base = mprGetMem();
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = mprAlloc(32);
        if (pin) memset(ptr, 0, 32);
    }
    endMark(start, count, "Alloc mprAlloc(32)");
    // mprPrintf("\tMpr overhead per block %d (approx)\n\n", ((mprGetMem() - base) / count) - 32);

    /*
        mprAlloc(64)
     */
    // base = mprGetMem();
    start = startMark();
    for (i = 0; i < count; i++) {
        ptr = mprAlloc(64);
        if (pin) memset(ptr, 0, 64);
    }
    endMark(start, count, "Alloc mprAlloc(32)");
    // mprPrintf("\tMpr overhead per block %d (approx)\n\n", ((mprGetMem() - base) / count) - 64);

    mprPrintf("\n");
}
Пример #6
0
/*
    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;
}
Пример #7
0
/*
    The http timer does maintenance activities and will fire per second while there are active requests.
    This routine will also be called by httpTerminate with event == 0 to signify a shutdown.
    NOTE: Because we lock the http here, connections cannot be deleted while we are modifying the list.
 */
static void httpTimer(Http *http, MprEvent *event)
{
    HttpConn    *conn;
    HttpStage   *stage;
    HttpLimits  *limits;
    MprModule   *module;
    int         next, active, abort;

    updateCurrentDate();

    /* 
       Check for any inactive connections or expired requests (inactivityTimeout and requestTimeout)
       OPT - could check for expired connections every 10 seconds.
     */
    lock(http->connections);
    for (active = 0, next = 0; (conn = mprGetNextItem(http->connections, &next)) != 0; active++) {
        limits = conn->limits;
        if (!conn->timeoutEvent) {
            abort = mprIsStopping();
            if (httpServerConn(conn) && (HTTP_STATE_CONNECTED < conn->state && conn->state < HTTP_STATE_PARSED) && 
                    (http->now - conn->started) > limits->requestParseTimeout) {
                conn->timeout = HTTP_PARSE_TIMEOUT;
                abort = 1;
            } else if ((http->now - conn->lastActivity) > limits->inactivityTimeout) {
                conn->timeout = HTTP_INACTIVITY_TIMEOUT;
                abort = 1;
            } else if ((http->now - conn->started) > limits->requestTimeout) {
                conn->timeout = HTTP_REQUEST_TIMEOUT;
                abort = 1;
            } else if (!event) {
                /* Called directly from httpStop to stop connections */
                if (MPR->exitTimeout > 0) {
                    if (conn->state == HTTP_STATE_COMPLETE || 
                        (HTTP_STATE_CONNECTED < conn->state && conn->state < HTTP_STATE_PARSED)) {
                        abort = 1;
                    }
                } else {
                    abort = 1;
                }
            }
            if (abort && !mprGetDebugMode()) {
                httpScheduleConnTimeout(conn);
            }
        }
    }

    /*
        Check for unloadable modules
        OPT - could check for modules every minute
     */
    if (mprGetListLength(http->connections) == 0) {
        for (next = 0; (module = mprGetNextItem(MPR->moduleService->modules, &next)) != 0; ) {
            if (module->timeout) {
                if (module->lastActivity + module->timeout < http->now) {
                    mprLog("info http", 2, "Unloading inactive module %s", module->name);
                    if ((stage = httpLookupStage(module->name)) != 0) {
                        if (mprUnloadModule(module) < 0)  {
                            active++;
                        } else {
                            stage->flags |= HTTP_STAGE_UNLOADED;
                        }
                    } else {
                        mprUnloadModule(module);
                    }
                } else {
                    active++;
                }
            }
        }
    }
    httpPruneMonitors();

    if (active == 0 || mprIsStopping()) {
        if (event) {
            mprRemoveEvent(event);
        }
        http->timer = 0;
        /*
            Going to sleep now, so schedule a GC to free as much as possible.
         */
        mprGC(MPR_GC_FORCE | MPR_GC_NO_BLOCK);
    } else {
        mprGC(MPR_GC_NO_BLOCK);
    }
    unlock(http->connections);
}