Exemple #1
0
void
Ice::stringSeqToArgs(const StringSeq& args, int& argc, char* argv[])
{
    //
    // Shift all elements in argv which are present in args to the
    // beginning of argv.
    //
    int i = 0;
    while(i < argc)
    {
        if(find(args.begin(), args.end(), argv[i]) == args.end())
        {
            for(int j = i; j < argc - 1; j++)
            {
                argv[j] = argv[j + 1];
            }
            --argc;
        }
        else
        {
            ++i;
        }
    }

    //
    // Make sure that argv[argc] == 0, the ISO C++ standard requires this.
    //
    if(argv)
    {
        argv[argc] = 0;
    }
}
IceInternal::ProxyFactory::ProxyFactory(const InstancePtr& instance) :
    _instance(instance)
{
    StringSeq retryValues = _instance->initializationData().properties->getPropertyAsList("Ice.RetryIntervals");
    if(retryValues.size() == 0)
    {
        _retryIntervals.push_back(0);
    }
    else
    {
        for(StringSeq::const_iterator p = retryValues.begin(); p != retryValues.end(); ++p)
        {
            istringstream value(*p);

            int v;
            if(!(value >> v) || !value.eof())
            {
                v = 0;
            }

            //
            // If -1 is the first value, no retry and wait intervals.
            //
            if(v == -1 && _retryIntervals.empty())
            {
                break;
            }

            _retryIntervals.push_back(v > 0 ? v : 0);
        }
    }
}
	void ScriptSystem::getClassList(const char* prefix, bool sort, StringSeq& result) const {
		ClassInfoDict::const_iterator it = m_classInfoReg.begin();
		size_t prefixlen = 0;
		
		if (prefix) {
			prefixlen = strlen(prefix);
		}

		for (; it != m_classInfoReg.end(); ++it) {
			ClassInfo* ci = it->second;
			if (prefixlen) {
				if (strncmp(prefix, ci->m_className.c_str(), prefixlen) != 0) {
					continue;
				}

				result.push_back(ci->m_className.c_str() + prefixlen);
			} else {
				result.push_back(ci->m_className);
			}
		}

		if (sort) {
			std::sort(result.begin(), result.end(), std::less<String>());
		}
	}
