Exemplo n.º 1
0
    void _initAndListen(int listenPort ) {

        Client::initThread("initandlisten");

        bool is32bit = sizeof(int*) == 4;

        {
            ProcessId pid = ProcessId::getCurrent();
            LogstreamBuilder l = log();
            l << "MongoDB starting : pid=" << pid
              << " port=" << serverGlobalParams.port
              << " dbpath=" << storageGlobalParams.dbpath;
            if( replSettings.master ) l << " master=" << replSettings.master;
            if( replSettings.slave )  l << " slave=" << (int) replSettings.slave;
            l << ( is32bit ? " 32" : " 64" ) << "-bit host=" << getHostNameCached() << endl;
        }
        DEV log() << "_DEBUG build (which is slower)" << endl;
        logStartupWarnings();
#if defined(_WIN32)
        printTargetMinOS();
#endif
        logProcessDetails();
        {
            stringstream ss;
            ss << endl;
            ss << "*********************************************************************" << endl;
            ss << " ERROR: dbpath (" << storageGlobalParams.dbpath << ") does not exist." << endl;
            ss << " Create this directory or give existing directory in --dbpath." << endl;
            ss << " See http://dochub.mongodb.org/core/startingandstoppingmongo" << endl;
            ss << "*********************************************************************" << endl;
            uassert(10296,  ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.dbpath));
        }
        {
            stringstream ss;
            ss << "repairpath (" << storageGlobalParams.repairpath << ") does not exist";
            uassert(12590,  ss.str().c_str(),
                    boost::filesystem::exists(storageGlobalParams.repairpath));
        }

        // TODO check non-journal subdirs if using directory-per-db
        checkReadAhead(storageGlobalParams.dbpath);

        acquirePathLock(mongodGlobalParams.repair);
        boost::filesystem::remove_all(storageGlobalParams.dbpath + "/_tmp/");

        FileAllocator::get()->start();

        // TODO:  This should go into a MONGO_INITIALIZER once we have figured out the correct
        // dependencies.
        if (snmpInit) {
            snmpInit();
        }

        MONGO_ASSERT_ON_EXCEPTION_WITH_MSG( clearTmpFiles(), "clear tmp files" );

        dur::startup();

        if (storageGlobalParams.durOptions & StorageGlobalParams::DurRecoverOnly)
            return;

        unsigned long long missingRepl = checkIfReplMissingFromCommandLine();
        if (missingRepl) {
            log() << startupWarningsLog;
            log() << "** WARNING: mongod started without --replSet yet " << missingRepl
                  << " documents are present in local.system.replset" << startupWarningsLog;
            log() << "**          Restart with --replSet unless you are doing maintenance and no"
                  << " other clients are connected." << startupWarningsLog;
            log() << "**          The TTL collection monitor will not start because of this." << startupWarningsLog;
            log() << "**          For more info see http://dochub.mongodb.org/core/ttlcollections" << startupWarningsLog;
            log() << startupWarningsLog;
        }

        if (mongodGlobalParams.scriptingEnabled) {
            ScriptEngine::setup();
            globalScriptEngine->setCheckInterruptCallback( jsInterruptCallback );
            globalScriptEngine->setGetCurrentOpIdCallback( jsGetCurrentOpIdCallback );
        }

        // On replica set members we only clear temp collections on DBs other than "local" during
        // promotion to primary. On pure slaves, they are only cleared when the oplog tells them to.
        // The local DB is special because it is not replicated.  See SERVER-10927 for more details.
        const bool shouldClearNonLocalTmpCollections = !(missingRepl
                                                         || replSettings.usingReplSets()
                                                         || replSettings.slave == SimpleSlave);
        repairDatabasesAndCheckVersion(shouldClearNonLocalTmpCollections);

        if (mongodGlobalParams.upgrade)
            return;

        uassertStatusOK(getGlobalAuthorizationManager()->initialize());

        /* this is for security on certain platforms (nonce generation) */
        srand((unsigned) (curTimeMicros() ^ startupSrandTimer.micros()));

        snapshotThread.go();
        d.clientCursorMonitor.go();
        PeriodicTask::startRunningPeriodicTasks();
        if (missingRepl) {
            // a warning was logged earlier
        }
        else {
            startTTLBackgroundJob();
        }

