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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: context.cpp,v $
  4.  * PRODUCTION Revision 1000.5  2004/06/01 19:19:38  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.32
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: context.cpp,v 1000.5 2004/06/01 19:19:38 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:  Driver for CTLib server
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <dbapi/driver/ctlib/interfaces.hpp>
  41. #include <dbapi/driver/util/numeric_convert.hpp>
  42. #if defined(NCBI_OS_MSWIN)
  43. #  include <winsock.h>
  44. #else
  45. #  include <unistd.h>
  46. #endif
  47. BEGIN_NCBI_SCOPE
  48. /////////////////////////////////////////////////////////////////////////////
  49. //
  50. //  CTLibContext::
  51. //
  52. CS_START_EXTERN_C
  53.     CS_RETCODE CS_PUBLIC s_CTLIB_cserr_callback(CS_CONTEXT* context, CS_CLIENTMSG* msg)
  54.     {
  55.         return CTLibContext::CTLIB_cserr_handler(context, msg)
  56.             ? CS_SUCCEED : CS_FAIL;
  57.     }
  58.     CS_RETCODE CS_PUBLIC s_CTLIB_cterr_callback(CS_CONTEXT* context, CS_CONNECTION* con,
  59.                                       CS_CLIENTMSG* msg)
  60.     {
  61.         return CTLibContext::CTLIB_cterr_handler(context, con, msg)
  62.             ? CS_SUCCEED : CS_FAIL;
  63.     }
  64.     CS_RETCODE CS_PUBLIC s_CTLIB_srverr_callback(CS_CONTEXT* context, CS_CONNECTION* con,
  65.                                        CS_SERVERMSG* msg)
  66.     {
  67.         return CTLibContext::CTLIB_srverr_handler(context, con, msg)
  68.             ? CS_SUCCEED : CS_FAIL;
  69.     }
  70. CS_END_EXTERN_C
  71. CTLibContext::CTLibContext(bool reuse_context, CS_INT version)
  72. {
  73.     DEFINE_STATIC_FAST_MUTEX(xMutex);
  74.     CFastMutexGuard mg(xMutex);
  75.     m_Context         = 0;
  76.     m_AppName         = "CTLibDriver";
  77.     m_LoginRetryCount = 0;
  78.     m_LoginLoopDelay  = 0;
  79.     m_PacketSize      = 2048;
  80.     CS_RETCODE r = reuse_context ? cs_ctx_global(version, &m_Context) :
  81.         cs_ctx_alloc(version, &m_Context);
  82.     if (r != CS_SUCCEED) {
  83.         m_Context = 0;
  84.         throw CDB_ClientEx(eDB_Fatal, 100001, "CTLibContext::CTLibContext",
  85.                            "Can not allocate a context");
  86.     }
  87.     CS_VOID*     cb;
  88.     CS_INT       outlen;
  89.     CPointerPot* p_pot = 0;
  90.     // check if cs message callback is already installed
  91.     r = cs_config(m_Context, CS_GET, CS_MESSAGE_CB, &cb, CS_UNUSED, &outlen);
  92.     if (r != CS_SUCCEED) {
  93.         m_Context = 0;
  94.         throw CDB_ClientEx(eDB_Error, 100006, "CTLibContext::CTLibContext",
  95.                            "cs_config failed");
  96.     }
  97.     if (cb == (CS_VOID*)  s_CTLIB_cserr_callback) {
  98.         // we did use this context already
  99.         r = cs_config(m_Context, CS_GET, CS_USERDATA,
  100.                       (CS_VOID*) &p_pot, (CS_INT) sizeof(p_pot), &outlen);
  101.         if (r != CS_SUCCEED) {
  102.             m_Context = 0;
  103.             throw CDB_ClientEx(eDB_Error, 100006, "CTLibContext::CTLibContext",
  104.                                "cs_config failed");
  105.         }
  106.     }
  107.     else {
  108.         // this is a brand new context
  109.         r = cs_config(m_Context, CS_SET, CS_MESSAGE_CB,
  110.                       (CS_VOID*) s_CTLIB_cserr_callback, CS_UNUSED, NULL);
  111.         if (r != CS_SUCCEED) {
  112.             cs_ctx_drop(m_Context);
  113.             m_Context = 0;
  114.             throw CDB_ClientEx(eDB_Error, 100005, "CTLibContext::CTLibContext",
  115.                                "Can not install the cslib message callback");
  116.         }
  117.         p_pot = new CPointerPot;
  118.         r = cs_config(m_Context, CS_SET, CS_USERDATA,
  119.                       (CS_VOID*) &p_pot, (CS_INT) sizeof(p_pot), NULL);
  120.         if (r != CS_SUCCEED) {
  121.             cs_ctx_drop(m_Context);
  122.             m_Context = 0;
  123.             delete p_pot;
  124.             throw CDB_ClientEx(eDB_Error, 100007, "CTLibContext::CTLibContext",
  125.                                "Can not install the user data");
  126.         }
  127.         r = ct_init(m_Context, version);
  128.         if (r != CS_SUCCEED) {
  129.             cs_ctx_drop(m_Context);
  130.             m_Context = 0;
  131.             delete p_pot;   
  132.             throw CDB_ClientEx(eDB_Error, 100002, "CTLibContext::CTLibContext",
  133.                                "ct_init failed");
  134.         }
  135.         r = ct_callback(m_Context, NULL, CS_SET, CS_CLIENTMSG_CB,
  136.                         (CS_VOID*) s_CTLIB_cterr_callback);
  137.         if (r != CS_SUCCEED) {
  138.             ct_exit(m_Context, CS_FORCE_EXIT);
  139.             cs_ctx_drop(m_Context);
  140.             m_Context = 0;
  141.             delete p_pot;           
  142.             throw CDB_ClientEx(eDB_Error, 100003, "CTLibContext::CTLibContext",
  143.                                "Can not install the client message callback");
  144.         }
  145.         r = ct_callback(m_Context, NULL, CS_SET, CS_SERVERMSG_CB,
  146.                         (CS_VOID*) s_CTLIB_srverr_callback);
  147.         if (r != CS_SUCCEED) {
  148.             ct_exit(m_Context, CS_FORCE_EXIT);
  149.             cs_ctx_drop(m_Context);
  150.             m_Context = 0;
  151.             delete p_pot;           
  152.             throw CDB_ClientEx(eDB_Error, 100004, "CTLibContext::CTLibContext",
  153.                                "Can not install the server message callback");
  154.         }
  155.     }
  156.     if ( p_pot ) {
  157.         p_pot->Add((TPotItem) this);
  158.     }
  159. }
  160. bool CTLibContext::SetLoginTimeout(unsigned int nof_secs)
  161. {
  162.     CS_INT t_out = (CS_INT) nof_secs;
  163.     return ct_config(m_Context, CS_SET,
  164.                      CS_LOGIN_TIMEOUT, &t_out, CS_UNUSED, NULL) == CS_SUCCEED;
  165. }
  166. bool CTLibContext::SetTimeout(unsigned int nof_secs)
  167. {
  168.     CS_INT t_out = (CS_INT) nof_secs;
  169.     return ct_config(m_Context, CS_SET,
  170.                      CS_TIMEOUT, &t_out, CS_UNUSED, NULL) == CS_SUCCEED;
  171. }
  172. bool CTLibContext::SetMaxTextImageSize(size_t nof_bytes)
  173. {
  174.     CS_INT ti_size = (CS_INT) nof_bytes;
  175.     return ct_config(m_Context, CS_SET,
  176.                      CS_TEXTLIMIT, &ti_size, CS_UNUSED, NULL) == CS_SUCCEED;
  177. }
  178. CDB_Connection* CTLibContext::Connect(const string&   srv_name,
  179.                                       const string&   user_name,
  180.                                       const string&   passwd,
  181.                                       TConnectionMode mode,
  182.                                       bool            reusable,
  183.                                       const string&   pool_name)
  184. {
  185.     //DEFINE_STATIC_FAST_MUTEX(xMutex);
  186.     // CFastMutexGuard mg(xMutex);
  187.     CFastMutexGuard mg(m_Mtx);
  188.     if (reusable  &&  m_NotInUse.NofItems() > 0) {
  189.         // try to get a connection from the pot
  190.         if ( !pool_name.empty() ) {
  191.             // use a pool name
  192.             for (int i = m_NotInUse.NofItems();  i--; ) {
  193.                 CTL_Connection* t_con
  194.                     = static_cast<CTL_Connection*> (m_NotInUse.Get(i));
  195.                 if (pool_name.compare(t_con->PoolName()) == 0) {
  196.                     m_NotInUse.Remove(i);
  197.                     if(t_con->Refresh()) {
  198.                         m_InUse.Add((TPotItem) t_con);
  199.                         return Create_Connection(*t_con);
  200.                     }
  201.                     delete t_con;
  202.                 }
  203.             }
  204.         }
  205.         else { // using server name as a pool name
  206.             if ( srv_name.empty() )
  207.                 return 0;
  208.             // try to use a server name
  209.             for (int i = m_NotInUse.NofItems();  i--; ) {
  210.                 CTL_Connection* t_con
  211.                     = static_cast<CTL_Connection*> (m_NotInUse.Get(i));
  212.                 if (srv_name.compare(t_con->ServerName()) == 0) {
  213.                     m_NotInUse.Remove(i);
  214.                     if(t_con->Refresh()) {
  215.                         m_InUse.Add((TPotItem) t_con);
  216.                         return Create_Connection(*t_con);
  217.                     }
  218.                     delete t_con;
  219.                 }
  220.             }
  221.         }
  222.     }
  223.     if((mode & fDoNotConnect) != 0) return 0;
  224.     // new connection needed
  225.     if (srv_name.empty()  ||  user_name.empty()  ||  passwd.empty()) {
  226.         throw CDB_ClientEx(eDB_Error, 100010, "CTLibContext::Connect",
  227.                            "You have to provide server name, user name and "
  228.                            "password to connect to the server");
  229.     }
  230.     CS_CONNECTION* con = x_ConnectToServer(srv_name, user_name, passwd, mode);
  231.     if (con == 0) {
  232.         throw CDB_ClientEx(eDB_Error, 100011, "CTLibContext::Connect",
  233.                            "Can not connect to the server");
  234.     }
  235.     CTL_Connection* t_con = new CTL_Connection(this, con, reusable, pool_name);
  236.     t_con->m_MsgHandlers = m_ConnHandlers;
  237.     m_InUse.Add((TPotItem) t_con);
  238.     return Create_Connection(*t_con);
  239. }
  240. bool CTLibContext::IsAbleTo(ECapability cpb) const
  241. {
  242.     switch(cpb) {
  243.     case eBcp:
  244.     case eReturnITDescriptors:
  245.     case eReturnComputeResults:
  246.     return true;
  247.     default:
  248.     break;
  249.     }
  250.     return false;
  251. }
  252. CTLibContext::~CTLibContext()
  253. {
  254.     CFastMutexGuard mg(m_Mtx);
  255.     if ( !m_Context ) {
  256.         return;
  257.     }
  258.     // close all connections first
  259.     for (int i = m_NotInUse.NofItems();  i--; ) {
  260.         CTL_Connection* t_con = static_cast<CTL_Connection*>(m_NotInUse.Get(i));
  261.         delete t_con;
  262.     }
  263.     for (int i = m_InUse.NofItems();  i--; ) {
  264.         CTL_Connection* t_con = static_cast<CTL_Connection*> (m_InUse.Get(i));
  265.         delete t_con;
  266.     }
  267.     CS_INT       outlen;
  268.     CPointerPot* p_pot = 0;
  269.     if (cs_config(m_Context, CS_GET, CS_USERDATA,
  270.                   (void*) &p_pot, (CS_INT) sizeof(p_pot), &outlen) == CS_SUCCEED
  271.         &&  p_pot != 0) {
  272.         p_pot->Remove(this);
  273.         if (p_pot->NofItems() == 0) { // this is a last driver for this context
  274.             delete p_pot;
  275.             if (ct_exit(m_Context, CS_UNUSED) != CS_SUCCEED) {
  276.                 ct_exit(m_Context, CS_FORCE_EXIT);
  277.             }
  278.             cs_ctx_drop(m_Context);
  279.         }
  280.     }
  281. }
  282. void CTLibContext::CTLIB_SetApplicationName(const string& a_name)
  283. {
  284.     m_AppName = a_name;
  285. }
  286. void CTLibContext::CTLIB_SetHostName(const string& host_name)
  287. {
  288.     m_HostName = host_name;
  289. }
  290. void CTLibContext::CTLIB_SetPacketSize(CS_INT packet_size)
  291. {
  292.     m_PacketSize = packet_size;
  293. }
  294. void CTLibContext::CTLIB_SetLoginRetryCount(CS_INT n)
  295. {
  296.     m_LoginRetryCount = n;
  297. }
  298. void CTLibContext::CTLIB_SetLoginLoopDelay(CS_INT nof_sec)
  299. {
  300.     m_LoginLoopDelay = nof_sec;
  301. }
  302. CS_CONTEXT* CTLibContext::CTLIB_GetContext() const
  303. {
  304.     return m_Context;
  305. }
  306. bool CTLibContext::CTLIB_cserr_handler(CS_CONTEXT* context, CS_CLIENTMSG* msg)
  307. {
  308.     CS_INT       outlen;
  309.     CPointerPot* p_pot = 0;
  310.     CS_RETCODE   r;
  311.     r = cs_config(context, CS_GET, CS_USERDATA,
  312.                   (void*) &p_pot, (CS_INT) sizeof(p_pot), &outlen);
  313.     if (r == CS_SUCCEED  &&  p_pot != 0  &&  p_pot->NofItems() > 0) {
  314.         CTLibContext* drv = (CTLibContext*) p_pot->Get(0);
  315.         EDB_Severity sev = eDB_Error;
  316.         if (msg->severity == CS_SV_INFORM) {
  317.             sev = eDB_Info;
  318.         }
  319.         else if (msg->severity == CS_SV_FATAL) {
  320.             sev = eDB_Fatal;
  321.         }
  322.         CDB_ClientEx ex(sev, msg->msgnumber, "cslib", msg->msgstring);
  323.         drv->m_CntxHandlers.PostMsg(&ex);
  324.     }
  325.     else if (msg->severity != CS_SV_INFORM) {
  326.         // nobody can be informed, so put it to stderr
  327.         cerr << "CSLIB error handler detects the following error" << endl
  328.              << msg->msgstring << endl;
  329.     }
  330.     return true;
  331. }
  332. bool CTLibContext::CTLIB_cterr_handler(CS_CONTEXT* context, CS_CONNECTION* con,
  333.                                        CS_CLIENTMSG* msg)
  334. {
  335.     CS_INT           outlen;
  336.     CPointerPot*        p_pot = 0;
  337.     CTL_Connection*  link = 0;
  338.     CDBHandlerStack* hs;
  339.     if (con != 0  &&
  340.         ct_con_props(con, CS_GET, CS_USERDATA,
  341.                      (void*) &link, (CS_INT) sizeof(link),
  342.                      &outlen) == CS_SUCCEED  &&  link != 0) {
  343.         hs = &link->m_MsgHandlers;
  344.     }
  345.     else if (cs_config(context, CS_GET, CS_USERDATA,
  346.                        (void*) &p_pot, (CS_INT) sizeof(p_pot),
  347.                        &outlen) == CS_SUCCEED  &&
  348.              p_pot != 0  &&  p_pot->NofItems() > 0) {
  349.         CTLibContext* drv = (CTLibContext*) p_pot->Get(0);
  350.         hs = &drv->m_CntxHandlers;
  351.     }
  352.     else {
  353.         if (msg->severity != CS_SV_INFORM) {
  354.             // nobody can be informed, let's put it in stderr
  355.             cerr << "CTLIB error handler detects the following error" << endl
  356.                  << "Severity:" << msg->severity
  357.                  << " Msg # " << msg->msgnumber << endl
  358.                  << msg->msgstring << endl;
  359.             if (msg->osstringlen > 1) {
  360.                 cerr << "OS # "    << msg->osnumber
  361.                      << " OS msg " << msg->osstring << endl;
  362.             }
  363.             if (msg->sqlstatelen > 1  &&
  364.                 (msg->sqlstate[0] != 'Z'  ||  msg->sqlstate[1] != 'Z')) {
  365.                 cerr << "SQL: " << msg->sqlstate << endl;
  366.             }
  367.         }
  368.         return true;
  369.     }
  370.     switch (msg->severity) {
  371.     case CS_SV_INFORM: {
  372.         CDB_ClientEx info(eDB_Info,
  373.                           (int) msg->msgnumber, "ctlib", msg->msgstring);
  374.         hs->PostMsg(&info);
  375.         break;
  376.     }
  377.     case CS_SV_RETRY_FAIL: {
  378.         CDB_TimeoutEx to((int) msg->msgnumber, "ctlib", msg->msgstring);
  379.         hs->PostMsg(&to);
  380. if(con) {
  381.   CS_INT status;
  382.   if((ct_con_props(con, CS_GET, CS_LOGIN_STATUS, (CS_VOID*)&status, CS_UNUSED, NULL) != CS_SUCCEED) ||
  383.    (!status)) return false;
  384.   if(ct_cancel(con, (CS_COMMAND*)0, CS_CANCEL_ATTN) != CS_SUCCEED) return false;
  385. }
  386. else return false;
  387. break;
  388.     }
  389.     case CS_SV_CONFIG_FAIL:
  390.     case CS_SV_API_FAIL:
  391.     case CS_SV_INTERNAL_FAIL: {
  392.         CDB_ClientEx err(eDB_Error,
  393.                          (int) msg->msgnumber, "ctlib", msg->msgstring);
  394.         hs->PostMsg(&err);
  395.         break;
  396.     }
  397.     default: {
  398.         CDB_ClientEx ftl(eDB_Fatal,
  399.                          (int) msg->msgnumber, "ctlib", msg->msgstring);
  400.         hs->PostMsg(&ftl);
  401.         break;
  402.     }
  403.     }
  404.     return true;
  405. }
  406. bool CTLibContext::CTLIB_srverr_handler(CS_CONTEXT* context,
  407.                                         CS_CONNECTION* con,
  408.                                         CS_SERVERMSG* msg)
  409. {
  410.     if ((msg->severity == 0  &&  msg->msgnumber == 0)  ||
  411.         msg->msgnumber == 5701  ||  msg->msgnumber == 5703) {
  412.         return true;
  413.     }
  414.     CS_INT           outlen;
  415.     CPointerPot*     p_pot = 0;
  416.     CTL_Connection*  link = 0;
  417.     CDBHandlerStack* hs;
  418.     if (con != 0  &&  ct_con_props(con, CS_GET, CS_USERDATA,
  419.                                    (void*) &link, (CS_INT) sizeof(link),
  420.                                    &outlen) == CS_SUCCEED  &&
  421.         link != 0) {
  422.         hs = &link->m_MsgHandlers;
  423.     }
  424.     else if (cs_config(context, CS_GET, CS_USERDATA,
  425.                        (void*) &p_pot, (CS_INT) sizeof(p_pot),
  426.                        &outlen) == CS_SUCCEED  &&
  427.              p_pot != 0  &&  p_pot->NofItems() > 0) {
  428.         CTLibContext* drv = (CTLibContext*) p_pot->Get(0);
  429.         hs = &drv->m_CntxHandlers;
  430.     }
  431.     else {
  432.         cerr << "Message from the server ";
  433.         if (msg->svrnlen > 0) {
  434.             cerr << "<" << msg->svrname << "> ";
  435.         }
  436.         cerr << "msg # " << msg->msgnumber
  437.              << " severity: " << msg->severity << endl;
  438.         if (msg->proclen > 0) {
  439.             cerr << "Proc: " << msg->proc << " line: " << msg->line << endl;
  440.         }
  441.         if (msg->sqlstatelen > 1  &&
  442.             (msg->sqlstate[0] != 'Z'  ||  msg->sqlstate[1] != 'Z')) {
  443.             cerr << "SQL: " << msg->sqlstate << endl;
  444.         }
  445.         cerr << msg->text << endl;
  446.         return true;
  447.     }
  448.     if (msg->msgnumber == 1205 /*DEADLOCK*/) {
  449.         CDB_DeadlockEx dl(msg->svrname, msg->text);
  450.         hs->PostMsg(&dl);
  451.     }
  452.     else {
  453.         EDB_Severity sev =
  454.             msg->severity <  10 ? eDB_Info :
  455.             msg->severity == 10 ? eDB_Warning :
  456.             msg->severity <  16 ? eDB_Error :
  457.             msg->severity >  16 ? eDB_Fatal :
  458.             eDB_Unknown;
  459.         if (msg->proclen > 0) {
  460.             CDB_RPCEx rpc(sev, (int) msg->msgnumber, msg->svrname, msg->text,
  461.                           msg->proc, (int) msg->line);
  462.             hs->PostMsg(&rpc);
  463.         }
  464.         else if (msg->sqlstatelen > 1  &&
  465.                  (msg->sqlstate[0] != 'Z'  ||  msg->sqlstate[1] != 'Z')) {
  466.             CDB_SQLEx sql(sev, (int) msg->msgnumber, msg->svrname, msg->text,
  467.                           (const char*) msg->sqlstate, (int) msg->line);
  468.             hs->PostMsg(&sql);
  469.         }
  470.         else {
  471.             CDB_DSEx m(sev, (int) msg->msgnumber, msg->svrname, msg->text);
  472.             hs->PostMsg(&m);
  473.         }
  474.     }
  475.     return true;
  476. }
  477. CS_CONNECTION* CTLibContext::x_ConnectToServer(const string&   srv_name,
  478.                                                const string&   user_name,
  479.                                                const string&   passwd,
  480.                                                TConnectionMode mode)
  481. {
  482.     CS_CONNECTION* con;
  483.     if (ct_con_alloc(m_Context, &con) != CS_SUCCEED)
  484.         return 0;
  485.     ct_callback(NULL, con, CS_SET, CS_CLIENTMSG_CB,
  486.                 (CS_VOID*) s_CTLIB_cterr_callback);
  487.     
  488.     ct_callback(NULL, con, CS_SET, CS_SERVERMSG_CB,
  489.                 (CS_VOID*) s_CTLIB_srverr_callback);
  490.     char hostname[256];
  491.     if(gethostname(hostname, 256)) {
  492.       strcpy(hostname, "UNKNOWN");
  493.     }
  494.     else hostname[255]= '';
  495.     
  496.     if (ct_con_props(con, CS_SET, CS_USERNAME, (void*) user_name.c_str(),
  497.                      CS_NULLTERM, NULL) != CS_SUCCEED  ||
  498.         ct_con_props(con, CS_SET, CS_PASSWORD, (void*) passwd.c_str(),
  499.                      CS_NULLTERM, NULL) != CS_SUCCEED  ||
  500.         ct_con_props(con, CS_SET, CS_APPNAME, (void*) m_AppName.c_str(),
  501.                      CS_NULLTERM, NULL) != CS_SUCCEED ||
  502.         ct_con_props(con, CS_SET, CS_HOSTNAME, (void*) hostname,
  503.                      CS_NULLTERM, NULL) != CS_SUCCEED) {
  504.         ct_con_drop(con);
  505.         return 0;
  506.     }
  507.     if ( !m_HostName.empty() ) {
  508.         ct_con_props(con, CS_SET, CS_HOSTNAME,
  509.                      (void*) m_HostName.c_str(), CS_NULLTERM, NULL);
  510.     }
  511.     if (m_PacketSize > 0) {
  512.         ct_con_props(con, CS_SET, CS_PACKETSIZE,
  513.                      (void*) &m_PacketSize, CS_UNUSED, NULL);
  514.     }
  515.     if (m_LoginRetryCount > 0) {
  516.         ct_con_props(con, CS_SET, CS_RETRY_COUNT,
  517.                      (void*) &m_LoginRetryCount, CS_UNUSED, NULL);
  518.     }
  519.     if (m_LoginLoopDelay > 0) {
  520.         ct_con_props(con, CS_SET, CS_LOOP_DELAY,
  521.                      (void*) &m_LoginLoopDelay, CS_UNUSED, NULL);
  522.     }
  523.     CS_BOOL flag = CS_TRUE;
  524.     if ((mode & fBcpIn) != 0) {
  525.         ct_con_props(con, CS_SET, CS_BULK_LOGIN, &flag, CS_UNUSED, NULL);
  526.     }
  527.     if ((mode & fPasswordEncrypted) != 0) {
  528.         ct_con_props(con, CS_SET, CS_SEC_ENCRYPTION, &flag, CS_UNUSED, NULL);
  529.     }
  530.     if (ct_connect(con, const_cast<char*> (srv_name.c_str()), CS_NULLTERM)
  531.         != CS_SUCCEED) {
  532.         ct_con_drop(con);
  533.         return 0;
  534.     }
  535.     return con;
  536. }
  537. /////////////////////////////////////////////////////////////////////////////
  538. //
  539. //  Miscellaneous
  540. //
  541. void g_CTLIB_GetRowCount(CS_COMMAND* cmd, int* cnt)
  542. {
  543.     CS_INT n;
  544.     CS_INT outlen;
  545.     if (cnt  &&
  546.         ct_res_info(cmd, CS_ROW_COUNT, &n, CS_UNUSED, &outlen) == CS_SUCCEED
  547.         && n >= 0  &&  n != CS_NO_COUNT) {
  548.         *cnt = (int) n;
  549.     }
  550. }
  551. bool g_CTLIB_AssignCmdParam(CS_COMMAND*   cmd,
  552.                             CDB_Object&   param,
  553.                             const string& param_name,
  554.                             CS_DATAFMT&   param_fmt,
  555.                             CS_SMALLINT   indicator,
  556.                             bool          declare_only)
  557. {
  558.     {{
  559.         size_t l = param_name.copy(param_fmt.name, CS_MAX_NAME-1);
  560.         param_fmt.name[l] = '';
  561.     }}
  562.     CS_RETCODE ret_code;
  563.     switch ( param.GetType() ) {
  564.     case eDB_Int: {
  565.         CDB_Int& par = dynamic_cast<CDB_Int&> (param);
  566.         param_fmt.datatype = CS_INT_TYPE;
  567.         if ( declare_only )
  568.             break;
  569.         CS_INT value = (CS_INT) par.Value();
  570.         ret_code = ct_param(cmd, &param_fmt,
  571.                             (CS_VOID*) &value, CS_UNUSED, indicator);
  572.         break;
  573.     }
  574.     case eDB_SmallInt: {
  575.         CDB_SmallInt& par = dynamic_cast<CDB_SmallInt&> (param);
  576.         param_fmt.datatype = CS_SMALLINT_TYPE;
  577.         if ( declare_only )
  578.             break;
  579.         CS_SMALLINT value = (CS_SMALLINT) par.Value();
  580.         ret_code = ct_param(cmd, &param_fmt,
  581.                             (CS_VOID*) &value, CS_UNUSED, indicator);
  582.         break;
  583.     }
  584.     case eDB_TinyInt: {
  585.         CDB_TinyInt& par = dynamic_cast<CDB_TinyInt&> (param);
  586.         param_fmt.datatype = CS_TINYINT_TYPE;
  587.         if ( declare_only )
  588.             break;
  589.         CS_TINYINT value = (CS_TINYINT) par.Value();
  590.         ret_code = ct_param(cmd, &param_fmt,
  591.                             (CS_VOID*) &value, CS_UNUSED, indicator);
  592.         break;
  593.     }
  594.     case eDB_Bit: {
  595.         CDB_Bit& par = dynamic_cast<CDB_Bit&> (param);
  596.         param_fmt.datatype = CS_BIT_TYPE;
  597.         if ( declare_only )
  598.             break;
  599.         CS_BIT value = (CS_BIT) par.Value();
  600.         ret_code = ct_param(cmd, &param_fmt,
  601.                             (CS_VOID*) &value, CS_UNUSED, indicator);
  602.         break;
  603.     }
  604.     case eDB_BigInt: {
  605.         CDB_BigInt& par = dynamic_cast<CDB_BigInt&> (param);
  606.         param_fmt.datatype = CS_NUMERIC_TYPE;
  607.         if ( declare_only )
  608.             break;
  609.         CS_NUMERIC value;
  610.         Int8 v8 = par.Value();
  611.         memset(&value, 0, sizeof(value));
  612.         value.precision= 18;
  613.         if (longlong_to_numeric(v8, 18, value.array) == 0)
  614.             return false;
  615.         ret_code = ct_param(cmd, &param_fmt,
  616.                             (CS_VOID*) &value, CS_UNUSED, indicator);
  617.         break;
  618.     }
  619.     case eDB_Char: {
  620.         CDB_Char& par = dynamic_cast<CDB_Char&> (param);
  621.         param_fmt.datatype = CS_CHAR_TYPE;
  622.         if ( declare_only )
  623.             break;
  624.         ret_code = ct_param(cmd, &param_fmt, (CS_VOID*) par.Value(),
  625.                             (CS_INT) par.Size(), indicator);
  626.         break;
  627.     }
  628.     case eDB_LongChar: {
  629.         CDB_LongChar& par = dynamic_cast<CDB_LongChar&> (param);
  630.         param_fmt.datatype = CS_LONGCHAR_TYPE;
  631.         if ( declare_only )
  632.             break;
  633.         ret_code = ct_param(cmd, &param_fmt, (CS_VOID*) par.Value(),
  634.                             (CS_INT) par.Size(), indicator);
  635.         break;
  636.     }
  637.     case eDB_VarChar: {
  638.         CDB_VarChar& par = dynamic_cast<CDB_VarChar&> (param);
  639.         param_fmt.datatype = CS_CHAR_TYPE;
  640.         if ( declare_only )
  641.             break;
  642.         ret_code = ct_param(cmd, &param_fmt, (CS_VOID*) par.Value(),
  643.                             (CS_INT) par.Size(), indicator);
  644.         break;
  645.     }
  646.     case eDB_Binary: {
  647.         CDB_Binary& par = dynamic_cast<CDB_Binary&> (param);
  648.         param_fmt.datatype = CS_BINARY_TYPE;
  649.         if ( declare_only )
  650.             break;
  651.         ret_code = ct_param(cmd, &param_fmt, (CS_VOID*) par.Value(),
  652.                             (CS_INT) par.Size(), indicator);
  653.         break;
  654.     }
  655.     case eDB_LongBinary: {
  656.         CDB_LongBinary& par = dynamic_cast<CDB_LongBinary&> (param);
  657.         param_fmt.datatype = CS_LONGBINARY_TYPE;
  658.         if ( declare_only )
  659.             break;
  660.         ret_code = ct_param(cmd, &param_fmt, (CS_VOID*) par.Value(),
  661.                             (CS_INT) par.Size(), indicator);
  662.         break;
  663.     }
  664.     case eDB_VarBinary: {
  665.         CDB_VarBinary& par = dynamic_cast<CDB_VarBinary&> (param);
  666.         param_fmt.datatype = CS_BINARY_TYPE;
  667.         if ( declare_only )
  668.             break;
  669.         ret_code = ct_param(cmd, &param_fmt, (CS_VOID*) par.Value(),
  670.                             (CS_INT) par.Size(), indicator);
  671.         break;
  672.     }
  673.     case eDB_Float: {
  674.         CDB_Float& par = dynamic_cast<CDB_Float&> (param);
  675.         param_fmt.datatype = CS_REAL_TYPE;
  676.         if ( declare_only )
  677.             break;
  678.         CS_REAL value = (CS_REAL) par.Value();
  679.         ret_code = ct_param(cmd, &param_fmt,
  680.                             (CS_VOID*) &value, CS_UNUSED, indicator);
  681.         break;
  682.     }
  683.     case eDB_Double: {
  684.         CDB_Double& par = dynamic_cast<CDB_Double&> (param);
  685.         param_fmt.datatype = CS_FLOAT_TYPE;
  686.         if ( declare_only )
  687.             break;
  688.         CS_FLOAT value = (CS_FLOAT) par.Value();
  689.         ret_code = ct_param(cmd, &param_fmt,
  690.                             (CS_VOID*) &value, CS_UNUSED, indicator);
  691.         break;
  692.     }
  693.     case eDB_SmallDateTime: {
  694.         CDB_SmallDateTime& par = dynamic_cast<CDB_SmallDateTime&> (param);
  695.         param_fmt.datatype = CS_DATETIME4_TYPE;
  696.         if ( declare_only )
  697.             break;
  698.         CS_DATETIME4 dt;
  699.         dt.days    = par.GetDays();
  700.         dt.minutes = par.GetMinutes();
  701.         ret_code = ct_param(cmd, &param_fmt,
  702.                             (CS_VOID*) &dt, CS_UNUSED, indicator);
  703.         break;
  704.     }
  705.     case eDB_DateTime: {
  706.         CDB_DateTime& par = dynamic_cast<CDB_DateTime&> (param);
  707.         param_fmt.datatype = CS_DATETIME_TYPE;
  708.         if ( declare_only )
  709.             break;
  710.         CS_DATETIME dt;
  711.         dt.dtdays = par.GetDays();
  712.         dt.dttime = par.Get300Secs();
  713.         ret_code = ct_param(cmd, &param_fmt,
  714.                             (CS_VOID*) &dt, CS_UNUSED, indicator);
  715.         break;
  716.     }
  717.     default: {
  718.         return false;
  719.     }
  720.     }
  721.     if ( declare_only ) {
  722.         ret_code = ct_param(cmd, &param_fmt, 0, CS_UNUSED, 0);
  723.     }
  724.     return (ret_code == CS_SUCCEED);
  725. }
  726. ///////////////////////////////////////////////////////////////////////
  727. // Driver manager related functions
  728. //
  729. I_DriverContext* CTLIB_CreateContext(map<string,string>* attr = 0)
  730. {
  731.     bool reuse_context= true;
  732.     CS_INT version= CS_VERSION_110;
  733.     if(attr) {
  734.   reuse_context= (*attr)["reuse_context"] != "false";
  735.   string vers= (*attr)["version"];
  736.   if(vers.find("100") != string::npos) {
  737. version= CS_VERSION_100;
  738.   }
  739.   else {
  740. char* e;
  741. long v= strtol(vers.c_str(), &e, 10);
  742. if (v > 0 && (e == 0 || (!isalpha(*e)))) version= v;
  743.   }
  744. }
  745. CTLibContext* cntx= new CTLibContext(reuse_context, version);
  746. if(cntx && attr) {
  747.   string page_size= (*attr)["packet"];
  748.   if(!page_size.empty()) {
  749. CS_INT s= atoi(page_size.c_str());
  750. cntx->CTLIB_SetPacketSize(s);
  751.   }
  752.      string prog_name= (*attr)["prog_name"];
  753.      if(!prog_name.empty()) {
  754.          cntx->CTLIB_SetApplicationName(prog_name);
  755.      }
  756.      string host_name= (*attr)["host_name"];
  757.      if(!host_name.empty()) {
  758.          cntx->CTLIB_SetHostName(host_name);
  759.      }
  760. }
  761.     return cntx;
  762. }
  763. void DBAPI_RegisterDriver_CTLIB(I_DriverMgr& mgr)
  764. {
  765.     mgr.RegisterDriver("ctlib", CTLIB_CreateContext);
  766. }
  767. extern "C" {
  768.     NCBI_DBAPIDRIVER_CTLIB_EXPORT
  769.     void* DBAPI_E_ctlib()
  770.     {
  771.     return (void*)DBAPI_RegisterDriver_CTLIB;
  772.     }
  773. END_NCBI_SCOPE
  774. /*
  775.  * ===========================================================================
  776.  * $Log: context.cpp,v $
  777.  * Revision 1000.5  2004/06/01 19:19:38  gouriano
  778.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.32
  779.  *
  780.  * Revision 1.32  2004/05/17 21:12:03  gorelenk
  781.  * Added include of PCH ncbi_pch.hpp
  782.  *
  783.  * Revision 1.31  2004/04/07 13:41:47  gorelenk
  784.  * Added export prefix to implementations of DBAPI_E_* functions.
  785.  *
  786.  * Revision 1.30  2003/11/19 22:47:20  soussov
  787.  * adds code to setup client/server msg callbacks for each connection; adds 'prog_name' and 'host_name' attributes for create context
  788.  *
  789.  * Revision 1.29  2003/11/14 20:46:13  soussov
  790.  * implements DoNotConnect mode
  791.  *
  792.  * Revision 1.28  2003/10/29 21:45:54  soussov
  793.  * adds code which prevents repeated timeouts if server is hanging
  794.  *
  795.  * Revision 1.27  2003/10/27 17:00:20  soussov
  796.  * adds code to prevent the return of broken connection from the pool
  797.  *
  798.  * Revision 1.26  2003/07/21 22:00:36  soussov
  799.  * fixes bug whith pool name mismatch in Connect()
  800.  *
  801.  * Revision 1.25  2003/07/17 20:45:44  soussov
  802.  * connections pool improvements
  803.  *
  804.  * Revision 1.24  2003/05/27 21:12:03  soussov
  805.  * bit type param added
  806.  *
  807.  * Revision 1.23  2003/05/15 21:54:30  soussov
  808.  * fixed bug in timeout handling
  809.  *
  810.  * Revision 1.22  2003/04/29 21:15:35  soussov
  811.  * new datatypes CDB_LongChar and CDB_LongBinary added
  812.  *
  813.  * Revision 1.21  2003/04/01 21:49:55  soussov
  814.  * new attribute 'packet=XXX' (where XXX is a packet size) added to CTLIB_CreateContext
  815.  *
  816.  * Revision 1.20  2003/03/18 14:34:20  ivanov
  817.  * Fix for Rev 1.18-1.19 -- #include's for gethostname() on NCBI_OS_MSWIN platform
  818.  *
  819.  * Revision 1.19  2003/03/17 20:57:09  ivanov
  820.  * #include <unistd.h> everywhere except NCBI_OS_MSWIN platform
  821.  *
  822.  * Revision 1.18  2003/03/17 19:37:31  ucko
  823.  * #include <unistd.h> for gethostname()
  824.  *
  825.  * Revision 1.17  2003/03/17 15:29:02  soussov
  826.  * sets the default host name using gethostname()
  827.  *
  828.  * Revision 1.16  2002/12/20 17:53:56  soussov
  829.  * renames the members of ECapability enum
  830.  *
  831.  * Revision 1.15  2002/09/19 20:05:43  vasilche
  832.  * Safe initialization of static mutexes
  833.  *
  834.  * Revision 1.14  2002/06/28 22:49:02  garrett
  835.  * CTLIB now connects under Windows.
  836.  *
  837.  * Revision 1.13  2002/04/19 15:01:28  soussov
  838.  * adds static mutex to Connect
  839.  *
  840.  * Revision 1.12  2002/04/12 18:50:25  soussov
  841.  * static mutex in context constructor added
  842.  *
  843.  * Revision 1.11  2002/03/26 15:34:38  soussov
  844.  * new image/text operations added
  845.  *
  846.  * Revision 1.10  2002/01/17 22:07:10  soussov
  847.  * changes driver registration
  848.  *
  849.  * Revision 1.9  2002/01/11 20:24:33  soussov
  850.  * driver manager support added
  851.  *
  852.  * Revision 1.8  2001/11/06 18:02:00  lavr
  853.  * Added methods formely inline (moved from header files)
  854.  *
  855.  * Revision 1.7  2001/10/12 21:21:55  lavr
  856.  * Bugfix: Changed '=' -> '==' in severity parsing
  857.  *
  858.  * Revision 1.6  2001/10/11 16:30:44  soussov
  859.  * exclude ctlib dependencies from numeric conversion calls
  860.  *
  861.  * Revision 1.5  2001/10/01 20:09:30  vakatov
  862.  * Introduced a generic default user error handler and the means to
  863.  * alternate it. Added an auxiliary error handler class
  864.  * "CDB_UserHandler_Stream".
  865.  * Moved "{Push/Pop}{Cntx/Conn}MsgHandler()" to the generic code
  866.  * (in I_DriverContext).
  867.  *
  868.  * Revision 1.4  2001/09/27 20:08:33  vakatov
  869.  * Added "DB_" (or "I_") prefix where it was missing
  870.  *
  871.  * Revision 1.3  2001/09/27 16:46:34  vakatov
  872.  * Non-const (was const) exception object to pass to the user handler
  873.  *
  874.  * Revision 1.2  2001/09/26 23:23:31  vakatov
  875.  * Moved the err.message handlers' stack functionality (generic storage
  876.  * and methods) to the "abstract interface" level.
  877.  *
  878.  * Revision 1.1  2001/09/21 23:40:02  vakatov
  879.  * -----  Initial (draft) revision.  -----
  880.  * This is a major revamp (by Denis Vakatov, with help from Vladimir Soussov)
  881.  * of the DBAPI "driver" libs originally written by Vladimir Soussov.
  882.  * The revamp involved massive code shuffling and grooming, numerous local
  883.  * API redesigns, adding comments and incorporating DBAPI to the C++ Toolkit.
  884.  *
  885.  * ===========================================================================
  886.  */