Exemple #4
0
void golem::findSensor(const Sensor::Map& sensors, const StringSeq& idSeq, Sensor::Seq& sensorSeq) {
	for (StringSeq::const_iterator i = idSeq.begin(); i != idSeq.end(); ++i) {
		golem::Sensor::Map::const_iterator pSensor = std::find_if(sensors.begin(), sensors.end(), [=](const golem::Sensor::Map::value_type& val) -> bool { return val.first == *i; });
		if (pSensor == sensors.end())
			throw Message(Message::LEVEL_CRIT, "findSensor(): unknown sensor id: %s", i->c_str());
		sensorSeq.push_back(pSensor->second.get());
	}
}
void
Ice::stringSeqToArgs(const StringSeq& args, int& argc, const wchar_t* argv[])
{
    //
    // Don't need to use a wide string converter argv is expected to
    // come from Windows API.
    //
    const StringConverterPtr converter = getProcessStringConverter();

    //
    // Shift all elements in argv which are present in args to the
    // beginning of argv. We record the original value of argc so
    // that we can know later if we've shifted the array.
    //
    const int argcOrig = argc;
    int i = 0;
    while(i < argc)
    {
        if(find(args.begin(), args.end(), wstringToString(argv[i], converter)) == args.end())
        {
            for(int j = i; j < argc - 1; j++)
            {
                argv[j] = argv[j + 1];
            }
            --argc;
        }
        else
        {
            ++i;
        }
    }

    //
    // Make sure that argv[argc] == 0, the ISO C++ standard requires this.
    // We can only do this if we've shifted the array, otherwise argv[argc]
    // may point to an invalid address.
    //
    if(argv && argcOrig != argc)
    {
        argv[argc] = 0;
    }
}
IceBox::ServiceManagerI::ServiceManagerI(CommunicatorPtr communicator, int& argc, char* argv[]) :
    _communicator(communicator),
    _adminEnabled(false),
    _pendingStatusChanges(false),
    _traceServiceObserver(0)
{
#ifndef ICE_CPP11_MAPPING
    const_cast<CallbackPtr&>(_observerCompletedCB) = newCallback(this, &ServiceManagerI::observerCompleted);
#endif
    _logger = _communicator->getLogger();

    PropertiesPtr props = _communicator->getProperties();
    _traceServiceObserver = props->getPropertyAsInt("IceBox.Trace.ServiceObserver");

    if(props->getProperty("Ice.Admin.Enabled") == "")
    {
        _adminEnabled = props->getProperty("Ice.Admin.Endpoints") != "";
    }
    else
    {
        _adminEnabled = props->getPropertyAsInt("Ice.Admin.Enabled") > 0;
    }

    if(_adminEnabled)
    {
        StringSeq facetSeq = props->getPropertyAsList("Ice.Admin.Facets");
        if(!facetSeq.empty())
        {
            _adminFacetFilter.insert(facetSeq.begin(), facetSeq.end());
        }
    }

    for(int i = 1; i < argc; i++)
    {
        _argv.push_back(argv[i]);
    }
}
Exemple #7
0
void
Ice::stringSeqToArgs(const StringSeq& args, int& argc, char* argv[])
{
    //
    // Shift all elements in argv which are present in args to the
    // beginning of argv. We record the original value of argc so
    // that we can know later if we've shifted the array.
    //
    const int argcOrig = argc;
    int i = 0;
    while(i < argc)
    {
        if(find(args.begin(), args.end(), argv[i]) == args.end())
        {
            for(int j = i; j < argc - 1; j++)
            {
                argv[j] = argv[j + 1];
            }
            --argc;
        }
        else
        {
            ++i;
        }
    }

    //
    // Make sure that argv[argc] == 0, the ISO C++ standard requires this.
    // We can only do this if we've shifted the array, otherwise argv[argc]
    // may point to an invalid address.
    //
    if(argv && argcOrig != argc)
    {
        argv[argc] = 0;
    }
}
Exemple #8
0
bool
IceBox::ServiceManagerI::start()
{
    try
    {
        ServiceManagerPtr obj = this;
        PropertiesPtr properties = _communicator->getProperties();

        //
        // Create an object adapter. Services probably should NOT share
        // this object adapter, as the endpoint(s) for this object adapter
        // will most likely need to be firewalled for security reasons.
        //
        ObjectAdapterPtr adapter;
        if(properties->getProperty("IceBox.ServiceManager.Endpoints") != "")
        {
            adapter = _communicator->createObjectAdapter("IceBox.ServiceManager");

            Identity identity;
            identity.category = properties->getPropertyWithDefault("IceBox.InstanceName", "IceBox");
            identity.name = "ServiceManager";
            adapter->add(obj, identity);
        }

        //
        // Parse the property set with the prefix "IceBox.Service.". These
        // properties should have the following format:
        //
        // IceBox.Service.Foo=entry_point [args]
        //
        // We parse the service properties specified in IceBox.LoadOrder 
        // first, then the ones from remaining services.
        //
        const string prefix = "IceBox.Service.";
        PropertyDict services = properties->getPropertiesForPrefix(prefix);
        PropertyDict::iterator p;
        StringSeq loadOrder = properties->getPropertyAsList("IceBox.LoadOrder");
        vector<StartServiceInfo> servicesInfo;
        for(StringSeq::const_iterator q = loadOrder.begin(); q != loadOrder.end(); ++q)
        {
            p = services.find(prefix + *q);
            if(p == services.end())
            {
                FailureException ex(__FILE__, __LINE__);
                ex.reason = "ServiceManager: no service definition for `" + *q + "'";
                throw ex;
            }
            servicesInfo.push_back(StartServiceInfo(*q, p->second, _argv));
            services.erase(p);
        }
        for(p = services.begin(); p != services.end(); ++p)
        {
            servicesInfo.push_back(StartServiceInfo(p->first.substr(prefix.size()), p->second, _argv));
        }
        
        //
        // Check if some services are using the shared communicator in which
        // case we create the shared communicator now with a property set which
        // is the union of all the service properties (services which are using
        // the shared communicator).
        //
        PropertyDict sharedCommunicatorServices = properties->getPropertiesForPrefix("IceBox.UseSharedCommunicator.");
        if(!sharedCommunicatorServices.empty())
        {
            InitializationData initData;
            initData.properties = createServiceProperties("SharedCommunicator");
            for(vector<StartServiceInfo>::iterator q = servicesInfo.begin(); q != servicesInfo.end(); ++q)
            {
                if(properties->getPropertyAsInt("IceBox.UseSharedCommunicator." + q->name) <= 0)
                {
                    continue;
                }

                //
                // Load the service properties using the shared communicator properties as
                // the default properties.
                //
                PropertiesPtr svcProperties = createProperties(q->args, initData.properties);

                //
                // Erase properties from the shared communicator which don't exist in the
                // service properties (which include the shared communicator properties
                // overriden by the service properties).
                //
                PropertyDict allProps = initData.properties->getPropertiesForPrefix("");
                for(PropertyDict::iterator p = allProps.begin(); p != allProps.end(); ++p)
                {
                    if(svcProperties->getProperty(p->first) == "")
                    {
                        initData.properties->setProperty(p->first, "");
                    }
                }

                //
                // Add the service properties to the shared communicator properties.
                //
                PropertyDict props = svcProperties->getPropertiesForPrefix("");
                for(PropertyDict::const_iterator r = props.begin(); r != props.end(); ++r)
                {
                    initData.properties->setProperty(r->first, r->second);
                }
            
                //
                // Parse <service>.* command line options (the Ice command line options 
                // were parsed by the createProperties above)
                //
                q->args = initData.properties->parseCommandLineOptions(q->name, q->args);                
            }
            _sharedCommunicator = initialize(initData);
        }

        //
        // Start the services.
        //
        for(vector<StartServiceInfo>::const_iterator r = servicesInfo.begin(); r != servicesInfo.end(); ++r)
        {
            start(r->name, r->entryPoint, r->args);
        }

        //
        // We may want to notify external scripts that the services
        // have started. This is done by defining the property:
        //
        // IceBox.PrintServicesReady=bundleName
        //
        // Where bundleName is whatever you choose to call this set of
        // services. It will be echoed back as "bundleName ready".
        //
        // This must be done after start() has been invoked on the
        // services.
        //
        string bundleName = properties->getProperty("IceBox.PrintServicesReady");
        if(!bundleName.empty())
        {
            cout << bundleName << " ready" << endl;
        }

        //
        // Register "this" as a facet to the Admin object, and then create
        // Admin object
        //
        try
        {
            _communicator->addAdminFacet(this, "IceBox.ServiceManager");

            //
            // Add a Properties facet for each service
            // 
            for(vector<ServiceInfo>::iterator r = _services.begin(); r != _services.end(); ++r)
            {
                const ServiceInfo& info = *r;
                CommunicatorPtr communicator = info.communicator != 0 ? info.communicator : _sharedCommunicator;
                _communicator->addAdminFacet(new PropertiesAdminI(communicator->getProperties()),
                                             "IceBox.Service." + info.name + ".Properties");
            }
          
            _communicator->getAdmin();
        }
        catch(const ObjectAdapterDeactivatedException&)
        {
            //
            // Expected if the communicator has been shutdown.
            //
        }

        if(adapter)
        {
            try
            {
                adapter->activate();
            }
            catch(const ObjectAdapterDeactivatedException&)
            {
                //
                // Expected if the communicator has been shutdown.
                //
            }
        }
    }
    catch(const FailureException& ex)
    {
        Error out(_logger);
        out << ex.reason;
        stopAll();
        return false;
    }
    catch(const Exception& ex)
    {
        Error out(_logger);
        out << "ServiceManager: " << ex;
        stopAll();
        return false;
    }

    return true;
}
Exemple #9
0
int
Activator::activate(const string& name,
                    const string& exePath,
                    const string& pwdPath,
#ifndef _WIN32
                    uid_t uid,
                    gid_t gid,
#endif
                    const Ice::StringSeq& options,
                    const Ice::StringSeq& envs,
                    const ServerIPtr& server)
{
    IceUtil::Monitor< IceUtil::Mutex>::Lock sync(*this);

    if(_deactivating)
    {
        throw string("The node is being shutdown.");
    }

    string path = exePath;
    if(path.empty())
    {
        throw string("The server executable path is empty.");
    }

    string pwd = IcePatch2Internal::simplify(pwdPath);
#ifdef _WIN32
    if(!IceUtilInternal::isAbsolutePath(path))
    {
        if(path.find('/') == string::npos)
        {
            //
            // Get the absolute pathname of the executable.
            //
            wchar_t absbuf[_MAX_PATH];
            wchar_t* fPart;
            wstring ext = path.size() <= 4 || path[path.size() - 4] != '.' ? L".exe" : L"";

            //
            // IceGrid doesn't support to use string converters, so don't need to use
            // any string converter in wstringToString conversions.
            //
            if(SearchPathW(NULL, IceUtil::stringToWstring(path).c_str(), ext.c_str(), _MAX_PATH, absbuf, &fPart) == 0)
            {
                if(_traceLevels->activator > 0)
                {
                    Trace out(_traceLevels->logger, _traceLevels->activatorCat);
                    out << "couldn't find `" << path << "' executable.";
                }
                throw string("Couldn't find `" + path + "' executable.");
            }
            path = IceUtil::wstringToString(absbuf);
        }
        else if(!pwd.empty())
        {
            path = pwd + "/" + path;
        }
    }

    //
    // Get the absolute pathname of the working directory.
    //
    // IceGrid doesn't support to use string converters, so
    // don't need to use any string converter in stringToWstring
    // conversions.
    //
    if(!pwd.empty())
    {
        wchar_t absbuf[_MAX_PATH];
        if(_wfullpath(absbuf, IceUtil::stringToWstring(pwd).c_str(), _MAX_PATH) == NULL)
        {
            if(_traceLevels->activator > 0)
            {
                Trace out(_traceLevels->logger, _traceLevels->activatorCat);
                out << "cannot convert `" << pwd << "' into an absolute path";
            }
            throw string("The server working directory path `" + pwd + "' can't be converted into an absolute path.");
        }
        pwd = IceUtil::wstringToString(absbuf);
    }
#endif

    //
    // Setup arguments.
    //
    StringSeq args;
    args.push_back(path);
    args.insert(args.end(), options.begin(), options.end());

    if(_traceLevels->activator > 0)
    {
        Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat);
        out << "activating server `" << name << "'";
        if(_traceLevels->activator > 1)
        {
            out << "\n";
            out << "path = " << path << "\n";
            if(pwd.empty())
            {
                string cwd;
                if(IceUtilInternal::getcwd(cwd) == 0)
                {
                    out << "pwd = " << cwd << "\n";
                }
            }
            else
            {
                out << "pwd = " << pwd << "\n";
            }
#ifndef _WIN32
            out << "uid/gid = " << uid << "/" << gid << "\n";
#endif
            if(!envs.empty())
            {
                out << "envs = " << toString(envs, ", ") << "\n";
            }
            if(!args.empty())
            {
                out << "args = " << toString(args);
            }
        }
    }

    //
    // Activate and create.
    //