#ifndef _WIN32
        mongo::signalForkSuccess();
#endif

        if(getGlobalAuthorizationManager()->isAuthEnabled()) {
            // open admin db in case we need to use it later. TODO this is not the right way to
            // resolve this.
            Client::WriteContext c("admin", storageGlobalParams.dbpath);
        }

        authindex::configureSystemIndexes("admin");

        getDeleter()->startWorkers();

        // Starts a background thread that rebuilds all incomplete indices. 
        indexRebuilder.go(); 

        listen(listenPort);

        // listen() will return when exit code closes its socket.
        exitCleanly(EXIT_NET_ERROR);
    }
Exemplo n.º 2
0
ExitCode _initAndListen(int listenPort) {
    Client::initThread("initandlisten");

    _initWireSpec();
    auto globalServiceContext = getGlobalServiceContext();

    globalServiceContext->setFastClockSource(FastClockSourceFactory::create(Milliseconds(10)));
    globalServiceContext->setOpObserver(stdx::make_unique<OpObserver>());

    DBDirectClientFactory::get(globalServiceContext)
        .registerImplementation([](OperationContext* txn) {
            return std::unique_ptr<DBClientBase>(new DBDirectClient(txn));
        });

    const repl::ReplSettings& replSettings = repl::getGlobalReplicationCoordinator()->getSettings();

    {
        ProcessId pid = ProcessId::getCurrent();
        LogstreamBuilder l = log(LogComponent::kControl);
        l << "MongoDB starting : pid=" << pid << " port=" << serverGlobalParams.port
          << " dbpath=" << storageGlobalParams.dbpath;
        if (replSettings.isMaster())
            l << " master=" << replSettings.isMaster();
        if (replSettings.isSlave())
            l << " slave=" << (int)replSettings.isSlave();

        const bool is32bit = sizeof(int*) == 4;
        l << (is32bit ? " 32" : " 64") << "-bit host=" << getHostNameCached() << endl;
    }

    DEV log(LogComponent::kControl) << "DEBUG build (which is slower)" << endl;

#if defined(_WIN32)
    VersionInfoInterface::instance().logTargetMinOS();
#endif

    logProcessDetails();

    checked_cast<ServiceContextMongoD*>(getGlobalServiceContext())->createLockFile();

    transport::TransportLayerLegacy::Options options;
    options.port = listenPort;
    options.ipList = serverGlobalParams.bind_ip;

    auto sep =
        stdx::make_unique<ServiceEntryPointMongod>(getGlobalServiceContext()->getTransportLayer());
    auto sepPtr = sep.get();

    getGlobalServiceContext()->setServiceEntryPoint(std::move(sep));

    // Create, start, and attach the TL
    auto transportLayer = stdx::make_unique<transport::TransportLayerLegacy>(options, sepPtr);
    auto res = transportLayer->setup();
    if (!res.isOK()) {
        error() << "Failed to set up listener: " << res;
        return EXIT_NET_ERROR;
    }

    std::shared_ptr<DbWebServer> dbWebServer;
    if (serverGlobalParams.isHttpInterfaceEnabled) {
        dbWebServer.reset(new DbWebServer(serverGlobalParams.bind_ip,
                                          serverGlobalParams.port + 1000,
                                          getGlobalServiceContext(),
                                          new RestAdminAccess()));
        if (!dbWebServer->setupSockets()) {
            error() << "Failed to set up sockets for HTTP interface during startup.";
            return EXIT_NET_ERROR;
        }
    }

    getGlobalServiceContext()->initializeGlobalStorageEngine();

#ifdef MONGO_CONFIG_WIREDTIGER_ENABLED
    if (WiredTigerCustomizationHooks::get(getGlobalServiceContext())->restartRequired()) {
        exitCleanly(EXIT_CLEAN);
    }
#endif

    // Warn if we detect configurations for multiple registered storage engines in
    // the same configuration file/environment.
    if (serverGlobalParams.parsedOpts.hasField("storage")) {
        BSONElement storageElement = serverGlobalParams.parsedOpts.getField("storage");
        invariant(storageElement.isABSONObj());
        BSONObj storageParamsObj = storageElement.Obj();
        BSONObjIterator i = storageParamsObj.begin();
        while (i.more()) {
            BSONElement e = i.next();
            // Ignore if field name under "storage" matches current storage engine.
            if (storageGlobalParams.engine == e.fieldName()) {
                continue;
            }

            // Warn if field name matches non-active registered storage engine.
            if (getGlobalServiceContext()->isRegisteredStorageEngine(e.fieldName())) {
                warning() << "Detected configuration for non-active storage engine "
                          << e.fieldName() << " when current storage engine is "
                          << storageGlobalParams.engine;
            }
        }
    }

    if (!getGlobalServiceContext()->getGlobalStorageEngine()->getSnapshotManager()) {
        if (moe::startupOptionsParsed.count("replication.enableMajorityReadConcern") &&
            moe::startupOptionsParsed["replication.enableMajorityReadConcern"].as<bool>()) {
            // Note: we are intentionally only erroring if the user explicitly requested that we
            // enable majority read concern. We do not error if the they are implicitly enabled for
            // CSRS because a required step in the upgrade procedure can involve an mmapv1 node in
            // the CSRS in the REMOVED state. This is handled by the TopologyCoordinator.
            invariant(replSettings.isMajorityReadConcernEnabled());
            severe() << "Majority read concern requires a storage engine that supports"
                     << " snapshots, such as wiredTiger. " << storageGlobalParams.engine
                     << " does not support snapshots.";
            exitCleanly(EXIT_BADOPTIONS);
        }
    }

    logMongodStartupWarnings(storageGlobalParams, serverGlobalParams);

    {
        stringstream ss;
        ss << endl;
        ss << "*********************************************************************" << endl;
        ss << " ERROR: dbpath (" << storageGlobalParams.dbpath << ") does not exist." << endl;
        ss << " Create this directory or give existing directory in --dbpath." << endl;
        ss << " See http://dochub.mongodb.org/core/startingandstoppingmongo" << endl;
        ss << "*********************************************************************" << endl;
        uassert(10296, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.dbpath));
    }

    {
        stringstream ss;
        ss << "repairpath (" << storageGlobalParams.repairpath << ") does not exist";
        uassert(12590, ss.str().c_str(), boost::filesystem::exists(storageGlobalParams.repairpath));
    }

    // TODO:  This should go into a MONGO_INITIALIZER once we have figured out the correct
    // dependencies.
    if (snmpInit) {
        snmpInit();
    }

    if (!storageGlobalParams.readOnly) {
        boost::filesystem::remove_all(storageGlobalParams.dbpath + "/_tmp/");
    }

    if (mmapv1GlobalOptions.journalOptions & MMAPV1Options::JournalRecoverOnly)
        return EXIT_NET_ERROR;

    if (mongodGlobalParams.scriptingEnabled) {
        ScriptEngine::setup();
    }

    auto startupOpCtx = getGlobalServiceContext()->makeOperationContext(&cc());

    repairDatabasesAndCheckVersion(startupOpCtx.get());

    if (storageGlobalParams.upgrade) {
        log() << "finished checking dbs";
        exitCleanly(EXIT_CLEAN);
    }

    uassertStatusOK(getGlobalAuthorizationManager()->initialize(startupOpCtx.get()));

    /* this is for security on certain platforms (nonce generation) */
    srand((unsigned)(curTimeMicros64() ^ startupSrandTimer.micros()));

    // The snapshot thread provides historical collection level and lock statistics for use
    // by the web interface. Only needed when HTTP is enabled.
    if (serverGlobalParams.isHttpInterfaceEnabled) {
        statsSnapshotThread.go();

        invariant(dbWebServer);
        stdx::thread web(stdx::bind(&webServerListenThread, dbWebServer));
        web.detach();
    }

