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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: connection.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:19:34  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: connection.cpp,v 1000.1 2004/06/01 19:19:34 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 connection
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/ctlib/interfaces.hpp>
  41. #include <string.h>
  42. BEGIN_NCBI_SCOPE
  43. CTL_Connection::CTL_Connection(CTLibContext* cntx, CS_CONNECTION* con,
  44.                                bool reusable, const string& pool_name)
  45. {
  46.     m_Link     = con;
  47.     m_Context  = cntx;
  48.     m_Reusable = reusable;
  49.     m_Pool     = pool_name;
  50.     CTL_Connection* link = this;
  51.     ct_con_props(m_Link, CS_SET, CS_USERDATA,
  52.                  &link, (CS_INT) sizeof(link), NULL);
  53.     // retrieve the connection attributes
  54.     CS_INT outlen(0);
  55.     char   buf[512];
  56.     ct_con_props(m_Link, CS_GET, CS_SERVERNAME,
  57.                  buf, (CS_INT) (sizeof(buf) - 1), &outlen);
  58.     if((outlen > 0) && (buf[outlen-1] == '')) --outlen;
  59.     m_Server.append(buf, (size_t) outlen);
  60.     ct_con_props(m_Link, CS_GET, CS_USERNAME,
  61.                  buf, (CS_INT) (sizeof(buf) - 1), &outlen);
  62.     if((outlen > 0) && (buf[outlen-1] == '')) --outlen;
  63.     m_User.append(buf, (size_t) outlen);
  64.     ct_con_props(m_Link, CS_GET, CS_PASSWORD,
  65.                  buf, (CS_INT) (sizeof(buf) - 1), &outlen);
  66.     if((outlen > 0) && (buf[outlen-1] == '')) --outlen;
  67.     m_Passwd.append(buf, (size_t) outlen);
  68.     CS_BOOL flag;
  69.     ct_con_props(m_Link, CS_GET, CS_BULK_LOGIN, &flag, CS_UNUSED, &outlen);
  70.     m_BCPable = (flag == CS_TRUE);
  71.     ct_con_props(m_Link, CS_GET, CS_SEC_ENCRYPTION, &flag, CS_UNUSED, &outlen);
  72.     m_SecureLogin = (flag == CS_TRUE);
  73.     m_ResProc= 0;
  74. }
  75. bool CTL_Connection::IsAlive()
  76. {
  77.     CS_INT status;
  78.     if (ct_con_props(m_Link, CS_GET, CS_CON_STATUS, &status, CS_UNUSED, 0)
  79.         != CS_SUCCEED)
  80.         return false;
  81.     return
  82.         (status & CS_CONSTAT_CONNECTED) != 0  &&
  83.         (status & CS_CONSTAT_DEAD     ) == 0;
  84. }
  85. CDB_LangCmd* CTL_Connection::LangCmd(const string& lang_query,
  86.                                      unsigned int  nof_params)
  87. {
  88.     CS_COMMAND* cmd;
  89.     switch ( ct_cmd_alloc(m_Link, &cmd) ) {
  90.     case CS_SUCCEED:
  91.         break;
  92.     case CS_FAIL:
  93.         throw CDB_ClientEx(eDB_Fatal, 110001, "CTL_Connection::LangCmd",
  94.                            "ct_cmd_alloc failed");
  95.     case CS_BUSY:
  96.         throw CDB_ClientEx(eDB_Fatal, 110002, "CTL_Connection::LangCmd",
  97.                            "the connection is busy");
  98.     }
  99.     CTL_LangCmd* lcmd = new CTL_LangCmd(this, cmd, lang_query, nof_params);
  100.     m_CMDs.Add(lcmd);
  101.     return Create_LangCmd(*lcmd);
  102. }
  103. CDB_RPCCmd* CTL_Connection::RPC(const string& rpc_name,
  104.                                 unsigned int  nof_args)
  105. {
  106.     CS_COMMAND* cmd;
  107.     switch ( ct_cmd_alloc(m_Link, &cmd) ) {
  108.     case CS_SUCCEED:
  109.         break;
  110.     case CS_FAIL:
  111.         throw CDB_ClientEx(eDB_Fatal, 110001, "CTL_Connection::RPC",
  112.                            "ct_cmd_alloc failed");
  113.     case CS_BUSY:
  114.         throw CDB_ClientEx(eDB_Fatal, 110002, "CTL_Connection::RPC",
  115.                            "the connection is busy");
  116.     }
  117.     CTL_RPCCmd* rcmd = new CTL_RPCCmd(this, cmd, rpc_name, nof_args);
  118.     m_CMDs.Add(rcmd);
  119.     return Create_RPCCmd(*rcmd);
  120. }
  121. CDB_BCPInCmd* CTL_Connection::BCPIn(const string& table_name,
  122.                                     unsigned int  nof_columns)
  123. {
  124.     if (!m_BCPable) {
  125.         throw CDB_ClientEx(eDB_Error, 110003, "CTL_Connection::BCPIn",
  126.                            "No bcp on this connection");
  127.     }
  128.     CS_BLKDESC* cmd;
  129.     if (blk_alloc(m_Link, BLK_VERSION_100, &cmd) != CS_SUCCEED) {
  130.         throw CDB_ClientEx(eDB_Fatal, 110004, "CTL_Connection::BCPIn",
  131.                            "blk_alloc failed");
  132.     }
  133.     CTL_BCPInCmd* bcmd = new CTL_BCPInCmd(this, cmd, table_name, nof_columns);
  134.     m_CMDs.Add(bcmd);
  135.     return Create_BCPInCmd(*bcmd);
  136. }
  137. CDB_CursorCmd* CTL_Connection::Cursor(const string& cursor_name,
  138.                                       const string& query,
  139.                                       unsigned int  nof_params,
  140.                                       unsigned int  batch_size)
  141. {
  142.     CS_COMMAND* cmd;
  143.     switch ( ct_cmd_alloc(m_Link, &cmd) ) {
  144.     case CS_SUCCEED:
  145.         break;
  146.     case CS_FAIL:
  147.         throw CDB_ClientEx(eDB_Fatal, 110001, "CTL_Connection::Cursor",
  148.                            "ct_cmd_alloc failed");
  149.     case CS_BUSY:
  150.         throw CDB_ClientEx(eDB_Fatal, 110002, "CTL_Connection::Cursor",
  151.                            "the connection is busy");
  152.     }
  153.     CTL_CursorCmd* ccmd = new CTL_CursorCmd(this, cmd, cursor_name, query,
  154.                                             nof_params, batch_size);
  155.     m_CMDs.Add(ccmd);
  156.     return Create_CursorCmd(*ccmd);
  157. }
  158. CDB_SendDataCmd* CTL_Connection::SendDataCmd(I_ITDescriptor& descr_in,
  159.                                              size_t data_size, bool log_it)
  160. {
  161.     if ( !data_size ) {
  162.         throw CDB_ClientEx(eDB_Fatal, 110092, "CTL_Connection::SendDataCmd",
  163.                            "wrong (zero) data size");
  164.     }
  165.     I_ITDescriptor* p_desc= 0;
  166.     // check what type of descriptor we've got
  167.     if(descr_in.DescriptorType() != CTL_ITDESCRIPTOR_TYPE_MAGNUM) {
  168.         // this is not a native descriptor
  169.         p_desc= x_GetNativeITDescriptor
  170.             (dynamic_cast<CDB_ITDescriptor&> (descr_in));
  171.         if(p_desc == 0) return 0;
  172.     }
  173.     C_ITDescriptorGuard d_guard(p_desc);
  174.     CS_COMMAND* cmd;
  175.     switch ( ct_cmd_alloc(m_Link, &cmd) ) {
  176.     case CS_SUCCEED:
  177.         break;
  178.     case CS_FAIL:
  179.         throw CDB_ClientEx(eDB_Fatal, 110001, "CTL_Connection::SendDataCmd",
  180.                            "ct_cmd_alloc failed");
  181.     case CS_BUSY:
  182.         throw CDB_ClientEx(eDB_Fatal, 110002, "CTL_Connection::SendDataCmd",
  183.                            "the connection is busy");
  184.     }
  185.     if (ct_command(cmd, CS_SEND_DATA_CMD, 0, CS_UNUSED, CS_COLUMN_DATA)
  186.         != CS_SUCCEED) {
  187.         ct_cmd_drop(cmd);
  188.         throw CDB_ClientEx(eDB_Fatal, 110093, "CTL_Connection::SendDataCmd",
  189.                            "ct_command failed");
  190.     }
  191.     CTL_ITDescriptor& desc = p_desc? dynamic_cast<CTL_ITDescriptor&>(*p_desc) :
  192.         dynamic_cast<CTL_ITDescriptor&> (descr_in);
  193.     // desc.m_Desc.datatype   = CS_TEXT_TYPE;
  194.     desc.m_Desc.total_txtlen  = (CS_INT)data_size;
  195.     desc.m_Desc.log_on_update = log_it ? CS_TRUE : CS_FALSE;
  196.     if (ct_data_info(cmd, CS_SET, CS_UNUSED, &desc.m_Desc) != CS_SUCCEED) {
  197.         ct_cancel(0, cmd, CS_CANCEL_ALL);
  198.         ct_cmd_drop(cmd);
  199.         throw CDB_ClientEx(eDB_Fatal, 110093, "CTL_Connection::SendDataCmd",
  200.                            "ct_data_info failed");
  201.     }
  202.     CTL_SendDataCmd* sd_cmd = new CTL_SendDataCmd(this, cmd, data_size);
  203.     m_CMDs.Add(sd_cmd);
  204.     return Create_SendDataCmd(*sd_cmd);
  205. }
  206. bool CTL_Connection::SendData(I_ITDescriptor& desc, CDB_Image& img,
  207.                               bool log_it)
  208. {
  209.     return x_SendData(desc, img, log_it);
  210. }
  211. bool CTL_Connection::SendData(I_ITDescriptor& desc, CDB_Text& txt,
  212.                               bool log_it)
  213. {
  214.     return x_SendData(desc, txt, log_it);
  215. }
  216. bool CTL_Connection::Refresh()
  217. {
  218.     // close all commands first
  219.     while(m_CMDs.NofItems() > 0) {
  220.         CDB_BaseEnt* pCmd = static_cast<CDB_BaseEnt*> (m_CMDs.Get(0));
  221.         try {
  222.             delete pCmd;
  223.         } catch (CDB_Exception& ) {
  224.         }
  225.         m_CMDs.Remove((int) 0);
  226.     }
  227.     // cancel all pending commands
  228.     if (ct_cancel(m_Link, 0, CS_CANCEL_ALL) != CS_SUCCEED)
  229.         return false;
  230.     // check the connection status
  231.     CS_INT status;
  232.     if (ct_con_props(m_Link, CS_GET, CS_CON_STATUS, &status, CS_UNUSED, 0)
  233.         != CS_SUCCEED)
  234.         return false;
  235.     return
  236.         (status & CS_CONSTAT_CONNECTED) != 0  &&
  237.         (status & CS_CONSTAT_DEAD     ) == 0;
  238. }
  239. const string& CTL_Connection::ServerName() const
  240. {
  241.     return m_Server;
  242. }
  243. const string& CTL_Connection::UserName() const
  244. {
  245.     return m_User;
  246. }
  247. const string& CTL_Connection::Password() const
  248. {
  249.     return m_Passwd;
  250. }
  251. I_DriverContext::TConnectionMode CTL_Connection::ConnectMode() const
  252. {
  253.     I_DriverContext::TConnectionMode mode = 0;
  254.     if ( m_BCPable ) {
  255.         mode |= I_DriverContext::fBcpIn;
  256.     }
  257.     if ( m_SecureLogin ) {
  258.         mode |= I_DriverContext::fPasswordEncrypted;
  259.     }
  260.     return mode;
  261. }
  262. bool CTL_Connection::IsReusable() const
  263. {
  264.     return m_Reusable;
  265. }
  266. const string& CTL_Connection::PoolName() const
  267. {
  268.     return m_Pool;
  269. }
  270. I_DriverContext* CTL_Connection::Context() const
  271. {
  272.     return const_cast<CTLibContext*> (m_Context);
  273. }
  274. void CTL_Connection::PushMsgHandler(CDB_UserHandler* h)
  275. {
  276.     m_MsgHandlers.Push(h);
  277. }
  278. void CTL_Connection::PopMsgHandler(CDB_UserHandler* h)
  279. {
  280.     m_MsgHandlers.Pop(h);
  281. }
  282. CDB_ResultProcessor* CTL_Connection::SetResultProcessor(CDB_ResultProcessor* rp)
  283. {
  284.     CDB_ResultProcessor* r= m_ResProc;
  285.     m_ResProc= rp;
  286.     return r;
  287. }
  288. void CTL_Connection::Release()
  289. {
  290.     m_BR = 0;
  291.     // close all commands first
  292.     while(m_CMDs.NofItems() > 0) {
  293.         CDB_BaseEnt* pCmd = static_cast<CDB_BaseEnt*> (m_CMDs.Get(0));
  294.         try {
  295.             delete pCmd;
  296.         } catch (CDB_Exception& ) {
  297.         }
  298.         m_CMDs.Remove((int) 0);
  299.     }
  300. }
  301. CTL_Connection::~CTL_Connection()
  302. {
  303.     if (!Refresh()  ||  ct_close(m_Link, CS_UNUSED) != CS_SUCCEED) {
  304.         ct_close(m_Link, CS_FORCE_CLOSE);
  305.     }
  306.     ct_con_drop(m_Link);
  307. }
  308. void CTL_Connection::DropCmd(CDB_BaseEnt& cmd)
  309. {
  310.     m_CMDs.Remove(static_cast<TPotItem> (&cmd));
  311. }
  312. bool CTL_Connection::x_SendData(I_ITDescriptor& descr_in, CDB_Stream& img,
  313.                                 bool log_it)
  314. {
  315.     CS_INT size = (CS_INT) img.Size();
  316.     if ( !size )
  317.         return false;
  318.     I_ITDescriptor* p_desc= 0;
  319.     // check what type of descriptor we've got
  320.     if(descr_in.DescriptorType() != CTL_ITDESCRIPTOR_TYPE_MAGNUM) {
  321.         // this is not a native descriptor
  322.         p_desc= x_GetNativeITDescriptor
  323.             (dynamic_cast<CDB_ITDescriptor&> (descr_in));
  324.         if(p_desc == 0)
  325.             return false;
  326.     }
  327.     
  328.     C_ITDescriptorGuard d_guard(p_desc);
  329.     CS_COMMAND* cmd;
  330.     switch ( ct_cmd_alloc(m_Link, &cmd) ) {
  331.     case CS_SUCCEED:
  332.         break;
  333.     case CS_FAIL:
  334.         throw CDB_ClientEx(eDB_Fatal, 110001, "CTL_Connection::SendData",
  335.                            "ct_cmd_alloc failed");
  336.     case CS_BUSY:
  337.         throw CDB_ClientEx(eDB_Fatal, 110002, "CTL_Connection::SendData",
  338.                            "the connection is busy");
  339.     }
  340.     if (ct_command(cmd, CS_SEND_DATA_CMD, 0, CS_UNUSED, CS_COLUMN_DATA)
  341.         != CS_SUCCEED) {
  342.         ct_cmd_drop(cmd);
  343.         throw CDB_ClientEx(eDB_Fatal, 110031, "CTL_Connection::SendData",
  344.                            "ct_command failed");
  345.     }
  346.     CTL_ITDescriptor& desc = p_desc ?
  347.         dynamic_cast<CTL_ITDescriptor&> (*p_desc) : 
  348.             dynamic_cast<CTL_ITDescriptor&> (descr_in);
  349.     // desc->m_Desc.datatype = CS_TEXT_TYPE;
  350.     desc.m_Desc.total_txtlen  = size;
  351.     desc.m_Desc.log_on_update = log_it ? CS_TRUE : CS_FALSE;
  352.     if (ct_data_info(cmd, CS_SET, CS_UNUSED, &desc.m_Desc) != CS_SUCCEED) {
  353.         ct_cancel(0, cmd, CS_CANCEL_ALL);
  354.         ct_cmd_drop(cmd);
  355.         return false;
  356.     }
  357.     while (size > 0) {
  358.         char   buff[1800];
  359.         CS_INT n_read = (CS_INT) img.Read(buff, sizeof(buff));
  360.         if ( !n_read ) {
  361.             ct_cancel(0, cmd, CS_CANCEL_ALL);
  362.             ct_cmd_drop(cmd);
  363.             throw CDB_ClientEx(eDB_Fatal, 110032, "CTL_Connection::SendData",
  364.                                "Text/Image data corrupted");
  365.         }
  366.         if (ct_send_data(cmd, buff, n_read) != CS_SUCCEED) {
  367.             ct_cancel(0, cmd, CS_CANCEL_CURRENT);
  368.             ct_cmd_drop(cmd);
  369.             throw CDB_ClientEx(eDB_Fatal, 110033, "CTL_Connection::SendData",
  370.                                "ct_send_data failed");
  371.         }
  372.         size -= n_read;
  373.     }
  374.     if (ct_send(cmd) != CS_SUCCEED) {
  375.         ct_cancel(0, cmd, CS_CANCEL_CURRENT);
  376.         ct_cmd_drop(cmd);
  377.         throw CDB_ClientEx(eDB_Fatal, 110034, "CTL_Connection::SendData",
  378.                            "ct_send failed");
  379.     }
  380.     for (;;) {
  381.         CS_INT res_type;
  382.         switch ( ct_results(cmd, &res_type) ) {
  383.         case CS_SUCCEED: {
  384.             if(m_ResProc) {
  385.                 I_Result* res= 0;
  386.                 switch (res_type) {
  387.                 case CS_ROW_RESULT:
  388.                     res = new CTL_RowResult(cmd);
  389.                     break;
  390.                 case CS_PARAM_RESULT:
  391.                     res = new CTL_ParamResult(cmd);
  392.                     break;
  393.                 case CS_COMPUTE_RESULT:
  394.                     res = new CTL_ComputeResult(cmd);
  395.                     break;
  396.                 case CS_STATUS_RESULT:
  397.                     res = new CTL_StatusResult(cmd);
  398.                     break;
  399.                 }
  400.                 if(res) {
  401.                     CDB_Result* dbres= Create_Result(*res);
  402.                     m_ResProc->ProcessResult(*dbres);
  403.                     delete dbres;
  404.                     delete res;
  405.                     continue;
  406.                 }
  407.             }
  408.                     
  409.             switch (res_type) {
  410.             case CS_COMPUTE_RESULT:
  411.             case CS_CURSOR_RESULT:
  412.             case CS_PARAM_RESULT:
  413.             case CS_ROW_RESULT:
  414.             case CS_STATUS_RESULT: {
  415.                 CS_RETCODE ret_code;
  416.                 while ((ret_code = ct_fetch(cmd, CS_UNUSED, CS_UNUSED,
  417.                                             CS_UNUSED, 0)) == CS_SUCCEED) {
  418.                     continue;
  419.                 }
  420.                 if (ret_code != CS_END_DATA) {
  421.                     ct_cmd_drop(cmd);
  422.                     throw CDB_ClientEx(eDB_Fatal, 110036,
  423.                                        "CTL_Connection::SendData",
  424.                                        "ct_fetch failed");
  425.                 }
  426.                 break;
  427.             }
  428.             case CS_CMD_FAIL:
  429.                 ct_cmd_drop(cmd);
  430.                 throw CDB_ClientEx(eDB_Error, 110037,
  431.                                    "CTL_Connection::SendData",
  432.                                    "command failed");
  433.             default:
  434.                 break;
  435.             }
  436.             continue;
  437.         }
  438.         case CS_END_RESULTS: {
  439.             ct_cmd_drop(cmd);
  440.             return true;
  441.         }
  442.         default: {
  443.             if (ct_cancel(0, cmd, CS_CANCEL_ALL) != CS_SUCCEED) {
  444.                 // we need to close this connection
  445.                 ct_cmd_drop(cmd);
  446.                 throw CDB_ClientEx(eDB_Fatal, 110033,
  447.                                    "CTL_Connection::SendData",
  448.                                    "Unrecoverable crash of ct_result. "
  449.                                    "Connection must be closed");
  450.             }
  451.             ct_cmd_drop(cmd);
  452.             throw CDB_ClientEx(eDB_Error, 110034, "CTL_Connection::SendData",
  453.                                "ct_result failed");
  454.         }
  455.         }
  456.     }
  457. }
  458. I_ITDescriptor* CTL_Connection::x_GetNativeITDescriptor
  459. (const CDB_ITDescriptor& descr_in)
  460. {
  461.     string q= "set rowcount 1nupdate ";
  462.     q+= descr_in.TableName();
  463.     q+= " set ";
  464.     q+= descr_in.ColumnName();
  465.     q+= "=NULL where ";
  466.     q+= descr_in.SearchConditions();
  467.     q+= " nselect ";
  468.     q+= descr_in.ColumnName();
  469.     q+= " from ";
  470.     q+= descr_in.TableName();
  471.     q+= " where ";
  472.     q+= descr_in.SearchConditions();
  473.     q+= " nset rowcount 0";
  474.     
  475.     CDB_LangCmd* lcmd= LangCmd(q, 0);
  476.     if(!lcmd->Send()) {
  477.         throw CDB_ClientEx(eDB_Error, 110035, "CTL_Connection::SendData",
  478.                            "can not send the language command");
  479.     }
  480.     CDB_Result* res;
  481.     I_ITDescriptor* descr= 0;
  482.     while(lcmd->HasMoreResults()) {
  483.         res= lcmd->Result();
  484.         if(res == 0) continue;
  485.         if((res->ResultType() == eDB_RowResult) && (descr == 0)) {
  486.             while(res->Fetch()) {
  487.                 //res->ReadItem(&i, 0);
  488.                 descr= res->GetImageOrTextDescriptor();
  489.                 if(descr) break;
  490.             }
  491.         }
  492.         delete res;
  493.     }
  494.     delete lcmd;
  495.     return descr;
  496. }
  497. /////////////////////////////////////////////////////////////////////////////
  498. //
  499. //  CTL_SendDataCmd::
  500. //
  501. CTL_SendDataCmd::CTL_SendDataCmd(CTL_Connection* con, CS_COMMAND* cmd,
  502.                                  size_t nof_bytes)
  503. {
  504.     m_Connect  = con;
  505.     m_Cmd      = cmd;
  506.     m_Bytes2go = nof_bytes;
  507. }
  508. size_t CTL_SendDataCmd::SendChunk(const void* pChunk, size_t nof_bytes)
  509. {
  510.     if (!pChunk  ||  !nof_bytes) {
  511.         throw CDB_ClientEx(eDB_Fatal, 190000, "CTL_SendDataCmd::SendChunk",
  512.                            "wrong (zero) arguments");
  513.     }
  514.     if ( !m_Bytes2go )
  515.         return 0;
  516.     if (nof_bytes > m_Bytes2go)
  517.         nof_bytes = m_Bytes2go;
  518.     if (ct_send_data(m_Cmd, (void*) pChunk, (CS_INT) nof_bytes) != CS_SUCCEED){
  519.         throw CDB_ClientEx(eDB_Fatal, 190001, "CTL_SendDataCmd::SendChunk",
  520.                            "ct_send_data failed");
  521.     }
  522.     m_Bytes2go -= nof_bytes;
  523.     if ( m_Bytes2go )
  524.         return nof_bytes;
  525.     if (ct_send(m_Cmd) != CS_SUCCEED) {
  526.         ct_cancel(0, m_Cmd, CS_CANCEL_CURRENT);
  527.         throw CDB_ClientEx(eDB_Fatal, 190004, "CTL_SendDataCmd::SendChunk",
  528.                            "ct_send failed");
  529.     }
  530.     for (;;) {
  531.         CS_INT res_type;
  532.         switch ( ct_results(m_Cmd, &res_type) ) {
  533.         case CS_SUCCEED: {
  534.             if(m_Connect->m_ResProc) {
  535.                 I_Result* res= 0;
  536.                 switch (res_type) {
  537.                 case CS_ROW_RESULT:
  538.                     res = new CTL_RowResult(m_Cmd);
  539.                     break;
  540.                 case CS_PARAM_RESULT:
  541.                     res = new CTL_ParamResult(m_Cmd);
  542.                     break;
  543.                 case CS_COMPUTE_RESULT:
  544.                     res = new CTL_ComputeResult(m_Cmd);
  545.                     break;
  546.                 case CS_STATUS_RESULT:
  547.                     res = new CTL_StatusResult(m_Cmd);
  548.                     break;
  549.                 }
  550.                 if(res) {
  551.                     CDB_Result* dbres= Create_Result(*res);
  552.                     m_Connect->m_ResProc->ProcessResult(*dbres);
  553.                     delete dbres;
  554.                     delete res;
  555.                     continue;
  556.                 }
  557.             }
  558.             switch ( res_type ) {
  559.             case CS_COMPUTE_RESULT:
  560.             case CS_CURSOR_RESULT:
  561.             case CS_PARAM_RESULT:
  562.             case CS_ROW_RESULT:
  563.             case CS_STATUS_RESULT: {
  564.                 CS_RETCODE ret_code;
  565.                 while ((ret_code = ct_fetch(m_Cmd, CS_UNUSED, CS_UNUSED,
  566.                                             CS_UNUSED, 0)) == CS_SUCCEED);
  567.                 if (ret_code != CS_END_DATA) {
  568.                     throw CDB_ClientEx(eDB_Fatal, 190006,
  569.                                        "CTL_SendDataCmd::SendChunk",
  570.                                        "ct_fetch failed");
  571.                 }
  572.                 break;
  573.             }
  574.             case CS_CMD_FAIL: {
  575.                 ct_cancel(NULL, m_Cmd, CS_CANCEL_ALL);
  576.                 throw CDB_ClientEx(eDB_Error, 190007,
  577.                                    "CTL_SendDataCmd::SendChunk",
  578.                                    "command failed");
  579.             }
  580.             default: {
  581.                 break;
  582.             }
  583.             }
  584.             continue;
  585.         }
  586.         case CS_END_RESULTS: {
  587.             return nof_bytes;
  588.         }
  589.         default: {
  590.             if (ct_cancel(0, m_Cmd, CS_CANCEL_ALL) != CS_SUCCEED) {
  591.                 throw CDB_ClientEx(eDB_Fatal, 190002,
  592.                                    "CTL_SendDataCmd::SendChunk",
  593.                                    "Unrecoverable crash of ct_result. "
  594.                                    "Connection must be closed");
  595.             }
  596.             throw CDB_ClientEx(eDB_Error, 190003, "CTL_SendDataCmd::SendChunk",
  597.                                "ct_result failed");
  598.         }
  599.         }
  600.     }
  601. }
  602. void CTL_SendDataCmd::Release()
  603. {
  604.     m_BR = 0;
  605.     if ( m_Bytes2go ) {
  606.         ct_cancel(0, m_Cmd, CS_CANCEL_ALL);
  607.         m_Bytes2go = 0;
  608.     }
  609.     m_Connect->DropCmd(*this);
  610.     delete this;
  611. }
  612. CTL_SendDataCmd::~CTL_SendDataCmd()
  613. {
  614.     if ( m_Bytes2go )
  615.         ct_cancel(0, m_Cmd, CS_CANCEL_ALL);
  616.     if ( m_BR )
  617.         *m_BR = 0;
  618.     ct_cmd_drop(m_Cmd);
  619. }
  620. END_NCBI_SCOPE
  621. /*
  622.  * ===========================================================================
  623.  * $Log: connection.cpp,v $
  624.  * Revision 1000.1  2004/06/01 19:19:34  gouriano
  625.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.17
  626.  *
  627.  * Revision 1.17  2004/05/17 21:12:03  gorelenk
  628.  * Added include of PCH ncbi_pch.hpp
  629.  *
  630.  * Revision 1.16  2003/09/23 19:38:22  soussov
  631.  * cancels send_data cmd if it failes while processing results
  632.  *
  633.  * Revision 1.15  2003/07/08 18:51:38  soussov
  634.  * fixed bug in constructor
  635.  *
  636.  * Revision 1.14  2003/06/05 16:00:31  soussov
  637.  * adds code for DumpResults and for the dumped results processing
  638.  *
  639.  * Revision 1.13  2003/02/05 14:56:22  dicuccio
  640.  * Fixed uninitialized read reported by valgrind.
  641.  *
  642.  * Revision 1.12  2003/01/31 16:49:38  lavr
  643.  * Remove unused variable "e" from catch() clause
  644.  *
  645.  * Revision 1.11  2002/12/16 16:17:25  soussov
  646.  * ct_con_props returns an outlen == strlen(x)+1. Adaptin to this feature
  647.  *
  648.  * Revision 1.10  2002/09/16 15:10:23  soussov
  649.  * add try catch when canceling active commands in Refresh method
  650.  *
  651.  * Revision 1.9  2002/03/27 05:01:58  vakatov
  652.  * Minor formal fixes
  653.  *
  654.  * Revision 1.8  2002/03/26 15:34:37  soussov
  655.  * new image/text operations added
  656.  *
  657.  * Revision 1.7  2002/02/01 21:49:37  soussov
  658.  * ct_cmd_drop for the CTL_Connection::SendData added
  659.  *
  660.  * Revision 1.6  2001/11/06 17:59:55  lavr
  661.  * Formatted uniformly as the rest of the library
  662.  *
  663.  * Revision 1.5  2001/10/12 21:21:00  lavr
  664.  * Faster checks against zero for unsigned ints
  665.  *
  666.  * Revision 1.4  2001/09/27 20:08:33  vakatov
  667.  * Added "DB_" (or "I_") prefix where it was missing
  668.  *
  669.  * Revision 1.3  2001/09/27 15:42:09  soussov
  670.  * CTL_Connection::Release() added
  671.  *
  672.  * Revision 1.2  2001/09/25 15:05:43  soussov
  673.  * fixed typo in CTL_SendDataCmd::SendChunk
  674.  *
  675.  * Revision 1.1  2001/09/21 23:40:02  vakatov
  676.  * -----  Initial (draft) revision.  -----
  677.  * This is a major revamp (by Denis Vakatov, with help from Vladimir Soussov)
  678.  * of the DBAPI "driver" libs originally written by Vladimir Soussov.
  679.  * The revamp involved massive code shuffling and grooming, numerous local
  680.  * API redesigns, adding comments and incorporating DBAPI to the C++ Toolkit.
  681.  *
  682.  * ===========================================================================
  683.  */