#ifdef _WIN32

    //
    // Compose command line.
    //
    string cmd;
    for(StringSeq::const_iterator p = args.begin(); p != args.end(); ++p)
    {
        if(p != args.begin())
        {
            cmd.push_back(' ');
        }
        //
        // Enclose arguments containing spaces in double quotes.
        //
        if((*p).find(' ') != string::npos)
        {
            cmd.push_back('"');
            cmd.append(*p);
            cmd.push_back('"');
        }
        else
        {
            cmd.append(*p);
        }
    }

    //
    // IceGrid doesn't support to use string converters, so don't need to use
    // any string converter in stringToWstring conversions.
    //
    wstring wpwd = IceUtil::stringToWstring(pwd);
    const wchar_t* dir = !wpwd.empty() ? wpwd.c_str() : NULL;

    //
    // Make a copy of the command line.
    //
    wchar_t* cmdbuf = _wcsdup(IceUtil::stringToWstring(cmd).c_str());

    //
    // Create the environment block for the child process. We start with the environment
    // of this process, and then merge environment variables from the server description.
    // Since Windows is case insensitive wrt environment variables we convert the keys to
    // uppercase to ensure matches are found.
    //
    const wchar_t* env = NULL;
    wstring envbuf;
    if(!envs.empty())
    {
        map<wstring, wstring, UnicodeStringLess> envMap;
        LPVOID parentEnv = GetEnvironmentStringsW();
        const wchar_t* var = reinterpret_cast<const wchar_t*>(parentEnv);
        if(*var == L'=')
        {
            //
            // The environment block may start with some information about the
            // current drive and working directory. This is indicated by a leading
            // '=' character, so we skip to the first '\0' byte.
            //
            while(*var != L'\0')
                var++;
            var++;
        }
        while(*var != L'\0')
        {
            wstring s(var);
            wstring::size_type pos = s.find(L'=');
            if(pos != wstring::npos)
            {
                envMap[s.substr(0, pos)] = s.substr(pos + 1);
            }
            var += s.size();
            var++; // Skip the '\0' byte
        }
        FreeEnvironmentStringsW(static_cast<wchar_t*>(parentEnv));
        for(StringSeq::const_iterator p = envs.begin(); p != envs.end(); ++p)
        {
            //
            // IceGrid doesn't support to use string converters, so don't need to use
            // any string converter in stringToWstring conversions.
            //
            wstring s = IceUtil::stringToWstring(*p);
            wstring::size_type pos = s.find(L'=');
            if(pos != wstring::npos)
            {
                envMap[s.substr(0, pos)] = s.substr(pos + 1);
            }
        }

        for(map<wstring, wstring, UnicodeStringLess>::const_iterator q = envMap.begin(); q != envMap.end(); ++q)
        {
            envbuf.append(q->first);
            envbuf.push_back(L'=');
            envbuf.append(q->second);
            envbuf.push_back(L'\0');
        }
        envbuf.push_back(L'\0');
        env = envbuf.c_str();
    }

    Process process;

    STARTUPINFOW si;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);

    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));
    BOOL b = CreateProcessW(
        NULL,                     // Executable
        cmdbuf,                   // Command line
        NULL,                     // Process attributes
        NULL,                     // Thread attributes
        FALSE,                    // Do NOT inherit handles
        CREATE_NEW_PROCESS_GROUP | CREATE_UNICODE_ENVIRONMENT, // Process creation flags
        (LPVOID)env,              // Process environment
        dir,                      // Current directory
        &si,                      // Startup info
        &pi                       // Process info
    );

    free(cmdbuf);

    if(!b)
    {
        throw IceUtilInternal::lastErrorToString();
    }

    //
    // Caller is responsible for closing handles in PROCESS_INFORMATION. We don't need to
    // keep the thread handle, so we close it now. The process handle will be closed later.
    //
    CloseHandle(pi.hThread);
    process.activator = this;
    process.pid = pi.dwProcessId;
    process.hnd = pi.hProcess;
    process.server = server;
    map<string, Process>::iterator it = _processes.insert(make_pair(name, process)).first;

    Process* pp = &it->second;
    if(!RegisterWaitForSingleObject(&pp->waithnd, pp->hnd, activatorWaitCallback, pp, INFINITE,
                                    WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE))
    {
        throw IceUtilInternal::lastErrorToString();
    }

    //
    // Don't print the following trace, this might interfer with the
    // output of the started process if it fails with an error message.
    //
