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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: rpc.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:19:50  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: rpc.cpp,v 1000.1 2004/06/01 19:19:50 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:  Vladimir Soussov
  35.  *
  36.  * File Description:  CTLib RPC command
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/ctlib/interfaces.hpp>
  41. BEGIN_NCBI_SCOPE
  42. /////////////////////////////////////////////////////////////////////////////
  43. //
  44. //  CTL_RPCCmd::
  45. //
  46. CTL_RPCCmd::CTL_RPCCmd(CTL_Connection* conn, CS_COMMAND* cmd,
  47.                        const string& proc_name, unsigned int nof_params)
  48.     : m_Connect(conn),
  49.       m_Cmd(cmd),
  50.       m_Query(proc_name),
  51.       m_Params(nof_params)
  52. {
  53.     m_WasSent     = false;
  54.     m_HasFailed   = false;
  55.     m_Recompile   = false;
  56.     m_Res         = 0;
  57.     m_RowCount    = -1;
  58. }
  59. bool CTL_RPCCmd::BindParam(const string& param_name, CDB_Object* param_ptr,
  60.                            bool out_param)
  61. {
  62.     return m_Params.BindParam(CDB_Params::kNoParamNumber, param_name,
  63.                               param_ptr, out_param);
  64. }
  65. bool CTL_RPCCmd::SetParam(const string& param_name, CDB_Object* param_ptr,
  66.                           bool out_param)
  67. {
  68.     return m_Params.SetParam(CDB_Params::kNoParamNumber, param_name,
  69.                              param_ptr, out_param);
  70. }
  71. bool CTL_RPCCmd::Send()
  72. {
  73.     if ( m_WasSent ) {
  74.         Cancel();
  75.     }
  76.     m_HasFailed = false;
  77.     switch ( ct_command(m_Cmd, CS_RPC_CMD,
  78.                         const_cast<char*> (m_Query.c_str()), CS_NULLTERM,
  79.                         m_Recompile ? CS_RECOMPILE : CS_UNUSED) ) {
  80.     case CS_SUCCEED:
  81.         break;
  82.     case CS_FAIL:
  83.         m_HasFailed = true;
  84.         throw CDB_ClientEx(eDB_Fatal, 121001, "CTL_RPCCmd::Send",
  85.                            "ct_command failed");
  86.     case CS_BUSY:
  87.         throw CDB_ClientEx(eDB_Error, 121002, "CTL_RPCCmd::Send",
  88.                            "the connection is busy");
  89.     }
  90.     if ( !x_AssignParams() ) {
  91.         m_HasFailed = true;
  92.         throw CDB_ClientEx(eDB_Error, 121003, "CTL_RPCCmd::Send",
  93.                            "cannot assign the params");
  94.     }
  95.     switch ( ct_send(m_Cmd) ) {
  96.     case CS_SUCCEED:
  97.         break;
  98.     case CS_FAIL:
  99.         m_HasFailed = true;
  100.         if (ct_cancel(0, m_Cmd, CS_CANCEL_ALL) != CS_SUCCEED) {
  101.             // we need to close this connection
  102.             throw CDB_ClientEx(eDB_Fatal, 121004, "CTL_RPCCmd::Send",
  103.                                "Unrecoverable crash of ct_send. "
  104.                                "Connection must be closed");
  105.         }
  106.         throw CDB_ClientEx(eDB_Error, 121005, "CTL_RPCCmd::Send",
  107.                            "ct_send failed");
  108.     case CS_CANCELED:
  109.         throw CDB_ClientEx(eDB_Error, 121006, "CTL_RPCCmd::Send",
  110.                            "command was canceled");
  111.     case CS_BUSY:
  112.         throw CDB_ClientEx(eDB_Error, 121007, "CTL_RPCCmd::Send",
  113.                            "connection has another request pending");
  114.     case CS_PENDING:
  115.     default:
  116.         m_WasSent = true;
  117.         return false;
  118.     }
  119.     m_WasSent = true;
  120.     return true;
  121. }
  122. bool CTL_RPCCmd::WasSent() const
  123. {
  124.     return m_WasSent;
  125. }
  126. bool CTL_RPCCmd::Cancel()
  127. {
  128.     if ( !m_WasSent ) {
  129.         return true;
  130.     }
  131.     if ( m_Res ) {
  132.         // to prevent ct_cancel(NULL, m_Cmd, CS_CANCEL_CURRENT) call:
  133.         ((CTL_RowResult*)m_Res)->m_EOR= true; 
  134.         delete m_Res;
  135.         m_Res = 0;
  136.     }
  137.     switch ( ct_cancel(0, m_Cmd, CS_CANCEL_ALL) ) {
  138.     case CS_SUCCEED:
  139.         m_WasSent = false;
  140.         return true;
  141.     case CS_FAIL:
  142.         throw CDB_ClientEx(eDB_Error, 121008, "CTL_RPCCmd::Cancel",
  143.                            "ct_cancel failed");
  144.     case CS_BUSY:
  145.         throw CDB_ClientEx(eDB_Error, 121009, "CTL_RPCCmd::Cancel",
  146.                            "connection has another request pending");
  147.     default:
  148.         return false;
  149.     }
  150. }
  151. bool CTL_RPCCmd::WasCanceled() const
  152. {
  153.     return !m_WasSent;
  154. }
  155. CDB_Result* CTL_RPCCmd::Result()
  156. {
  157.     if ( m_Res ) {
  158.         delete m_Res;
  159.         m_Res = 0;
  160.     }
  161.     if ( !m_WasSent ) {
  162.         throw CDB_ClientEx(eDB_Error, 121010, "CTL_RPCCmd::Result",
  163.                            "you need to send a command first");
  164.     }
  165.     for (;;) {
  166.         CS_INT res_type;
  167.         switch ( ct_results(m_Cmd, &res_type) ) {
  168.         case CS_SUCCEED:
  169.             break;
  170.         case CS_END_RESULTS:
  171.             m_WasSent = false;
  172.             return 0;
  173.         case CS_FAIL:
  174.             m_HasFailed = true;
  175.             if (ct_cancel(0, m_Cmd, CS_CANCEL_ALL) != CS_SUCCEED) {
  176.                 // we need to close this connection
  177.                 throw CDB_ClientEx(eDB_Fatal, 121012, "CTL_RPCCmd::Result",
  178.                                    "Unrecoverable crash of ct_result. "
  179.                                    "Connection must be closed");
  180.             }
  181.             m_WasSent = false;
  182.             throw CDB_ClientEx(eDB_Error, 121013, "CTL_RPCCmd::Result",
  183.                                "ct_result failed");
  184.         case CS_CANCELED:
  185.             m_WasSent = false;
  186.             throw CDB_ClientEx(eDB_Error, 121011, "CTL_RPCCmd::Result",
  187.                                "your command has been canceled");
  188.         case CS_BUSY:
  189.             throw CDB_ClientEx(eDB_Error, 121014, "CTL_RPCCmd::Result",
  190.                                "connection has another request pending");
  191.         default:
  192.             throw CDB_ClientEx(eDB_Error, 121015, "CTL_RPCCmd::Result",
  193.                                "your request is pending");
  194.         }
  195.         switch ( res_type ) {
  196.         case CS_CMD_SUCCEED:
  197.         case CS_CMD_DONE: // done with this command
  198.             // check the number of affected rows
  199.             g_CTLIB_GetRowCount(m_Cmd, &m_RowCount);
  200.             continue;
  201.         case CS_CMD_FAIL: // the command has failed
  202.             g_CTLIB_GetRowCount(m_Cmd, &m_RowCount);
  203.             m_HasFailed = true;
  204.             throw CDB_ClientEx(eDB_Warning, 121016, "CTL_RPCCmd::Result",
  205.                                "The server encountered an error while "
  206.                                "executing a command");
  207.         case CS_ROW_RESULT:
  208.             m_Res = new CTL_RowResult(m_Cmd);
  209.             break;
  210.         case CS_PARAM_RESULT:
  211.             m_Res = new CTL_ParamResult(m_Cmd);
  212.             break;
  213.         case CS_COMPUTE_RESULT:
  214.             m_Res = new CTL_ComputeResult(m_Cmd);
  215.             break;
  216.         case CS_STATUS_RESULT:
  217.             m_Res = new CTL_StatusResult(m_Cmd);
  218.             break;
  219.         case CS_COMPUTEFMT_RESULT:
  220.             throw CDB_ClientEx(eDB_Info, 121017, "CTL_RPCCmd::Result",
  221.                                "CS_COMPUTEFMT_RESULT has arrived");
  222.         case CS_ROWFMT_RESULT:
  223.             throw CDB_ClientEx(eDB_Info, 121018, "CTL_RPCCmd::Result",
  224.                                "CS_ROWFMT_RESULT has arrived");
  225.         case CS_MSG_RESULT:
  226.             throw CDB_ClientEx(eDB_Info, 121019, "CTL_RPCCmd::Result",
  227.                                "CS_MSG_RESULT has arrived");
  228.         default:
  229.             throw CDB_ClientEx(eDB_Warning, 121020, "CTL_RPCCmd::Result",
  230.                                "Unexpected result type has arrived");
  231.         }
  232.         return Create_Result(*m_Res);
  233.     }
  234. }
  235. void CTL_RPCCmd::DumpResults()
  236. {
  237.     if ( m_Res ) {
  238.         delete m_Res;
  239.         m_Res = 0;
  240.     }
  241.     if ( !m_WasSent ) {
  242.         throw CDB_ClientEx(eDB_Error, 121010, "CTL_RPCCmd::DumpResults",
  243.                            "you need to send a command first");
  244.     }
  245.     for (;;) {
  246.         CS_INT res_type;
  247.         switch ( ct_results(m_Cmd, &res_type) ) {
  248.         case CS_SUCCEED:
  249.             break;
  250.         case CS_END_RESULTS:
  251.             m_WasSent = false;
  252.             return;
  253.         case CS_FAIL:
  254.             m_HasFailed = true;
  255.             if (ct_cancel(0, m_Cmd, CS_CANCEL_ALL) != CS_SUCCEED) {
  256.                 // we need to close this connection
  257.                 throw CDB_ClientEx(eDB_Fatal, 121012, "CTL_RPCCmd::DumpResults",
  258.                                    "Unrecoverable crash of ct_result. "
  259.                                    "Connection must be closed");
  260.             }
  261.             m_WasSent = false;
  262.             throw CDB_ClientEx(eDB_Error, 121013, "CTL_RPCCmd::DumpResults",
  263.                                "ct_result failed");
  264.         case CS_CANCELED:
  265.             m_WasSent = false;
  266.             throw CDB_ClientEx(eDB_Error, 121011, "CTL_RPCCmd::DumpResults",
  267.                                "your command has been canceled");
  268.         case CS_BUSY:
  269.             throw CDB_ClientEx(eDB_Error, 121014, "CTL_RPCCmd::DumpResults",
  270.                                "connection has another request pending");
  271.         default:
  272.             throw CDB_ClientEx(eDB_Error, 121015, "CTL_RPCCmd::DumpResults",
  273.                                "your request is pending");
  274.         }
  275.         switch ( res_type ) {
  276.         case CS_CMD_SUCCEED:
  277.         case CS_CMD_DONE: // done with this command
  278.             // check the number of affected rows
  279.             g_CTLIB_GetRowCount(m_Cmd, &m_RowCount);
  280.             continue;
  281.         case CS_CMD_FAIL: // the command has failed
  282.             g_CTLIB_GetRowCount(m_Cmd, &m_RowCount);
  283.             m_HasFailed = true;
  284.             throw CDB_ClientEx(eDB_Warning, 121016, "CTL_RPCCmd::DumpResults",
  285.                                "The server encountered an error while "
  286.                                "executing a command");
  287.         case CS_ROW_RESULT:
  288.             m_Res = new CTL_RowResult(m_Cmd);
  289.             break;
  290.         case CS_PARAM_RESULT:
  291.             m_Res = new CTL_ParamResult(m_Cmd);
  292.             break;
  293.         case CS_COMPUTE_RESULT:
  294.             m_Res = new CTL_ComputeResult(m_Cmd);
  295.             break;
  296.         case CS_STATUS_RESULT:
  297.             m_Res = new CTL_StatusResult(m_Cmd);
  298.             break;
  299.         case CS_COMPUTEFMT_RESULT:
  300.             throw CDB_ClientEx(eDB_Info, 121017, "CTL_RPCCmd::DumpResults",
  301.                                "CS_COMPUTEFMT_RESULT has arrived");
  302.         case CS_ROWFMT_RESULT:
  303.             throw CDB_ClientEx(eDB_Info, 121018, "CTL_RPCCmd::DumpResults",
  304.                                "CS_ROWFMT_RESULT has arrived");
  305.         case CS_MSG_RESULT:
  306.             throw CDB_ClientEx(eDB_Info, 121019, "CTL_RPCCmd::DumpResults",
  307.                                "CS_MSG_RESULT has arrived");
  308.         default:
  309.             throw CDB_ClientEx(eDB_Warning, 121020, "CTL_RPCCmd::DumpResults",
  310.                                "Unexpected result type has arrived");
  311.         }
  312.         if(m_Res) {
  313.             if(m_Connect->m_ResProc) {
  314.                 CDB_Result* r= Create_Result(*m_Res);
  315.                 m_Connect->m_ResProc->ProcessResult(*r);
  316.                 delete r;
  317.             }
  318.             else {
  319.                 while(m_Res->Fetch());
  320.             }
  321.             delete m_Res;
  322.             m_Res= 0;
  323.         }
  324.     }
  325. }
  326. bool CTL_RPCCmd::HasMoreResults() const
  327. {
  328.     return m_WasSent;
  329. }
  330. bool CTL_RPCCmd::HasFailed() const
  331. {
  332.     return m_HasFailed;
  333. }
  334. int CTL_RPCCmd::RowCount() const
  335. {
  336.     return m_RowCount;
  337. }
  338. void CTL_RPCCmd::SetRecompile(bool recompile)
  339. {
  340.     m_Recompile = recompile;
  341. }
  342. void CTL_RPCCmd::Release()
  343. {
  344.     m_BR = 0;
  345.     if ( m_WasSent) {
  346.         try {
  347.             Cancel();
  348.         } catch (CDB_Exception& ) {}
  349.         m_WasSent = false;
  350.     }
  351.     m_Connect->DropCmd(*this);
  352.     delete this;
  353. }
  354. CTL_RPCCmd::~CTL_RPCCmd()
  355. {
  356.     if ( m_BR ) {
  357.         *m_BR = 0;
  358.     }
  359.     if ( m_WasSent ) {
  360.         try {
  361.             Cancel();
  362.         } catch (CDB_Exception& ) {}
  363.     }
  364.     ct_cmd_drop(m_Cmd);
  365. }
  366. bool CTL_RPCCmd::x_AssignParams()
  367. {
  368.     CS_DATAFMT param_fmt;
  369.     memset(&param_fmt, 0, sizeof(param_fmt));
  370.     param_fmt.namelen = CS_NULLTERM;
  371.     for (unsigned int i = 0;  i < m_Params.NofParams();  i++) {
  372.         if(m_Params.GetParamStatus(i) == 0) continue;
  373.         CDB_Object&   param      = *m_Params.GetParam(i);
  374.         const string& param_name = m_Params.GetParamName(i);
  375.         CS_SMALLINT   indicator  = param.IsNULL() ? -1 : 0;
  376.         param_fmt.status =
  377.             ((m_Params.GetParamStatus(i) & CDB_Params::fOutput) == 0)
  378.             ? CS_INPUTVALUE : CS_RETURN;
  379.         if ( !g_CTLIB_AssignCmdParam(m_Cmd, param, param_name, param_fmt,
  380.                                      indicator, false/*!declare_only*/) ) {
  381.             return false;
  382.         }
  383.     }
  384.     return true;
  385. }
  386. END_NCBI_SCOPE
  387. /*
  388.  * ===========================================================================
  389.  * $Log: rpc.cpp,v $
  390.  * Revision 1000.1  2004/06/01 19:19:50  gouriano
  391.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  392.  *
  393.  * Revision 1.9  2004/05/17 21:12:03  gorelenk
  394.  * Added include of PCH ncbi_pch.hpp
  395.  *
  396.  * Revision 1.8  2003/10/07 16:09:48  soussov
  397.  * adds code which prevents ct_cancel(NULL, m_Cmd, CS_CANCEL_CURRENT) call if command is canceled while retrieving results
  398.  *
  399.  * Revision 1.7  2003/06/24 18:42:26  soussov
  400.  * removes throwing exception from destructor
  401.  *
  402.  * Revision 1.6  2003/06/05 16:00:31  soussov
  403.  * adds code for DumpResults and for the dumped results processing
  404.  *
  405.  * Revision 1.5  2003/05/16 20:24:24  soussov
  406.  * adds code to skip parameters if it was not set
  407.  *
  408.  * Revision 1.4  2003/01/31 16:49:38  lavr
  409.  * Remove unused variable "e" from catch() clause
  410.  *
  411.  * Revision 1.3  2002/09/16 19:40:03  soussov
  412.  * add try catch when canceling in Release method
  413.  *
  414.  * Revision 1.2  2001/11/06 17:59:55  lavr
  415.  * Formatted uniformly as the rest of the library
  416.  *
  417.  * Revision 1.1  2001/09/21 23:40:02  vakatov
  418.  * -----  Initial (draft) revision.  -----
  419.  * This is a major revamp (by Denis Vakatov, with help from Vladimir Soussov)
  420.  * of the DBAPI "driver" libs originally written by Vladimir Soussov.
  421.  * The revamp involved massive code shuffling and grooming, numerous local
  422.  * API redesigns, adding comments and incorporating DBAPI to the C++ Toolkit.
  423.  *
  424.  * ===========================================================================
  425.  */