Пример #1
0
inline
void CRPCClient<TRequest, TReply>::Ask(const TRequest& request, TReply& reply)
{
    CMutexGuard LOCK(m_Mutex);
    
    unsigned int tries = 0;
    for (;;) {
        try {
            SetAffinity(GetAffinity(request));
            Connect(); // No-op if already connected
            *m_Out << request;
            *m_In >> reply;
            break;
        } catch (CException& e) {
            // Some exceptions tend to correspond to transient glitches;
            // the remainder, however, may as well get propagated immediately.
            if ( !dynamic_cast<CSerialException*>(&e)
                 &&  !dynamic_cast<CIOException*>(&e) ) {
                throw;
            } else if (++tries == m_RetryLimit  ||  !x_ShouldRetry(tries)) {
                throw;
            } else if ( !(tries & 1) ) {
                // reset on every other attempt in case we're out of sync
                try {
                    Reset();
                } STD_CATCH_ALL_XX(Serial_RPCClient,1,"CRPCClient<>::Reset()");
            }
            SleepSec(m_RetryDelay.GetCompleteSeconds());
            SleepMicroSec(m_RetryDelay.GetNanoSecondsAfterSecond() / 1000);
        }
    }
}
Пример #2
0
static int Test_MultiProcess_Child(int test, string lockname)
{
    LOG_CHILD("started");
    CInterProcessLock lock(lockname);
    
    switch (test) {
    
    case 1:
        // The lock already set in the parent process
        LOG_CHILD("try lock");
        assert( !lock.TryLock() );
        // Error acquire lock
        return IPCL_SUCCESS;
        
    case 2:
        // The lock already set in the parent process
        LOG_CHILD("try lock");
        assert( !lock.TryLock() );
        // It should be released soon, wait
        LOG_CHILD("lock in 3 sec");
        lock.Lock(CTimeout(3,0));
        LOG_CHILD("locked");
        // Parent process should try to set lock in the next 3 seconds
        // (without success)
        SleepSec(3);
        // The lock should be removed automatically on normal termination
        return IPCL_SUCCESS;
        
    case 3:
        LOG_CHILD("lock");
        lock.Lock();
        LOG_CHILD("locked");
        SleepSec(3);
        return IPCL_SUCCESS;
        
    case 4:
        LOG_CHILD("lock");
        lock.Lock(/*infinite*/);
        LOG_CHILD("locked");
        SleepSec(20);
        // Child process should be killed on this moment and lock released
        return 1;
    }
    // Unsuccessful exit code 
    return 1;
}
Пример #3
0
int CTestMultipartCgiApplication::ProcessRequest(CCgiContext& ctx)
{
    const CArgs& args = GetArgs();
    CCgiResponse& response = ctx.GetResponse();
    string mode = args["mode"].AsString();

    if (mode == "mixed") {
        response.SetMultipartMode(CCgiResponse::eMultipart_mixed);
    } else if (mode == "related") {
        response.SetMultipartMode(CCgiResponse::eMultipart_related);
    } else if (mode == "replace") {
        response.SetMultipartMode(CCgiResponse::eMultipart_replace);
    }

    response.WriteHeader();

    response.out() << "main document" << endl;

    if (mode == "mixed") {
        response.BeginPart("attachment.foo", "application/x-foo-bar");
        response.out() << "attachment" << endl;
    } else if (mode == "related") {
        response.BeginPart("more-content.foo", "application/x-foo-bar");
        response.out() << "more content" << endl;
    } else if (mode == "replace") {
        response.EndPart();
        SleepSec(1);
        response.BeginPart(kEmptyStr, "text/html");
        response.out() << "updated document" << endl;
    }
    if (mode != "none") {
        response.EndLastPart();
    }

    return 0;
}
Пример #4
0
    int Do(CWorkerNodeJobContext& context)
    {
        context.GetCleanupEventSource()->AddListener(
            new CSampleJobCleanupListener("Job-do"));

        LOG_POST( context.GetJobKey() + " " + context.GetJobInput());
        LOG_POST( "This parameter is read from a config file: " << m_Param);

        // 1. Get an input data from the client
        //    (You can use ASN.1 de-serialization here)
        //
        CNcbiIstream& is = context.GetIStream();
        CNcbiOstream& os = context.GetOStream();
        
        string output_type;
        is >> output_type; // could be "doubles" or "html"
        LOG_POST( "Output type: " << output_type);
        int count;
        is >> count;
        vector<double> dvec;
        dvec.reserve(count);
        LOG_POST( "Getting " << count << " doubles from stream...");
        for (int i = 0; i < count; ++i) {
            if (!is.good()) {
                ERR_POST( "Input stream error. Index : " << i );

                // If anything bad happened, throw an exception
                // and its message will be delivered to the client.
                throw runtime_error("Worker node input stream error"); 
            }
            // Don't forget to check if shutdown has been requested
            if (count % 1000 == 0)
                switch (context.GetShutdownLevel()) {
                case CNetScheduleAdmin::eShutdownImmediate:
                case CNetScheduleAdmin::eDie:
                    // Either this job is not needed anymore (canceled,
                    // expired or already executed elsewhere), or the
                    // server is going down and the job's execution
                    // should be gracefully (yet urgently) aborted and
                    // the job returned back to the network queue
                    // for execution by other worker node instances.
                    context.ReturnJob();
                    return 1;
                default:
                    break;
                }
            double d;
            is >> d;
            dvec.push_back(d);
        }
       
        // 2. Doing some time consuming job here
        // Well behaved algorithm checks from time to time if 
        // immediate shutdown has been requested and gracefully return 
        // without calling context.CommitJob()
        //
        for (int i = 0; i < m_Iters; ++i) {
            switch (context.GetShutdownLevel()) {
            case CNetScheduleAdmin::eShutdownImmediate:
            case CNetScheduleAdmin::eDie:
                // Either this job is not needed anymore (canceled,
                // expired or already executed elsewhere), or the
                // server is going down and the job's execution
                // should be gracefully (yet urgently) aborted and
                // the job returned back to the network queue
                // for execution by other worker node instances.
                context.ReturnJob();
                return 1;
            default:
                break;
            }
            context.PutProgressMessage("Iteration " + NStr::IntToString(i+1) +
                                       " from " + NStr::IntToString(m_Iters));
            SleepSec(m_SleepSec);            
        }
        sort(dvec.begin(), dvec.end());


        // 3. Return the result to the client 
        //    (You can use ASN.1 serialization here)
        //
        //        CNcbiOstream& os = context.GetOStream();
        if (output_type == "html") 
            os << "<html><head><title>"
                  "Sample Grid Worker Result Page"
                  "</title></head><body>"
                  "<p>Sample Grid Worker Result</p>";
            
        else
            os << dvec.size() << ' ';

        for (int i = 0; i < count; ++i) {
            if (!os.good()) {
                ERR_POST( "Output stream error. Index : " << i );
                throw runtime_error("Worker node output stream error"); 
            }
            os << dvec[i] << ' ';
        }
        if (output_type == "html") 
            os << "</body></html>";

        // 4. Indicate that the job is done and the result 
        // can be delivered to the client.
        //
        context.CommitJob();

        LOG_POST( "Job " << context.GetJobKey() << " is done.");
        return 0;
    }