//     if(_traceLevels->activator > 0)
//     {
//         Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat);
//         out << "activated server `" << name << "' (pid = " << pi.dwProcessId << ")";
//     }

    return static_cast<Ice::Int>(process.pid);
#else
    int fds[2];
    if(pipe(fds) != 0)
    {
        SyscallException ex(__FILE__, __LINE__);
        ex.error = getSystemErrno();
        throw ex;
    }

    int errorFds[2];
    if(pipe(errorFds) != 0)
    {
        SyscallException ex(__FILE__, __LINE__);
        ex.error = getSystemErrno();
        throw ex;
    }


    //
    // Convert to standard argc/argv.
    //
    IceUtilInternal::ArgVector av(args);
    IceUtilInternal::ArgVector env(envs);

    //
    // Current directory
    //
    const char* pwdCStr = pwd.c_str();

    pid_t pid = fork();
    if(pid == -1)
    {
        SyscallException ex(__FILE__, __LINE__);
        ex.error = getSystemErrno();
        throw ex;
    }

    if(pid == 0) // Child process.
    {
        //
        // Until exec, we can only use async-signal safe functions
        //

        //
        // Unblock signals blocked by IceUtil::CtrlCHandler.
        //
        sigset_t sigs;
        sigemptyset(&sigs);
        sigaddset(&sigs, SIGHUP);
        sigaddset(&sigs, SIGINT);
        sigaddset(&sigs, SIGTERM);
        sigprocmask(SIG_UNBLOCK, &sigs, 0);

        //
        // Change the uid/gid under which the process will run.
        //
        if(setgid(gid) == -1)
        {
            ostringstream os;
            os << gid;
            reportChildError(getSystemErrno(), errorFds[1], "cannot set process group id", os.str().c_str(),
                             _traceLevels);
        }

        errno = 0;
        struct passwd* pw = getpwuid(uid);
        if(!pw)
        {
            if(errno)
            {
                reportChildError(getSystemErrno(), errorFds[1], "cannot read the password database", "",
                                 _traceLevels);
            }
            else
            {
                ostringstream os;
                os << uid;
                reportChildError(getSystemErrno(), errorFds[1], "unknown user uid"  , os.str().c_str(),
                                 _traceLevels);
            }
        }

        //
        // Don't initialize supplementary groups if we are not running as root.
        //
        if(getuid() == 0 && initgroups(pw->pw_name, gid) == -1)
        {
            ostringstream os;
            os << pw->pw_name;
            reportChildError(getSystemErrno(), errorFds[1], "cannot initialize process supplementary group access list for user",
                             os.str().c_str(), _traceLevels);
        }

        if(setuid(uid) == -1)
        {
            ostringstream os;
            os << uid;
            reportChildError(getSystemErrno(), errorFds[1], "cannot set process user id", os.str().c_str(),
                             _traceLevels);
        }

        //
        // Assign a new process group for this process.
        //
        setpgid(0, 0);

        //
        // Close all file descriptors, except for standard input,
        // standard output, standard error, and the write side
        // of the newly created pipe.
        //
        int maxFd = static_cast<int>(sysconf(_SC_OPEN_MAX));
        for(int fd = 3; fd < maxFd; ++fd)
        {
            if(fd != fds[1] && fd != errorFds[1])
            {
                close(fd);
            }
        }

        for(int i = 0; i < env.argc; i++)
        {
            //
            // Each env is leaked on purpose ... see man putenv().
            //
            if(putenv(strdup(env.argv[i])) != 0)
            {
                reportChildError(errno, errorFds[1], "cannot set environment variable",  env.argv[i],
                                 _traceLevels);
            }
        }

        //
        // Change working directory.
        //
        if(strlen(pwdCStr) != 0)
        {
            if(chdir(pwdCStr) == -1)
            {
                reportChildError(errno, errorFds[1], "cannot change working directory to",  pwdCStr,
                                 _traceLevels);
            }
        }

        //
        // Close on exec the error message file descriptor.
        //
        int flags = fcntl(errorFds[1], F_GETFD);
        flags |= 1; // FD_CLOEXEC
        if(fcntl(errorFds[1], F_SETFD, flags) == -1)
        {
            close(errorFds[1]);
            errorFds[1] = -1;
        }

        if(execvp(av.argv[0], av.argv) == -1)
        {
            if(errorFds[1] != -1)
            {
                reportChildError(errno, errorFds[1], "cannot execute",  av.argv[0], _traceLevels);
            }
            else
            {
                reportChildError(errno, fds[1], "cannot execute",  av.argv[0], _traceLevels);
            }
        }
    }
    else // Parent process.
    {
        close(fds[1]);
        close(errorFds[1]);

        //
        // Read a potential error message over the error message pipe.
        //
        char s[16];
        ssize_t rs;
        string message;
        while((rs = read(errorFds[0], &s, 16)) > 0)
        {
            message.append(s, rs);
        }

        //
        // If an error occured before the exec() we do some cleanup and throw.
        //
        if(!message.empty())
        {
            close(fds[0]);
            close(errorFds[0]);
            waitPid(pid);
            throw message;
        }

        //
        // Otherwise, the exec() was successfull and we don't need the error message
        // pipe anymore.
        //
        close(errorFds[0]);

        Process process;
        process.pid = pid;
        process.pipeFd = fds[0];
        process.server = server;
        _processes.insert(make_pair(name, process));

        int flags = fcntl(process.pipeFd, F_GETFL);
        flags |= O_NONBLOCK;
        fcntl(process.pipeFd, F_SETFL, flags);

        setInterrupt();

    //
    // Don't print the following trace, this might interfere with the
    // output of the started process if it fails with an error message.
    //
//      if(_traceLevels->activator > 0)
//      {
//          Ice::Trace out(_traceLevels->logger, _traceLevels->activatorCat);
//          out << "activated server `" << name << "' (pid = " << pid << ")";
//      }
    }

    return pid;
