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); } } }
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; }
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; }
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; }
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"); }