#ifndef _WIN32
    mongo::signalForkSuccess();
#endif
    AuthorizationManager* globalAuthzManager = getGlobalAuthorizationManager();
    if (globalAuthzManager->shouldValidateAuthSchemaOnStartup()) {
        Status status = authindex::verifySystemIndexes(startupOpCtx.get());
        if (!status.isOK()) {
            log() << redact(status);
            exitCleanly(EXIT_NEED_UPGRADE);
        }

        // SERVER-14090: Verify that auth schema version is schemaVersion26Final.
        int foundSchemaVersion;
        status =
            globalAuthzManager->getAuthorizationVersion(startupOpCtx.get(), &foundSchemaVersion);
        if (!status.isOK()) {
            log() << "Auth schema version is incompatible: "
                  << "User and role management commands require auth data to have "
                  << "at least schema version " << AuthorizationManager::schemaVersion26Final
                  << " but startup could not verify schema version: " << status;
            exitCleanly(EXIT_NEED_UPGRADE);
        }
        if (foundSchemaVersion < AuthorizationManager::schemaVersion26Final) {
            log() << "Auth schema version is incompatible: "
                  << "User and role management commands require auth data to have "
                  << "at least schema version " << AuthorizationManager::schemaVersion26Final
                  << " but found " << foundSchemaVersion << ". In order to upgrade "
                  << "the auth schema, first downgrade MongoDB binaries to version "
                  << "2.6 and then run the authSchemaUpgrade command.";
            exitCleanly(EXIT_NEED_UPGRADE);
        }
    } else if (globalAuthzManager->isAuthEnabled()) {
        error() << "Auth must be disabled when starting without auth schema validation";
        exitCleanly(EXIT_BADOPTIONS);
    } else {
        // If authSchemaValidation is disabled and server is running without auth,
        // warn the user and continue startup without authSchema metadata checks.
        log() << startupWarningsLog;
        log() << "** WARNING: Startup auth schema validation checks are disabled for the "
                 "database."
              << startupWarningsLog;
        log() << "**          This mode should only be used to manually repair corrupted auth "
                 "data."
              << startupWarningsLog;
    }

    auto shardingInitialized =
        uassertStatusOK(ShardingState::get(startupOpCtx.get())
                            ->initializeShardingAwarenessIfNeeded(startupOpCtx.get()));
    if (shardingInitialized) {
        reloadShardRegistryUntilSuccess(startupOpCtx.get());
    }

    if (!storageGlobalParams.readOnly) {
        logStartup(startupOpCtx.get());

        startFTDC();

        getDeleter()->startWorkers();

        restartInProgressIndexesFromLastShutdown(startupOpCtx.get());

        if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) {
            // Note: For replica sets, ShardingStateRecovery happens on transition to primary.
            if (!repl::getGlobalReplicationCoordinator()->isReplEnabled()) {
                uassertStatusOK(ShardingStateRecovery::recover(startupOpCtx.get()));
            }
        } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) {
            uassertStatusOK(
                initializeGlobalShardingStateForMongod(startupOpCtx.get(),
                                                       ConnectionString::forLocal(),
                                                       kDistLockProcessIdForConfigServer));
            Balancer::create(startupOpCtx->getServiceContext());
        }

        repl::getGlobalReplicationCoordinator()->startup(startupOpCtx.get());

        const unsigned long long missingRepl =
            checkIfReplMissingFromCommandLine(startupOpCtx.get());
        if (missingRepl) {
            log() << startupWarningsLog;
            log() << "** WARNING: mongod started without --replSet yet " << missingRepl
                  << " documents are present in local.system.replset" << startupWarningsLog;
            log() << "**          Restart with --replSet unless you are doing maintenance and "
                  << " no other clients are connected." << startupWarningsLog;
            log() << "**          The TTL collection monitor will not start because of this."
                  << startupWarningsLog;
            log() << "**         ";
            log() << " For more info see http://dochub.mongodb.org/core/ttlcollections";
            log() << startupWarningsLog;
        } else {
            startTTLBackgroundJob();
        }

        if (!replSettings.usingReplSets() && !replSettings.isSlave() &&
            storageGlobalParams.engine != "devnull") {
            ScopedTransaction transaction(startupOpCtx.get(), MODE_X);
            Lock::GlobalWrite lk(startupOpCtx.get()->lockState());
            FeatureCompatibilityVersion::setIfCleanStartup(
                startupOpCtx.get(), repl::StorageInterface::get(getGlobalServiceContext()));
        }
    }

    startClientCursorMonitor();

    PeriodicTask::startRunningPeriodicTasks();

    // MessageServer::run will return when exit code closes its socket and we don't need the
    // operation context anymore
    startupOpCtx.reset();

    auto start = getGlobalServiceContext()->addAndStartTransportLayer(std::move(transportLayer));
    if (!start.isOK()) {
        error() << "Failed to start the listener: " << start.toString();
        return EXIT_NET_ERROR;
    }

    return waitForShutdown();
}
Exemplo n.º 3
0
PtpClock *
ptpdStartup(int argc, char **argv, Integer16 * ret, RunTimeOpts * rtOpts)
{
    PtpClock * ptpClock;
    int i = 0;

    /*
     * Set the default mode for all newly created files - previously
     * this was not the case for log files. This adds consistency
     * and allows to use FILE* vs. fds everywhere
     */
    umask(~DEFAULT_FILE_PERMS);

    /**
     * If a required setting, such as interface name, or a setting
     * requiring a range check is to be set via getopts_long,
     * the respective currentConfig dictionary entry should be set,
     * instead of just setting the rtOpts field.
     *
     * Config parameter evaluation priority order:
     * 	1. Any dictionary keys set in the getopt_long loop
     * 	2. CLI long section:key type options
     * 	3. Config file (parsed last), merged with 2. and 3 - will be overwritten by CLI options
     * 	4. Defaults and any rtOpts fields set in the getopt_long loop
    **/

    /**
     * Load defaults. Any options set here and further inside loadCommandLineOptions()
     * by setting rtOpts fields, will be considered the defaults
     * for config file and section:key long options.
     */
    loadDefaultSettings(rtOpts);
    /* initialise the config dictionary */
    rtOpts->candidateConfig = dictionary_new(0);
    rtOpts->cliConfig = dictionary_new(0);
    /* parse all long section:key options and clean up argv for getopt */
    loadCommandLineKeys(rtOpts->cliConfig,argc,argv);
    /* parse the normal short and long option, exit on error */
    if (!loadCommandLineOptions(rtOpts, rtOpts->cliConfig, argc, argv, ret)) {
        goto fail;
    }

    /* Display startup info and argv if not called with -? or -H */
    NOTIFY("%s version %s starting\n",USER_DESCRIPTION, USER_VERSION);
    dump_command_line_parameters(argc, argv);
    /*
     * we try to catch as many error conditions as possible, but before we call daemon().
     * the exception is the lock file, as we get a new pid when we call daemon(),
     * so this is checked twice: once to read, second to read/write
     */
    if(geteuid() != 0)
    {
        printf("Error: "PTPD_PROGNAME" daemon can only be run as root\n");
        *ret = 1;
        goto fail;
    }

    /* Have we got a config file? */
    if(strlen(rtOpts->configFile) > 0) {
        /* config file settings overwrite all others, except for empty strings */
        INFO("Loading configuration file: %s\n",rtOpts->configFile);
        if(loadConfigFile(&rtOpts->candidateConfig, rtOpts)) {
            dictionary_merge(rtOpts->cliConfig, rtOpts->candidateConfig, 1, "from command line");
        } else {
            *ret = 1;
            dictionary_merge(rtOpts->cliConfig, rtOpts->candidateConfig, 1, "from command line");
            goto configcheck;
        }
    } else {
        dictionary_merge(rtOpts->cliConfig, rtOpts->candidateConfig, 1, "from command line");
    }
    /**
     * This is where the final checking  of the candidate settings container happens.
     * A dictionary is returned with only the known options, explicitly set to defaults
     * if not present. NULL is returned on any config error - parameters missing, out of range,
     * etc. The getopt loop in loadCommandLineOptions() only sets keys verified here.
     */
    if( ( rtOpts->currentConfig = parseConfig(rtOpts->candidateConfig,rtOpts)) == NULL ) {
        *ret = 1;
        dictionary_del(rtOpts->candidateConfig);
        goto configcheck;
    }

    /* we've been told to print the lock file and exit cleanly */
    if(rtOpts->printLockFile) {
        printf("%s\n", rtOpts->lockFile);
        *ret = 0;
        goto fail;
    }

    /* we don't need the candidate config any more */
    dictionary_del(rtOpts->candidateConfig);

    /* Check network before going into background */
    if(!testInterface(rtOpts->ifaceName, rtOpts)) {
        ERROR("Error: Cannot use %s interface\n",rtOpts->ifaceName);
        *ret = 1;
        goto configcheck;
    }

configcheck:
    /*
     * We've been told to check config only - clean exit before checking locks
     */
    if(rtOpts->checkConfigOnly) {
        if(*ret != 0) {
            printf("Configuration has errors\n");
            *ret = 1;
        }
        else
            printf("Configuration OK\n");
        return 0;
    }

    /* Previous errors - exit */
    if(*ret !=0)
        return 0;

    /* First lock check, just to be user-friendly to the operator */
    if(!rtOpts->ignore_daemon_lock) {
        if(!writeLockFile(rtOpts)) {
            /* check and create Lock */
            ERROR("Error: file lock failed (use -L or global:ignore_lock to ignore lock file)\n");
            *ret = 3;
            return 0;
        }
        /* check for potential conflicts when automatic lock files are used */
        if(!checkOtherLocks(rtOpts)) {
            *ret = 3;
            return 0;
        }
    }

    /* Manage log files: stats, log, status and quality file */
    restartLogging(rtOpts);

    /* Allocate memory after we're done with other checks but before going into daemon */
    ptpClock = (PtpClock *) calloc(1, sizeof(PtpClock));
    if (!ptpClock) {
        PERROR("Error: Failed to allocate memory for protocol engine data");
        *ret = 2;
        return 0;
    } else {
        DBG("allocated %d bytes for protocol engine data\n",
            (int)sizeof(PtpClock));
        ptpClock->foreign = (ForeignMasterRecord *)
                            calloc(rtOpts->max_foreign_records,
                                   sizeof(ForeignMasterRecord));
        if (!ptpClock->foreign) {
            PERROR("failed to allocate memory for foreign "
                   "master data");
            *ret = 2;
            free(ptpClock);
            return 0;
        } else {
            DBG("allocated %d bytes for foreign master data\n",
                (int)(rtOpts->max_foreign_records *
                      sizeof(ForeignMasterRecord)));
        }

        ptpClock->owd_filt = FilterCreate(FILTER_EXPONENTIAL_SMOOTH, "owd");
        ptpClock->ofm_filt = FilterCreate(FILTER_MOVING_AVERAGE, "ofm");
    }

    if(rtOpts->statisticsLog.logEnabled)
        ptpClock->resetStatisticsLog = TRUE;

    /* Init to 0 net buffer */
    memset(ptpClock->msgIbuf, 0, PACKET_SIZE);
    memset(ptpClock->msgObuf, 0, PACKET_SIZE);

    /* Init user_description */
    memset(ptpClock->user_description, 0, sizeof(ptpClock->user_description));
    memcpy(ptpClock->user_description, &USER_DESCRIPTION, sizeof(USER_DESCRIPTION));

    /* Init outgoing management message */
    ptpClock->outgoingManageTmp.tlv = NULL;


    /*  DAEMON */
#ifdef PTPD_NO_DAEMON
    if(!rtOpts->nonDaemon) {
        rtOpts->nonDaemon=TRUE;
    }
#endif

    if(!rtOpts->nonDaemon) {
        /*
         * fork to daemon - nochdir non-zero to preserve the working directory:
         * allows relative paths to be used for log files, config files etc.
         * Always redirect stdout/err to /dev/null
         */
        if (daemon(1,0) == -1) {
            PERROR("Failed to start as daemon");
            *ret = 3;
            return 0;
        }
        INFO("  Info:    Now running as a daemon\n");
        /*
         * Wait for the parent process to terminate, but not forever.
         * On some systems this happened after we tried re-acquiring
         * the lock, so the lock would fail. Hence, we wait.
         */
        for (i = 0; i < 1000000; i++) {
            /* Once we've been reaped by init, parent PID will be 1 */
            if(getppid() == 1)
                break;
            usleep(1);
        }
    }

    /* Second lock check, to replace the contents with our own new PID and re-acquire the advisory lock */
    if(!rtOpts->nonDaemon && !rtOpts->ignore_daemon_lock) {
        /* check and create Lock */
        if(!writeLockFile(rtOpts)) {
            ERROR("Error: file lock failed (use -L or global:ignore_lock to ignore lock file)\n");
            *ret = 3;
            return 0;
        }
    }

#if defined(linux) && defined(HAVE_SCHED_H)
    /* Try binding to a single CPU core if configured to do so */

    if(rtOpts->cpuNumber > -1) {

        cpu_set_t mask;
        CPU_ZERO(&mask);
        CPU_SET(rtOpts->cpuNumber,&mask);
        if(sched_setaffinity(0, sizeof(mask), &mask) < 0) {
            PERROR("Could not bind to CPU core %d", rtOpts->cpuNumber);
        } else {
            INFO("Successfully bound "PTPD_PROGNAME" to CPU core %d\n", rtOpts->cpuNumber);
        }
    }
#endif /* linux && HAVE_SCHED_H */

#ifdef HAVE_SYS_CPUSET_H

    /* Try binding to a single CPU core if configured to do so */

    if(rtOpts->cpuNumber > -1) {
        cpuset_t mask;
        CPU_ZERO(&mask);
        CPU_SET(rtOpts->cpuNumber,&mask);
        if(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID,
                              -1, sizeof(mask), &mask) < 0) {
            PERROR("Could not bind to CPU core %d",
                   rtOpts->cpuNumber);
        } else {
            INFO("Successfully bound "PTPD_PROGNAME" to CPU core %d\n",
                 rtOpts->cpuNumber);
        }
    }