Пример #5
0
static void Test_MultiProcess()
{
    LOG_POST("\n=== Multi-process tests ===");

    const CTimeout zero_timeout = CTimeout(0,0);

    // Fixed names are usually more appropriate, but here we don't
    // want independent tests to step on each other....
    string lockname = CFile::GetTmpName();
    CInterProcessLock lock(lockname);
    LOG_POST("lock name = " << lock.GetName());
    LOG_POST("lock system name = " << lock.GetSystemName());
    
    string app = CNcbiApplication::Instance()->GetArguments().GetProgramName();
    TProcessHandle handle;
    TExitCode exitcode;

    LOG_POST("\n--- Test 1");
    // Set lock and start child process, that try to set lock also (unsuccessfully).
    {{
        LOG_PARENT("lock");
        lock.Lock(/*infinite*/);
        LOG_PARENT("locked");
        LOG_PARENT("start child");
        exitcode = CExec::SpawnL(CExec::eWait, app.c_str(),
                                 "-test", "1",
                                 "-lock", lockname.c_str(), NULL).GetExitCode(); 
        LOG_PARENT("child exitcode = " << exitcode);
        assert( exitcode == IPCL_SUCCESS );
    }}

    LOG_POST("\n--- Test 2");
    // Set lock and start child process, that try to set lock also (successfully after child termination).
    {{
        // lock.Lock(); -- still locked
        LOG_PARENT("start child");
        handle = CExec::SpawnL(CExec::eNoWait, app.c_str(),
                               "-test", "2",
                               "-lock", lockname.c_str(), NULL).GetProcessHandle(); 
        CProcess process(handle, CProcess::eHandle);
        // Wait until child starts
        SleepSec(1);
        LOG_PARENT("unlock");
        lock.Unlock();
        LOG_PARENT("unlocked");
        SleepSec(2);
        // Child should set lock on this moment
        LOG_PARENT("try lock");
        assert( !lock.TryLock() );
        LOG_PARENT("unable to lock");
        exitcode = process.Wait();
        LOG_PARENT("child exitcode = " << exitcode);
        assert( exitcode == IPCL_SUCCESS );
        // Lock should be already removed
        LOG_PARENT("lock");
        lock.Lock(zero_timeout);
        LOG_PARENT("locked");
        LOG_PARENT("unlock");
        lock.Remove();
        LOG_PARENT("removed");
    }}

    LOG_POST("\n--- Test 3");
    // Child set lock and current process try to lock it also.
    {{
        LOG_PARENT("start child");
        handle = CExec::SpawnL(CExec::eNoWait, app.c_str(),
                               "-test", "3",
                               "-lock", lockname.c_str(), NULL).GetProcessHandle(); 
        CProcess process(handle, CProcess::eHandle);
        // Wait until child starts
        SleepSec(1);
        LOG_PARENT("try lock");
        assert( !lock.TryLock() );
        LOG_PARENT("unable to lock");
        LOG_PARENT("lock in 3 sec");
        lock.Lock(CTimeout(3,0));
        LOG_PARENT("locked");
        LOG_PARENT("unlock");
        lock.Unlock();
        LOG_PARENT("unlocked");
        exitcode = process.Wait();
        LOG_PARENT("child exitcode = " << exitcode);
        assert( exitcode == IPCL_SUCCESS );
    }}
    
    LOG_POST("\n--- Test 4");
    // Child set lock, we kill child process and set our own lock.
    {{
        LOG_PARENT("start child");
        handle = CExec::SpawnL(CExec::eNoWait, app.c_str(),
                               "-test", "3",
                               "-lock", lockname.c_str(), NULL).GetProcessHandle(); 
        CProcess process(handle, CProcess::eHandle);
        // Wait until child starts
        SleepSec(1);
        // Lock should be set by child
        LOG_PARENT("try lock");
        assert( !lock.TryLock() );
        LOG_PARENT("unable to lock");
        LOG_PARENT("kill");
        assert(process.Kill());
        // Lock should be automaticaly released
        SleepSec(1);
        LOG_PARENT("lock");
        lock.Lock();
        LOG_PARENT("locked");
    }}
    
    // We don't need lock object anymore, remove it from the system
    lock.Remove();
    LOG_PARENT("removed");
}