#endif
}
Exemple #10
0
void
Ice::PluginManagerI::loadPlugin(const string& name, const string& pluginSpec, StringSeq& cmdArgs)
{
    assert(_communicator);

    string entryPoint;
    StringSeq args;
    if(!pluginSpec.empty())
    {
        //
        // Split the entire property value into arguments. An entry point containing spaces
        // must be enclosed in quotes.
        //
        try
        {
            args = IceUtilInternal::Options::split(pluginSpec);
        }
        catch(const IceUtilInternal::BadOptException& ex)
        {
            PluginInitializationException e(__FILE__, __LINE__);
            e.reason = "invalid arguments for plug-in `" + name + "':\n" + ex.reason;
            throw e;
        }

        assert(!args.empty());

        //
        // Shift the arguments.
        //
        entryPoint = args[0];
        args.erase(args.begin());

        //
        // Convert command-line options into properties. First we
        // convert the options from the plug-in configuration, then
        // we convert the options from the application command-line.
        //
        PropertiesPtr properties = _communicator->getProperties();
        args = properties->parseCommandLineOptions(name, args);
        cmdArgs = properties->parseCommandLineOptions(name, cmdArgs);
    }

    PluginFactory factory = 0;
    DynamicLibraryPtr library;

    //
    // Always check the static plugin factory table first, it takes
    // precedence over the the entryPoint specified in the plugin
    // property value.
    //
    if(factories)
    {
        map<string, PluginFactory>::const_iterator p = factories->find(name);
        if(p != factories->end())
        {
            factory = p->second;
        }
    }

    //
    // If we didn't find the factory, get the factory using the entry
    // point symbol.
    //
    if(!factory)
    {
        assert(!entryPoint.empty());
        library = new DynamicLibrary();
        DynamicLibrary::symbol_type sym = library->loadEntryPoint(entryPoint);
        if(sym == 0)
        {
            ostringstream out;
            string msg = library->getErrorMessage();
            out << "unable to load entry point `" << entryPoint << "'";
            if(!msg.empty())
            {
                out << ": " + msg;
            }
            PluginInitializationException ex(__FILE__, __LINE__);
            ex.reason = out.str();
            throw ex;
        }

#ifdef __IBMCPP__
    // xlC warns when casting a void* to function pointer
#   pragma report(disable, "1540-0216")
#endif

        factory = reinterpret_cast<PluginFactory>(sym);
    }

    //
    // Invoke the factory function. No exceptions can be raised
    // by the factory function because it's declared extern "C".
    //
    PluginPtr plugin(factory(_communicator, name, args));
    if(!plugin)
    {
        PluginInitializationException e(__FILE__, __LINE__);
        ostringstream out;
        out << "failure in entry point `" << entryPoint << "'";
        e.reason = out.str();
        throw e;
    }

    PluginInfo info;
    info.name = name;
    info.plugin = plugin;
    _plugins.push_back(info);

    if(library)
    {
        _libraries->add(library);
    }
}
Exemple #11
0
void
Ice::PluginManagerI::loadPlugins(int& argc, const char* argv[])
{
    assert(_communicator);

    StringSeq cmdArgs = argsToStringSeq(argc, argv);

    const string prefix = "Ice.Plugin.";
    PropertiesPtr properties = _communicator->getProperties();
    PropertyDict plugins = properties->getPropertiesForPrefix(prefix);

    //
    // First, load static plugin factories which were setup to load on
    // communicator initialization. If a matching plugin property is
    // set, we load the plugin with the plugin specification. The
    // entryPoint will be ignored but the rest of the plugin
    // specification might be used.
    //
    if(loadOnInitialization)
    {
        for(vector<string>::const_iterator p = loadOnInitialization->begin(); p != loadOnInitialization->end(); ++p)
        {
            string property = prefix + *p;
            PropertyDict::iterator r = plugins.find(property + ".cpp");
            if(r == plugins.end())
            {
                r = plugins.find(property);
            }
            else
            {
                plugins.erase(property);
            }

            if(r != plugins.end())
            {
                loadPlugin(*p, r->second, cmdArgs);
                plugins.erase(r);
            }
            else
            {
                loadPlugin(*p, "", cmdArgs);
            }
        }
    }

    //
    // Next, load and initialize the plug-ins defined in the property
    // set with the prefix "Ice.Plugin.". These properties should have
    // the following format:
    //
    // Ice.Plugin.name[.<language>]=entry_point [args]
    //
    // If the Ice.PluginLoadOrder property is defined, load the
    // specified plug-ins in the specified order, then load any
    // remaining plug-ins.
    //
    StringSeq loadOrder = properties->getPropertyAsList("Ice.PluginLoadOrder");
    for(StringSeq::const_iterator p = loadOrder.begin(); p != loadOrder.end(); ++p)
    {
        string name = *p;

        if(findPlugin(name))
        {
            PluginInitializationException ex(__FILE__, __LINE__);
            ex.reason = "plug-in `" + name + "' already loaded";
            throw ex;
        }

        string property = prefix + name;
        PropertyDict::iterator r = plugins.find(property + ".cpp");
        if(r == plugins.end())
        {
            r = plugins.find(property);
        }
        else
        {
            plugins.erase(property);
        }

        if(r != plugins.end())
        {
            loadPlugin(name, r->second, cmdArgs);
            plugins.erase(r);
        }
        else
        {
            PluginInitializationException ex(__FILE__, __LINE__);
            ex.reason = "plug-in `" + name + "' not defined";
            throw ex;
        }
    }

    //
    // Load any remaining plug-ins that weren't specified in PluginLoadOrder.
    //

    while(!plugins.empty())
    {
        PropertyDict::iterator p = plugins.begin();

        string name = p->first.substr(prefix.size());

        size_t dotPos = name.find_last_of('.');
        if(dotPos != string::npos)
        {
            string suffix = name.substr(dotPos + 1);
            if(suffix == "java" || suffix == "clr")
            {
                //
                // Ignored
                //
                plugins.erase(p);
            }
            else if(suffix == "cpp")
            {
                name = name.substr(0, dotPos);
                loadPlugin(name, p->second, cmdArgs);
                plugins.erase(p);

                plugins.erase(prefix + name);
            }
            else
            {
                //
                // Name is just a regular name that happens to contain a dot
                //
                dotPos = string::npos;
            }
        }

        if(dotPos == string::npos)
        {
            //
            // Is there a .cpp entry?
            //
            PropertyDict::iterator q = plugins.find(prefix + name + ".cpp");
            if(q != plugins.end())
            {
                plugins.erase(p);
                p = q;
            }

            loadPlugin(name, p->second, cmdArgs);
            plugins.erase(p);
        }
    }

    stringSeqToArgs(cmdArgs, argc, argv);
}
Exemple #12
0
Freeze::MapDb::MapDb(const ConnectionIPtr& connection, 
                     const string& dbName,
                     const string& key,
                     const string& value,
                     const KeyCompareBasePtr& keyCompare,
                     const vector<MapIndexBasePtr>& indices,
                     bool createDb) :
    Db(connection->dbEnv()->getEnv(), 0),
    _communicator(connection->communicator()),
    _dbName(dbName),
    _trace(connection->trace()),
    _keyCompare(keyCompare)
{
    if(_trace >= 1)
    {
        Trace out(_communicator->getLogger(), "Freeze.Map");
        out << "opening Db \"" << _dbName << "\"";
    }

    Catalog catalog(connection, _catalogName);
   
    TransactionPtr tx = connection->currentTransaction();
    bool ownTx = (tx == 0);

    for(;;)
    {
        try
        {
            if(ownTx)
            {
                tx = 0;
                tx = connection->beginTransaction();
            }

            Catalog::iterator ci = catalog.find(_dbName);
        
            if(ci != catalog.end())
            {
                if(ci->second.evictor)
                {
                    throw DatabaseException(__FILE__, __LINE__, _dbName + " is an evictor database");
                }
                
                _key = ci->second.key;
                _value = ci->second.value;
                checkTypes(key, value);
            }
            else
            {
                _key = key;
                _value = value;
            }
    
            set_app_private(this);
            if(_keyCompare->compareEnabled())
            {
                set_bt_compare(&customCompare);
            }
            
            PropertiesPtr properties = _communicator->getProperties();
            string propPrefix = "Freeze.Map." + _dbName + ".";
            
            int btreeMinKey = properties->getPropertyAsInt(propPrefix + "BtreeMinKey");
            if(btreeMinKey > 2)
            {
                if(_trace >= 1)
                {
                    Trace out(_communicator->getLogger(), "Freeze.Map");
                    out << "Setting \"" << _dbName << "\"'s btree minkey to " << btreeMinKey;
                }
                set_bt_minkey(btreeMinKey);
            }
            
            bool checksum = properties->getPropertyAsInt(propPrefix + "Checksum") > 0;
            if(checksum)
            {
                if(_trace >= 1)
                {
                    Trace out(_communicator->getLogger(), "Freeze.Map");
                    out << "Turning checksum on for \"" << _dbName << "\"";
                }
                
                set_flags(DB_CHKSUM);
            }
            
            int pageSize = properties->getPropertyAsInt(propPrefix + "PageSize");
            if(pageSize > 0)
            {
                if(_trace >= 1)
                {
                    Trace out(_communicator->getLogger(), "Freeze.Map");
                    out << "Setting \"" << _dbName << "\"'s pagesize to " << pageSize;
                }
                set_pagesize(pageSize);
            }
            

            DbTxn* txn = getTxn(tx);
            
            u_int32_t flags = DB_THREAD;
            if(createDb)
            {
                flags |= DB_CREATE;
            }

            open(txn, Ice::nativeToUTF8(_communicator, _dbName).c_str(), 0, DB_BTREE, flags, FREEZE_DB_MODE);
            
            
            StringSeq oldIndices;
            StringSeq newIndices;
            size_t oldSize = 0;
            CatalogIndexList catalogIndexList(connection, _catalogIndexListName);
            
            if(createDb)
            {
                CatalogIndexList::iterator cil = catalogIndexList.find(_dbName);
                if(cil != catalogIndexList.end())
                {
                    oldIndices = cil->second;
                    oldSize = oldIndices.size();
                }
            } 
            
            for(vector<MapIndexBasePtr>::const_iterator p = indices.begin();
                p != indices.end(); ++p)
            {
                const MapIndexBasePtr& indexBase = *p; 
                assert(indexBase->_impl == 0);
                assert(indexBase->_communicator == 0);
                indexBase->_communicator = connection->communicator();
                
                auto_ptr<MapIndexI> indexI;

                try
                {
                    indexI.reset(new MapIndexI(connection, *this, txn, createDb, indexBase));
                }
                catch(const DbDeadlockException&)
                {
                    throw;
                }
                catch(const DbException& dx)
                {
                    string message = "Error while opening index \"" + _dbName +
                        "." + indexBase->name() + "\": " + dx.what();

                    throw DatabaseException(__FILE__, __LINE__, message);
                }
                
#ifndef NDEBUG
                bool inserted = 
#endif
                    _indices.insert(IndexMap::value_type(indexBase->name(), indexI.get())).second;
                assert(inserted);
                
                indexBase->_impl = indexI.release();
                
                if(createDb)
                {
                    newIndices.push_back(indexBase->name());
                    oldIndices.erase(std::remove(oldIndices.begin(), oldIndices.end(), indexBase->name()), oldIndices.end());
                }
            }
            
            if(ci == catalog.end())
            {
                CatalogData catalogData;
                catalogData.evictor = false;
                catalogData.key = key;
                catalogData.value = value;
                catalog.put(Catalog::value_type(_dbName, catalogData));
            }
            
            if(createDb)
            {
                //
                // Remove old indices and write the new ones
                //
                bool indexRemoved = false;

                for(StringSeq::const_iterator q = oldIndices.begin(); q != oldIndices.end(); ++q)
                {
                    const string& index = *q;
                    
                    if(_trace >= 1)
                    {
                        Trace out(_communicator->getLogger(), "Freeze.Map");
                        out << "removing old index \"" << index << "\" on Db \"" << _dbName << "\"";
                    }
                    
                    try
                    {
                        connection->removeMapIndex(_dbName, *q);
                        indexRemoved = true;
                    }
                    catch(const IndexNotFoundException&)
                    {
                        // Ignored
                        
                        if(_trace >= 1)
                        {
                            Trace out(_communicator->getLogger(), "Freeze.Map");
                            out << "index \"" << index << "\" on Db \"" << _dbName << "\" does not exist";
                        }
                    }
                }
                
                if(indexRemoved || oldSize != newIndices.size())
                {
                    if(newIndices.size() == 0)
                    {
                        catalogIndexList.erase(_dbName);
                        if(_trace >= 1)
                        {
                            Trace out(_communicator->getLogger(), "Freeze.Map");
                            out << "Removed catalogIndexList entry for Db \"" << _dbName << "\"";
                        }
                        
                    }
                    else
                    {
                        catalogIndexList.put(CatalogIndexList::value_type(_dbName, newIndices));
                        if(_trace >= 1)
                        {
                            Trace out(_communicator->getLogger(), "Freeze.Map");
                            out << "Updated catalogIndexList entry for Db \"" << _dbName << "\"";
                        }
                    }
                }
            }

            if(ownTx)
            {
                tx->commit();
            }
            break; // for(;;)
        }
        catch(const DbDeadlockException& dx)
        {
            if(ownTx)
            {
                if(connection->deadlockWarning())
                {
                    Warning out(connection->communicator()->getLogger());
                    out << "Deadlock in Freeze::MapDb::MapDb on Map \"" 
                        << _dbName << "\"; retrying ...";
                }

                //
                // Ignored, try again
                //
            }
            else
            {
                throw DeadlockException(__FILE__, __LINE__, dx.what(), tx);
            }
        }
        catch(const DbException& dx)
        {
            if(ownTx)
            {
                try
                {
                    tx->rollback();
                }
                catch(...)
                {
                }
            }
                
            string message = "Error while opening Db \"" + _dbName +
                "\": " + dx.what();

            throw DatabaseException(__FILE__, __LINE__, message);
        }
        catch(...)
        {
            if(ownTx && tx != 0)
            {   
                try
                {
                    tx->rollback();
                }
                catch(...)
                {
                }
            }
            throw;
        }
    }
}
Exemple #13
0
int
main(int argc, char* argv[])

