remote_blast.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:23k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: remote_blast.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 18:06:16  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: remote_blast.cpp,v 1000.1 2004/06/01 18:06:16 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author:  Kevin Bealer
  35. *
  36. * ===========================================================================
  37. */
  38. /// @file remote_blast.cpp
  39. /// Queueing and Polling code for Remote Blast API.
  40. #include <ncbi_pch.hpp>
  41. #include <corelib/ncbi_system.hpp>
  42. #include <algo/blast/api/remote_blast.hpp>
  43. #include <objects/blast/blastclient.hpp>
  44. #include <objects/blast/blast__.hpp>
  45. #include <objects/scoremat/scoremat__.hpp>
  46. #if defined(NCBI_OS_UNIX)
  47. #include <unistd.h>
  48. #endif
  49. /** @addtogroup AlgoBlast
  50.  *
  51.  * @{
  52.  */
  53. BEGIN_NCBI_SCOPE
  54. USING_SCOPE(objects);
  55. BEGIN_SCOPE(blast)
  56. // Static functions
  57. template <class T>
  58. void
  59. s_Output(CNcbiOstream & os, CRef<T> t)
  60. {
  61.     auto_ptr<CObjectOStream> x(CObjectOStream::Open(eSerial_AsnText, os));
  62.     *x << *t;
  63.     os.flush();
  64. }
  65. typedef list< CRef<CBlast4_error> > TErrorList;
  66. static bool
  67. s_SearchPending(CRef<CBlast4_reply> reply)
  68. {
  69.     const list< CRef<CBlast4_error> > & errors = reply->GetErrors();
  70.     
  71.     TErrorList::const_iterator i;
  72.     
  73.     for(i = errors.begin(); i != errors.end(); i++) {
  74.         if ((*i)->GetCode() == eBlast4_error_code_search_pending) {
  75.             return true;
  76.         }
  77.     }
  78.     return false;
  79. }
  80. void CRemoteBlast::x_SearchErrors(CRef<CBlast4_reply> reply)
  81. {
  82.     const list< CRef<CBlast4_error> > & errors = reply->GetErrors();
  83.     
  84.     TErrorList::const_iterator i;
  85.     
  86.     for(i = errors.begin(); i != errors.end(); i++) {
  87.         string msg;
  88.         
  89.         if ((*i)->CanGetMessage() && (! (*i)->GetMessage().empty())) {
  90.             msg = ": ";
  91.             msg += (*i)->GetMessage();
  92.         }
  93.         
  94.         switch((*i)->GetCode()) {
  95.         case eBlast4_error_code_conversion_warning:
  96.             m_Warn.push_back(string("Warning: conversion_warning") + msg);
  97.             break;
  98.             
  99.         case eBlast4_error_code_internal_error:
  100.             m_Errs.push_back(string("Error: internal_error") + msg);
  101.             break;
  102.             
  103.         case eBlast4_error_code_not_implemented:
  104.             m_Errs.push_back(string("Error: not_implemented") + msg);
  105.             break;
  106.             
  107.         case eBlast4_error_code_not_allowed:
  108.             m_Errs.push_back(string("Error: not_allowed") + msg);
  109.             break;
  110.             
  111.         case eBlast4_error_code_bad_request:
  112.             m_Errs.push_back(string("Error: bad_request") + msg);
  113.             break;
  114.             
  115.         case eBlast4_error_code_bad_request_id:
  116.             m_Errs.push_back(string("Error: bad_request_id") + msg);
  117.             break;
  118.         }
  119.     }
  120. }
  121. // CBlast4Option methods
  122. void CRemoteBlast::x_CheckConfig(void)
  123. {
  124.     // If not configured, throw an exception - the associated string
  125.     // will contain a list of the missing pieces.
  126.     
  127.     if (0 != m_NeedConfig) {
  128.         string cfg("Configuration required:");
  129.         
  130.         if (eProgram & m_NeedConfig) {
  131.             cfg += " <program>";
  132.         }
  133.         
  134.         if (eService & m_NeedConfig) {
  135.             cfg += " <service>";
  136.         }
  137.         
  138.         if (eQueries & m_NeedConfig) {
  139.             cfg += " <queries>";
  140.         }
  141.         
  142.         if (eSubject & m_NeedConfig) {
  143.             cfg += " <subject>";
  144.         }
  145.         
  146.         NCBI_THROW(CBlastException, eInternal, cfg.c_str());
  147.     }
  148. }
  149. CRef<CBlast4_reply>
  150. CRemoteBlast::x_SendRequest(CRef<CBlast4_request_body> body)
  151. {
  152.     // If not configured, throw.
  153.     x_CheckConfig();
  154.     
  155.     // Create the request; optionally echo it
  156.     
  157.     CRef<CBlast4_request> request(new CBlast4_request);
  158.     request->SetBody(*body);
  159.     
  160.     if (eDebug == m_Verbose) {
  161.         s_Output(NcbiCout, request);
  162.     }
  163.     
  164.     // submit to server, get reply; optionally echo it
  165.     
  166.     CRef<CBlast4_reply> reply(new CBlast4_reply);
  167.     
  168.     try {
  169.         //throw some_kind_of_nothing();
  170.         CBlast4Client().Ask(*request, *reply);
  171.     }
  172.     catch(const CEofException&) {
  173.         ERR_POST(Error << "No response from server, cannot "
  174.                  "complete request.");
  175.         
  176. #if defined(NCBI_OS_UNIX)
  177.         // Use _exit() to avoid coredump.
  178.         _exit(-1);
  179. #else
  180.         exit(-1);
  181. #endif
  182.     }
  183.     
  184.     if (eDebug == m_Verbose) {
  185.         s_Output(NcbiCout, reply);
  186.     }
  187.     
  188.     return reply;
  189. }
  190. CRef<CBlast4_reply>
  191. CRemoteBlast::x_GetSearchResults(void)
  192. {
  193.     CRef<CBlast4_get_search_results_request>
  194.         gsrr(new CBlast4_get_search_results_request);
  195.     
  196.     gsrr->SetRequest_id(m_RID);
  197.     
  198.     CRef<CBlast4_request_body> body(new CBlast4_request_body);
  199.     body->SetGet_search_results(*gsrr);
  200.     
  201.     return x_SendRequest(body);
  202. }
  203. // Pre:  start, wait, or done
  204. // Post: failed or done
  205. // Returns: true if done
  206. bool CRemoteBlast::SubmitSync(int seconds)
  207. {
  208.     // eFailed: no work to do, already an error.
  209.     // eDone:   already done, just return.
  210.     
  211.     EImmediacy immed = ePollAsync;
  212.     
  213.     switch(x_GetState()) {
  214.     case eStart:
  215.         x_SubmitSearch();
  216.         if (! m_Errs.empty()) {
  217.             break;
  218.         }
  219.         immed = ePollImmed;
  220.         // fall through
  221.         
  222.     case eWait:
  223.         x_PollUntilDone(immed, seconds);
  224.         break;
  225.     }
  226.     
  227.     return (x_GetState() == eDone);
  228. }
  229. // Pre:  start
  230. // Post: failed, wait or done
  231. // Returns: true if no error so far
  232. bool CRemoteBlast::Submit(void)
  233. {
  234.     switch(x_GetState()) {
  235.     case eStart:
  236.         x_SubmitSearch();
  237.     }
  238.     
  239.     return m_Errs.empty();
  240. }
  241. // Pre:  start, wait or done
  242. // Post: wait or done
  243. // Returns: true if done
  244. bool CRemoteBlast::CheckDone(void)
  245. {
  246.     switch(x_GetState()) {
  247.     case eFailed:
  248.     case eDone:
  249.         break;
  250.         
  251.     case eStart:
  252.         Submit();
  253.         break;
  254.         
  255.     case eWait:
  256.         x_CheckResults();
  257.     }
  258.     
  259.     return (x_GetState() == eDone);
  260. }
  261. CRemoteBlast::TGSRR * CRemoteBlast::x_GetGSRR(void)
  262. {
  263.     TGSRR* rv = NULL;
  264.     
  265.     if (SubmitSync() &&
  266.         m_Reply.NotEmpty() &&
  267.         m_Reply->CanGetBody() &&
  268.         m_Reply->GetBody().IsGet_search_results()) {
  269.         
  270.         rv = & (m_Reply->SetBody().SetGet_search_results());
  271.     }
  272.     
  273.     return rv;
  274. }
  275. CRef<objects::CSeq_align_set> CRemoteBlast::GetAlignments(void)
  276. {
  277.     CRef<objects::CSeq_align_set> rv;
  278.     
  279.     TGSRR * gsrr = x_GetGSRR();
  280.     
  281.     if (gsrr && gsrr->CanGetAlignments()) {
  282.         rv = & (gsrr->SetAlignments());
  283.     }
  284.     
  285.     return rv;
  286. }
  287. CRef<objects::CBlast4_phi_alignments> CRemoteBlast::GetPhiAlignments(void)
  288. {
  289.     CRef<objects::CBlast4_phi_alignments> rv;
  290.     
  291.     TGSRR * gsrr = x_GetGSRR();
  292.     
  293.     if (gsrr && gsrr->CanGetPhi_alignments()) {
  294.         rv = & (gsrr->SetPhi_alignments());
  295.     }
  296.     
  297.     return rv;
  298. }
  299. CRef<objects::CBlast4_mask> CRemoteBlast::GetMask(void)
  300. {
  301.     CRef<objects::CBlast4_mask> rv;
  302.     
  303.     TGSRR * gsrr = x_GetGSRR();
  304.     
  305.     if (gsrr && gsrr->CanGetMask()) {
  306.         rv = & (gsrr->SetMask());
  307.     }
  308.     
  309.     return rv;
  310. }
  311. list< CRef<objects::CBlast4_ka_block > > CRemoteBlast::GetKABlocks(void)
  312.     list< CRef<objects::CBlast4_ka_block > > rv;
  313.         
  314.     TGSRR * gsrr = x_GetGSRR();
  315.     
  316.     if (gsrr && gsrr->CanGetKa_blocks()) {
  317.         rv = (gsrr->SetKa_blocks());
  318.     }
  319.     
  320.     return rv;
  321. }
  322. list< string > CRemoteBlast::GetSearchStats(void)
  323. {
  324.     list< string > rv;
  325.     
  326.     TGSRR * gsrr = x_GetGSRR();
  327.     
  328.     if (gsrr && gsrr->CanGetSearch_stats()) {
  329.         rv = (gsrr->SetSearch_stats());
  330.     }
  331.     
  332.     return rv;
  333. }
  334. CRef<objects::CScore_matrix_parameters> CRemoteBlast::GetPSSM(void)
  335. {
  336.     CRef<objects::CScore_matrix_parameters> rv;
  337.     
  338.     TGSRR * gsrr = x_GetGSRR();
  339.     
  340.     if (gsrr && gsrr->CanGetPssm()) {
  341.         rv = & (gsrr->SetPssm());
  342.     }
  343.     
  344.     return rv;
  345. }
  346. // Internal CRemoteBlast methods
  347. int CRemoteBlast::x_GetState(void)
  348. {
  349.     // CBlast4Option states:
  350.     
  351.     // 0. start  (no rid, no errors)
  352.     // 1. failed (errors)
  353.     // 2. wait   (has rid, no errors, still pending)
  354.     // 3. done   (has rid, no errors, not pending)
  355.     
  356.     int rv = 0;
  357.     
  358.     if (! m_Errs.empty()) {
  359.         rv = eFailed;
  360.     } else if (m_RID.empty()) {
  361.         rv = eStart;
  362.     } else if (m_Pending) {
  363.         rv = eWait;
  364.     } else {
  365.         rv = eDone;
  366.     }
  367.     
  368.     return rv;
  369. }
  370. void CRemoteBlast::x_SubmitSearch(void)
  371. {
  372.     if (m_QSR.Empty()) {
  373.         m_Errs.push_back("No request exists and no RID was specified.");
  374.         return;
  375.     }
  376.     
  377.     x_SetAlgoOpts();
  378.     
  379.     CRef<CBlast4_request_body> body(new CBlast4_request_body);
  380.     body->SetQueue_search(*m_QSR);
  381.     
  382.     CRef<CBlast4_reply> reply;
  383.     
  384.     try {
  385.         reply = x_SendRequest(body);
  386.     }
  387.     catch(const CEofException&) {
  388.         m_Errs.push_back("No response from server, cannot complete request.");
  389.         return;
  390.     }
  391.     
  392.     if (reply->CanGetBody()  &&
  393.         reply->GetBody().GetQueue_search().CanGetRequest_id()) {
  394.         
  395.         m_RID = reply->GetBody().GetQueue_search().GetRequest_id();
  396.     }
  397.     
  398.     x_SearchErrors(reply);
  399.     
  400.     if (m_Errs.empty()) {
  401.         m_Pending = true;
  402.     }
  403. }
  404. void CRemoteBlast::x_CheckResults(void)
  405. {
  406.     if (! m_Errs.empty()) {
  407.         m_Pending = false;
  408.     }
  409.     
  410.     if (! m_Pending) {
  411.         return;
  412.     }
  413.     
  414.     CRef<CBlast4_reply> r;
  415.     
  416.     bool try_again = true;
  417.     
  418.     while(try_again) {
  419.         try {
  420.             r = x_GetSearchResults();
  421.             m_Pending = s_SearchPending(r);
  422.             try_again = false;
  423.         }
  424.         catch(const CEofException&) {
  425.             --m_ErrIgn;
  426.             
  427.             if (m_ErrIgn == 0) {
  428.                 m_Errs.push_back("No response from server, "
  429.                                  "cannot complete request.");
  430.                 return;
  431.             }
  432.             
  433.             SleepSec(10);
  434.         }
  435.     }
  436.     
  437.     if (! m_Pending) {
  438.         x_SearchErrors(r);
  439.         
  440.         if (! m_Errs.empty()) {
  441.             return;
  442.         } else if (r->CanGetBody() && r->GetBody().IsGet_search_results()) {
  443.             m_Reply = r;
  444.         } else {
  445.             m_Errs.push_back("Results were not a get-search-results reply");
  446.         }
  447.     }
  448. }
  449. // The input here is a hint as to whether the request might be ready.
  450. // If the flag is true, then we are polling immediately after
  451. // submission.  In this case, the results will not be ready, and so we
  452. // skip the first results check to reduce net traffic.  If the flag is
  453. // false, then the user is using the asynchronous interface, and we do
  454. // not know how long it has been since the request was submitted.  In
  455. // this case, we check the results before sleeping.
  456. //
  457. // If this was always set to 'true' then async mode would -always-
  458. // sleep.  This is undesireable in the case where (for example) 100
  459. // requests are batched together - the mandatory sleeps would add to a
  460. // total of 1000 seconds, more than a quarter hour.
  461. //
  462. // If it were always specified as 'false', then synchronous mode would
  463. // shoot off an immediate 'check results' as soon as the "submit"
  464. // returned, which creates unnecessary traffic.
  465. //
  466. // Futher optimizations are no doubt possible.
  467. void CRemoteBlast::x_PollUntilDone(EImmediacy immed, int timeout)
  468. {
  469.     if (eDebug == m_Verbose)
  470.         cout << "polling " << 0 << endl;
  471.     
  472.     // Configuration - internal for now
  473.     
  474.     double start_sec = 10.0;
  475.     double increment = 1.30;
  476.     double max_sleep = 300.0;
  477.     double max_time  = timeout;
  478.     
  479.     if (eDebug == m_Verbose)
  480.         cout << "polling " << start_sec << "/" << increment << "/" << max_sleep << "/" << max_time << "/" << endl;
  481.     
  482.     // End config
  483.     
  484.     double sleep_next = start_sec;
  485.     double sleep_totl = 0.0;
  486.     
  487.     if (eDebug == m_Verbose)
  488.         cout << "line " << __LINE__ << " sleep next " << sleep_next << " sleep totl " << sleep_totl << endl;
  489.     
  490.     if (ePollAsync == immed) {
  491.         x_CheckResults();
  492.     }
  493.     
  494.     while (m_Pending && (sleep_totl < max_time)) {
  495.         if (eDebug == m_Verbose)
  496.             cout << " about to sleep " << sleep_next << endl;
  497.         
  498.         double max_left = max_time - sleep_totl;
  499.         
  500.         // Don't oversleep
  501.         if (sleep_next > max_left) {
  502.             sleep_next = max_left;
  503.             
  504.             // But never sleep less than 2
  505.             if (sleep_next < 2.0)
  506.                 sleep_next = 2.0;
  507.         }
  508.         
  509.         SleepSec(int(sleep_next));
  510.         sleep_totl += sleep_next;
  511.         
  512.         if (eDebug == m_Verbose)
  513.             cout << " done, total = " << sleep_totl << endl;
  514.         
  515.         if (sleep_next < max_sleep) {
  516.             sleep_next *= increment;
  517.             if (sleep_next > max_sleep) {
  518.                 sleep_next = max_sleep;
  519.             }
  520.         }
  521.         
  522.         if (eDebug == m_Verbose)
  523.             cout << " next sleep time = " << sleep_next << endl;
  524.         
  525.         x_CheckResults();
  526.     }
  527. }
  528. void CRemoteBlast::x_Init(CBlastOptionsHandle * opts_handle,
  529.                           const char          * program,
  530.                           const char          * service)
  531. {
  532.     if (! (opts_handle && program && service)) {
  533.         if (! opts_handle) {
  534.             NCBI_THROW(CBlastException, eBadParameter,
  535.                        "NULL argument specified: options handle");
  536.         }
  537.         if (! program) {
  538.             NCBI_THROW(CBlastException, eBadParameter,
  539.                        "NULL argument specified: program");
  540.         }
  541.         NCBI_THROW(CBlastException, eBadParameter,
  542.                    "NULL argument specified: service");
  543.     }
  544.     
  545.     m_CBOH.Reset( opts_handle );
  546.     m_ErrIgn     = 5;
  547.     m_Pending    = false;
  548.     m_Verbose    = eSilent;
  549.     m_NeedConfig = eNeedAll;
  550.     
  551.     m_QSR.Reset(new objects::CBlast4_queue_search_request);
  552.     
  553.     m_QSR->SetProgram(program);
  554.     m_QSR->SetService(service);
  555.     
  556.     m_NeedConfig = ENeedConfig(m_NeedConfig & ~(eProgram | eService));
  557.     
  558.     if (! (opts_handle && opts_handle->SetOptions().GetBlast4AlgoOpts())) {
  559.         // This happens if you do not specify eRemote for the
  560.         // CBlastOptions subclass constructor.
  561.         
  562.         NCBI_THROW(CBlastException, eBadParameter,
  563.                    "CRemoteBlast: No remote API options.");
  564.     }
  565. }
  566. void CRemoteBlast::x_Init(const string & RID)
  567. {
  568.     if (RID.empty()) {
  569.         NCBI_THROW(CBlastException, eBadParameter,
  570.                    "Empty RID string specified");
  571.     }
  572.     
  573.     m_RID        = RID;
  574.     m_ErrIgn     = 5;
  575.     m_Pending    = true;
  576.     m_Verbose    = eSilent;
  577.     m_NeedConfig = eNoConfig;
  578. }
  579. void CRemoteBlast::x_SetAlgoOpts(void)
  580. {
  581.     CBlast4_parameters * algo_opts =
  582.         m_CBOH->SetOptions().GetBlast4AlgoOpts();
  583.     
  584.     m_QSR->SetAlgorithm_options().Set() = *algo_opts;
  585. }
  586. // the "int" version is not actually used (no program options need it.)
  587. void CRemoteBlast::x_SetOneParam(const char * name, const int * x)
  588. {
  589.     CRef<objects::CBlast4_value> v(new objects::CBlast4_value);
  590.     v->SetInteger(*x);
  591.         
  592.     CRef<objects::CBlast4_parameter> p(new objects::CBlast4_parameter);
  593.     p->SetName(name);
  594.     p->SetValue(*v);
  595.         
  596.     m_QSR->SetProgram_options().Set().push_back(p);
  597. }
  598. void CRemoteBlast::x_SetOneParam(const char * name, const list<int> * x)
  599. {
  600.     CRef<objects::CBlast4_value> v(new objects::CBlast4_value);
  601.     v->SetInteger_list() = *x;
  602.         
  603.     CRef<objects::CBlast4_parameter> p(new objects::CBlast4_parameter);
  604.     p->SetName(name);
  605.     p->SetValue(*v);
  606.         
  607.     m_QSR->SetProgram_options().Set().push_back(p);
  608. }
  609. void CRemoteBlast::x_SetOneParam(const char * name, const char ** x)
  610. {
  611.     CRef<objects::CBlast4_value> v(new objects::CBlast4_value);
  612.     v->SetString().assign((x && (*x)) ? (*x) : "");
  613.         
  614.     CRef<objects::CBlast4_parameter> p(new objects::CBlast4_parameter);
  615.     p->SetName(name);
  616.     p->SetValue(*v);
  617.         
  618.     m_QSR->SetProgram_options().Set().push_back(p);
  619. }
  620. void CRemoteBlast::x_SetOneParam(const char * name, objects::CScore_matrix_parameters * matrix)
  621. {
  622.     CRef<objects::CBlast4_value> v(new objects::CBlast4_value);
  623.     v->SetMatrix(*matrix);
  624.         
  625.     CRef<objects::CBlast4_parameter> p(new objects::CBlast4_parameter);
  626.     p->SetName(name);
  627.     p->SetValue(*v);
  628.         
  629.     m_QSR->SetProgram_options().Set().push_back(p);
  630. }
  631. void CRemoteBlast::SetQueries(CRef<objects::CBioseq_set> bioseqs)
  632. {
  633.     if (bioseqs.Empty()) {
  634.         NCBI_THROW(CBlastException, eBadParameter,
  635.                    "Empty reference for query.");
  636.     }
  637.     
  638.     CRef<objects::CBlast4_queries> queries_p(new objects::CBlast4_queries);
  639.     queries_p->SetBioseq_set(*bioseqs);
  640.     
  641.     m_QSR->SetQueries(*queries_p);
  642.     m_NeedConfig = ENeedConfig(m_NeedConfig & (~ eQueries));
  643. }
  644. void CRemoteBlast::SetQueries(list< CRef<objects::CSeq_loc> > & seqlocs)
  645. {
  646.     if (seqlocs.empty()) {
  647.         NCBI_THROW(CBlastException, eBadParameter,
  648.                    "Empty list for query.");
  649.     }
  650.     
  651.     CRef<objects::CBlast4_queries> queries_p(new objects::CBlast4_queries);
  652.     queries_p->SetSeq_loc_list() = seqlocs;
  653.     
  654.     m_QSR->SetQueries(*queries_p);
  655.     m_NeedConfig = ENeedConfig(m_NeedConfig & (~ eQueries));
  656. }
  657. void CRemoteBlast::SetQueries(CRef<objects::CScore_matrix_parameters> pssm)
  658. {
  659.     if (pssm.Empty()) {
  660.         NCBI_THROW(CBlastException, eBadParameter,
  661.                    "Empty reference for query pssm.");
  662.     }
  663.     
  664.     if (! pssm->GetMatrix().CanGetQuery()) {
  665.         NCBI_THROW(CBlastException, eBadParameter,
  666.                    "Empty reference for pssm component pssm.matrix.query.");
  667.     }
  668.     
  669.     string psi_program("blastp");
  670.     string old_service("plain");
  671.     string new_service("psi");
  672.     
  673.     if (m_QSR->GetProgram() != psi_program) {
  674.         NCBI_THROW(CBlastException, eBadParameter,
  675.                    "PSI-Blast is only supported for blastp.");
  676.     }
  677.     
  678.     if (m_QSR->GetService().empty()) {
  679.         NCBI_THROW(CBlastException, eInternal,
  680.                    "Internal error: service is not set.");
  681.     }
  682.     
  683.     if ((m_QSR->GetService() != old_service) &&
  684.         (m_QSR->GetService() != new_service)) {
  685.         
  686.         // Allowing "psi" allows the matrix to be set, then replaced.
  687.         
  688.         NCBI_THROW(CBlastException, eBadParameter,
  689.                    string("PSI-Blast cannot also be ") +
  690.                    m_QSR->GetService() + ".");
  691.     }
  692.     
  693.     CRef<objects::CBlast4_queries> queries_p(new objects::CBlast4_queries);
  694.     queries_p->SetPssm(*pssm);
  695.     
  696.     m_QSR->SetQueries(*queries_p);
  697.     m_NeedConfig = ENeedConfig(m_NeedConfig & (~ eQueries));
  698.     
  699.     m_QSR->SetService(new_service);
  700. }
  701. void CRemoteBlast::SetDatabase(const char * x)
  702. {
  703.     if (!x) {
  704.         NCBI_THROW(CBlastException, eBadParameter,
  705.                    "NULL specified for database.");
  706.     }
  707.         
  708.     CRef<objects::CBlast4_subject> subject_p(new objects::CBlast4_subject);
  709.     subject_p->SetDatabase(x);
  710.     m_QSR->SetSubject(*subject_p);
  711.     m_NeedConfig = ENeedConfig(m_NeedConfig & (~ eSubject));
  712. }
  713. string CRemoteBlast::GetErrors(void)
  714. {
  715.     if (m_Errs.empty()) {
  716.         return string();
  717.     }
  718.     
  719.     string rvalue = m_Errs[0];
  720.     
  721.     for(unsigned i = 1; i<m_Errs.size(); i++) {
  722.         rvalue += "n";
  723.         rvalue += m_Errs[i];
  724.     }
  725.     
  726.     return rvalue;
  727. }
  728. string CRemoteBlast::GetWarnings(void)
  729. {
  730.     if (m_Warn.empty()) {
  731.         return string();
  732.     }
  733.     
  734.     string rvalue = m_Warn[0];
  735.     
  736.     for(unsigned i = 1; i<m_Warn.size(); i++) {
  737.         rvalue += "n";
  738.         rvalue += m_Warn[i];
  739.     }
  740.     
  741.     return rvalue;
  742. }
  743. END_SCOPE(blast)
  744. END_NCBI_SCOPE
  745. /* @} */
  746. /*
  747. * ===========================================================================
  748. *
  749. * $Log: remote_blast.cpp,v $
  750. * Revision 1000.1  2004/06/01 18:06:16  gouriano
  751. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  752. *
  753. * Revision 1.13  2004/05/21 21:41:02  gorelenk
  754. * Added PCH ncbi_pch.hpp
  755. *
  756. * Revision 1.12  2004/05/12 19:26:49  bealer
  757. * - Additional checking for PSSM queries.
  758. * - PSSM query now implies service="psi".
  759. *
  760. * Revision 1.11  2004/05/10 15:10:08  bealer
  761. * - Error processing problem: messages should be treated as optional.
  762. *
  763. * Revision 1.10  2004/05/05 17:39:46  dicuccio
  764. * Fixed syntax error on MSVC6
  765. *
  766. * Revision 1.9  2004/05/05 15:35:30  bealer
  767. * - Features:
  768. *   - Add PSSM queries (for PSI-Blast) and seq-loc-list.
  769. *   - Add GetWarnings() mechanism.
  770. *   - Add PSSM queries (for PSI-Blast).
  771. *   - Add seq-loc-list queries (allows multiple identifier base queries, or
  772. *     one query based on identifier plus interval.
  773. *   - Add GetPSSM() to retrieve results of PSI-Blast run.
  774. *
  775. * - Other changes:
  776. *   - Move some static functions into class.
  777. *   - Rework error processing to split out warnings.
  778. *   - Changes to error text formats.
  779. *   - Seperate some common code into x_GetGSSR() util method.
  780. *   - De-inlined several methods.
  781. *
  782. * Revision 1.8  2004/04/12 16:35:25  bealer
  783. * - Fix CheckDone problem in CRemoteBlast.
  784. * - Add more parameter checking and exception throwing.
  785. *
  786. * Revision 1.7  2004/03/23 22:29:42  bealer
  787. * - Verify that CRemoteBlast objects are configured properly.
  788. *
  789. * Revision 1.6  2004/03/19 19:22:55  camacho
  790. * Move to doxygen group AlgoBlast, add missing CVS logs at EOF
  791. *
  792. * Revision 1.5  2004/03/12 22:07:03  camacho
  793. * Remove unused variables
  794. *
  795. * Revision 1.4  2004/02/26 22:24:46  gorelenk
  796. * Include for <unistd.h> moved to be after
  797. * #include <corelib/ncbi_system.hpp>.
  798. *
  799. * Revision 1.3  2004/02/26 17:07:40  gorelenk
  800. * Added #if defined(NCBI_OS_UNIX) for #include <unistd.h>.
  801. *
  802. * Revision 1.2  2004/02/18 18:28:51  bealer
  803. * - Fix verbosity tests.
  804. *
  805. * Revision 1.1  2004/02/18 17:30:57  bealer
  806. * - Change blast4_options.* to remote_blast.*, plus changes.
  807. *
  808. * Revision 1.6  2004/02/09 22:35:37  bealer
  809. * - Delay examination of CBlastOptionsHandle object until Submit() action.
  810. *
  811. * Revision 1.5  2004/02/06 00:16:39  bealer
  812. * - Add RID capability.
  813. * - Detect lack of eRemote flag.
  814. *
  815. * Revision 1.4  2004/02/05 19:20:39  bealer
  816. * - Add retry capability to API code.
  817. *
  818. * Revision 1.3  2004/02/05 00:37:43  bealer
  819. * - Polling optimization.
  820. *
  821. * Revision 1.2  2004/02/04 22:31:14  bealer
  822. * - Add async interface to Blast4 API.
  823. * - Clean up, simplify code and interfaces.
  824. * - Add state-based logic to promote robustness.
  825. *
  826. * Revision 1.1  2004/01/16 20:37:55  bealer
  827. * - Add CBlast4Options class (Blast 4 API)
  828. *
  829. *
  830. * ===========================================================================
  831. */