#endif /* HAVE_SYS_CPUSET_H */

    /* use new synchronous signal handlers */
    signal(SIGINT,  catchSignals);
    signal(SIGTERM, catchSignals);
    signal(SIGHUP,  catchSignals);

    signal(SIGUSR1, catchSignals);
    signal(SIGUSR2, catchSignals);

#if defined PTPD_SNMP
    /* Start SNMP subsystem */
    if (rtOpts->snmp_enabled)
        snmpInit(rtOpts, ptpClock);
#endif



    NOTICE(USER_DESCRIPTION" started successfully on %s using \"%s\" preset (PID %d)\n",
           rtOpts->ifaceName,
           (getPtpPreset(rtOpts->selectedPreset,rtOpts)).presetName,
           getpid());
    ptpClock->resetStatisticsLog = TRUE;

#ifdef PTPD_STATISTICS
    if (rtOpts->delayMSOutlierFilterEnabled) {
        ptpClock->delayMSRawStats = createDoubleMovingStdDev(rtOpts->delayMSOutlierFilterCapacity);
        strncpy(ptpClock->delayMSRawStats->identifier, "delayMS", 10);
        ptpClock->delayMSFiltered = createDoubleMovingMean(rtOpts->delayMSOutlierFilterCapacity);
    } else {
        ptpClock->delayMSRawStats = NULL;
        ptpClock->delayMSFiltered = NULL;
    }

    if (rtOpts->delaySMOutlierFilterEnabled) {
        ptpClock->delaySMRawStats = createDoubleMovingStdDev(rtOpts->delaySMOutlierFilterCapacity);
        strncpy(ptpClock->delaySMRawStats->identifier, "delaySM", 10);
        ptpClock->delaySMFiltered = createDoubleMovingMean(rtOpts->delaySMOutlierFilterCapacity);
    } else {
        ptpClock->delaySMRawStats = NULL;
        ptpClock->delaySMFiltered = NULL;
    }
#endif

    *ret = 0;
    return ptpClock;

fail:
    dictionary_del(rtOpts->candidateConfig);
    return 0;
}