#endif
{
    Ice::StringSeq originalArgs = Ice::argsToStringSeq(argc, argv);
    assert(originalArgs.size() > 0);
    const string appName = originalArgs[0];
    string dataDir;
    StringSeq fileSeq;
    int compress = 1;
    bool verbose;
    bool caseInsensitive;

    IceUtilInternal::Options opts;
    opts.addOpt("h", "help");
    opts.addOpt("v", "version");
    opts.addOpt("z", "compress");
    opts.addOpt("Z", "no-compress");
    opts.addOpt("V", "verbose");
    opts.addOpt("i", "case-insensitive");
    
    vector<string> args;
    try
    {
        args = opts.parse(originalArgs);
    }
    catch(const IceUtilInternal::BadOptException& e)
    {
        cerr << e.reason << endl;
        usage(appName);
        return EXIT_FAILURE;
    }

    if(opts.isSet("help"))
    {
        usage(appName);
        return EXIT_SUCCESS;
    }
    if(opts.isSet("version"))
    {
        cout << ICE_STRING_VERSION << endl;
        return EXIT_SUCCESS;
    }
    bool doCompress = opts.isSet("compress");
    bool dontCompress = opts.isSet("no-compress");
    if(doCompress && dontCompress)
    {
        cerr << appName << ": only one of -z and -Z are mutually exclusive" << endl;
        usage(appName);
        return EXIT_FAILURE;
    }
    if(doCompress)
    {
        compress = 2;
    }
    else if(dontCompress)
    {
        compress = 0;
    }
    verbose = opts.isSet("verbose");
    caseInsensitive = opts.isSet("case-insensitive");

    if(args.empty())
    {
        cerr << appName << ": no data directory specified" << endl;
        usage(appName);
        return EXIT_FAILURE;
    }
    dataDir = simplify(args[0]);

    for(vector<string>::size_type i = 1; i < args.size(); ++i)
    {
        fileSeq.push_back(simplify(args[i]));
    }

    try
    {
        string absDataDir = dataDir;
    
        string cwd;
        if(IceUtilInternal::getcwd(cwd) != 0)
        {
            throw "cannot get the current directory:\n" + IceUtilInternal::lastErrorToString();
        }

        if(!IceUtilInternal::isAbsolutePath(absDataDir))
        {
            absDataDir = simplify(cwd + '/' + absDataDir);
        }
        
        for(StringSeq::iterator p = fileSeq.begin(); p != fileSeq.end(); ++p)
        {
            if(!IceUtilInternal::isAbsolutePath(*p))
            {
                *p = cwd + '/' + *p;
            }
        }

        //
        // We must call simplify() here: under Cygwin, any path starting with
        // a double slash simply doesn't work. But, if dataDir is "/", we end
        // up with paths that start with "//" unless we call simplify().
        //
        string absDataDirWithSlash = simplify(absDataDir + '/');

        for(StringSeq::iterator p = fileSeq.begin(); p != fileSeq.end(); ++p)
        {
            if(p->compare(0, absDataDirWithSlash.size(), absDataDirWithSlash) != 0)
            {
                throw "`" + *p + "' is not a path in `" + dataDir + "'";
            }
            
            p->erase(0, absDataDirWithSlash.size());
        }
    
        LargeFileInfoSeq infoSeq;
            
        if(fileSeq.empty())
        {
            CalcCB calcCB;
            if(!getFileInfoSeq(absDataDir, compress, verbose ? &calcCB : 0, infoSeq))
            {
                return EXIT_FAILURE;
            }
        }
        else
        {
            loadFileInfoSeq(absDataDir, infoSeq);

            for(StringSeq::iterator p = fileSeq.begin(); p != fileSeq.end(); ++p)
            {
                LargeFileInfoSeq partialInfoSeq;

                CalcCB calcCB;
                if(!getFileInfoSeqSubDir(absDataDir, *p, compress, verbose ? &calcCB : 0, partialInfoSeq))
                {
                    return EXIT_FAILURE;
                }

                LargeFileInfoSeq newInfoSeq;
                newInfoSeq.reserve(infoSeq.size());

                set_difference(infoSeq.begin(),
                               infoSeq.end(),
                               partialInfoSeq.begin(),
                               partialInfoSeq.end(),
                               back_inserter(newInfoSeq),
                               FileInfoPathLess());

                infoSeq.swap(newInfoSeq);

                newInfoSeq.clear();
                newInfoSeq.reserve(infoSeq.size() + partialInfoSeq.size());

                set_union(infoSeq.begin(),
                          infoSeq.end(),
                          partialInfoSeq.begin(),
                          partialInfoSeq.end(),
                          back_inserter(newInfoSeq),
                          FileInfoPathLess());

                infoSeq.swap(newInfoSeq);
            }
        }

        if(caseInsensitive)
        {
            LargeFileInfoSeq newInfoSeq = infoSeq;
            sort(newInfoSeq.begin(), newInfoSeq.end(), IFileInfoPathLess());

            string ex;
            LargeFileInfoSeq::iterator p = newInfoSeq.begin();
            while((p = adjacent_find(p, newInfoSeq.end(), IFileInfoPathEqual())) != newInfoSeq.end())
            {
                do
                {
                    ex += '\n' + dataDir + '/' + p->path;
                    ++p;
                }
                while(p < newInfoSeq.end() && IFileInfoPathEqual()(*(p - 1), *p));
            }

            if(!ex.empty())
            {
                ex = "duplicate files:" + ex;
                throw ex;
            }
        }

        saveFileInfoSeq(absDataDir, infoSeq);
    }
    catch(const string& ex)
    {
        cerr << appName << ": " << ex << endl;
        return EXIT_FAILURE;
    }
    catch(const char* ex)
    {
        cerr << appName << ": " << ex << endl;
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}