cl_lib.c
上传用户:dgyhgb
上传日期:2007-01-07
资源大小:676k
文件大小:12k
源码类别:

SQL Server

开发平台:

Unix_Linux

  1. /* 
  2.  *  cl_lib.c -  rpc client support library
  3.  *              of GNU SQL compiler
  4.  *                
  5.  *  This file is a part of GNU SQL Server
  6.  *
  7.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  8.  *  Developed at the Institute of System Programming
  9.  *  This file is written by Michael Kimelman 
  10.  * 
  11.  *  This program is free software; you can redistribute it and/or modify
  12.  *  it under the terms of the GNU General Public License as published by
  13.  *  the Free Software Foundation; either version 2 of the License, or
  14.  *  (at your option) any later version.
  15.  *
  16.  *  This program is distributed in the hope that it will be useful,
  17.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  *  GNU General Public License for more details.
  20.  *
  21.  *  You should have received a copy of the GNU General Public License
  22.  *  along with this program; if not, write to the Free Software
  23.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  24.  *
  25.  *  Contacts: gss@ispras.ru
  26.  *
  27.  */
  28. /* $Id: cl_lib.c,v 1.247 1997/03/31 12:07:26 kml Exp $ */
  29. #include "setup_os.h"
  30. #ifdef HAVE_UNISTD_H
  31. #include  <unistd.h>
  32. #endif
  33. #ifdef  STDC_HEADERS        
  34. #include  <string.h>
  35. #else
  36. #include  <strings.h>
  37. #endif
  38. #if HAVE_UNAME
  39. #include <sys/utsname.h>
  40. #endif
  41. #include  "cl_lib.h"
  42. #include  "xmem.h"
  43. #include  "errors.h"
  44. #include  "dispatch.h"
  45. #include  "sql_decl.h"
  46. #include  "gsqltrn.h"
  47. #include  "sql.h"
  48. #define DEFAULT_TRN_CLIENT_WAIT_TIME   300  /* 5 min - wait between client calls */
  49. #define DEFAULT_TOTAL_TRANSACTION_TIME 3600 /* 1 hour - whole transaction window */
  50. #define DEFAULT_MIN_DELAY              1    
  51. #define DEFAULT_MAX_DELAY              16
  52. #define DEFAULT_MAX_WAIT_TIME          3600 /* max waiting for transaction response*/
  53. #define DEFAULT_ANSWER_WAIT_TIME       20
  54. i4_t last_client_asked_for_gdb;
  55. typedef struct A {
  56.   struct A *next;
  57.   struct A *prev;
  58.   CLIENT   *svc;
  59.   opq       proc_id;
  60.   rpc_svc_t svc_type;
  61. } svc_t;
  62. typedef struct B {
  63.   struct B *next;
  64.   struct B *prev;
  65.   CLIENT   *adm ;
  66.   svc_t    *svcs;
  67.   char     *host;
  68. } svr_t;
  69. static svr_t *svrs = NULL;
  70. static struct {
  71.   i4_t   used;
  72.   char *err_message;
  73. } rpc_err_msg = { 1, NULL };
  74. char *
  75. SQL__err_msg(i4_t code)
  76. {
  77.   static char *err_str[]=
  78.   {
  79. #define DEF_ERR(CODE,ERRstr)  ERRstr,
  80. #include "errors.h"
  81. #undef DEF_ERR
  82.     NULL
  83.   };
  84.   if ( code < 0 )
  85.     code = -code;
  86.   if (code>=0 && code<sizeof(err_str)/sizeof(char*))
  87.     return err_str[code];
  88.   return "incorrect error code";
  89. }
  90. static void 
  91. store_err(char *msg)
  92. {
  93.   if (rpc_err_msg.err_message)
  94.     {
  95.       xfree(rpc_err_msg.err_message);
  96.       rpc_err_msg.err_message = NULL;
  97.     }
  98.   if (!msg)
  99.     return;
  100.   rpc_err_msg.err_message = savestring(msg);
  101.   rpc_err_msg.used = 0;
  102. }
  103. char *
  104. clnt_error_msg(void)
  105. {
  106.   if (rpc_err_msg.used)
  107.     return "";
  108.   rpc_err_msg.used = 1;
  109.   return rpc_err_msg.err_message;
  110. }
  111. static void global_disconnect __P((void));
  112.      
  113. char *
  114. choose_host(char *hostname)
  115. {
  116.   if ( !hostname )
  117.     hostname = getenv("GSSHOST");
  118. #if defined(HAVE_UNAME) && 0
  119.   if ( !hostname )
  120.     {
  121.       static struct utsname buf;
  122.       uname(&buf);
  123.       hostname = buf.nodename; /*!!!!!!!!! for debugging purpose only      */
  124.       /* there is a hole for procedure for finding the only working server */
  125.       /* or something like it..............................................*/
  126.     }
  127. #endif
  128.   if ( !hostname )
  129.     hostname = "localhost";
  130.   if ( !hostname)
  131.     {
  132.       store_err("Can't choose the host to connect to.");
  133.       return NULL;
  134.     }
  135.   return hostname;
  136. }
  137. CLIENT *
  138. create_service(char *hostname, 
  139.        rpc_svc_t required_service,
  140.        i4_t answer_wait_time,
  141.        i4_t trn_client_wait_time,
  142.        i4_t total_transaction_time)
  143. {
  144.   static i4_t atexit_registered = 0;
  145.   svr_t *csvr;
  146.   svc_t *csvc;
  147.   struct timeval tv;
  148.   tv.tv_sec = answer_wait_time; tv.tv_usec = 0;
  149.   if (answer_wait_time == -1 )
  150.     tv.tv_sec = answer_wait_time = DEFAULT_ANSWER_WAIT_TIME;
  151.   if ( !atexit_registered)
  152.     {
  153. #if HAVE_ATEXIT
  154.       atexit(global_disconnect);
  155. #elif HAVE_ON_EXIT
  156.       on_exit(global_disconnect);
  157. #endif
  158.       atexit_registered = 1;
  159.     }
  160.   if (hostname)
  161.     {
  162.       static char *host=NULL;
  163.       char *p = hostname;
  164.       while ( *p && *p != ':' ) p++;
  165.       if ( *p == ':' ) /* then hostname contained portid */
  166.         {
  167.           i4_t l = p - hostname + 1;
  168.           if ( l > 1 )
  169.             {
  170.               host = xrealloc (host, l);
  171.               bcopy (hostname, host, l);
  172.               host[l]=0;
  173.               hostname=host;
  174.             }
  175.            fix_adm_port(p+1);
  176.         }
  177.     }
  178.   hostname = choose_host(hostname);
  179.   /* change adm port in according to environment, options and defaults */
  180.   fix_adm_port(NULL); 
  181.   for ( csvr = svrs; csvr ; csvr = csvr->next )
  182.     if ( !strcmp(csvr->host,hostname) )
  183.       break;
  184.   if (!csvr) /* if we don't have RPC handle of desired host */
  185.     {
  186.       CLIENT *clnt;
  187.       
  188.       clnt = clnt_create(hostname, SQL_DISP, SQL_DISP_ONE,"tcp");
  189.       if (clnt == (CLIENT *) NULL) 
  190. {
  191.   store_err(clnt_spcreateerror(hostname));
  192.   return NULL;
  193. }
  194.       clnt->cl_auth = authunix_create_default();
  195.       if (answer_wait_time > 0)
  196. {
  197.   tv.tv_sec *= 10;
  198.   clnt_control(clnt,CLSET_TIMEOUT,(char*)&tv);
  199.   tv.tv_sec  = answer_wait_time;
  200. }
  201.       csvr = xmalloc(sizeof(svr_t));
  202.       
  203.       csvr->prev = NULL;
  204.       csvr->next = svrs;
  205.       csvr->adm  = clnt;
  206.       csvr->svcs = NULL;
  207.       csvr->host = savestring(hostname);
  208.       if (svrs)
  209. svrs->prev = csvr;
  210.       svrs = csvr;
  211.     }
  212.   /* csvr points now to the handle of required server */
  213.   for ( csvc = csvr->svcs; csvc ; csvc = csvc->next )
  214.     if ( csvc->svc_type == required_service )
  215.       break;
  216.   
  217.   if (!csvc) /* if we aren`t currently connected to the given host */
  218.     {
  219.       CLIENT    *clnt;
  220.       i4_t        vers_id;
  221.       res       *result;
  222.       init_arg   i_arg;
  223.       
  224.       if ( trn_client_wait_time < 0 )
  225. trn_client_wait_time = DEFAULT_TRN_CLIENT_WAIT_TIME;
  226.       if ( total_transaction_time < 0 )
  227. total_transaction_time = DEFAULT_TOTAL_TRANSACTION_TIME;
  228.       
  229.       i_arg.user_name         = get_user_name();
  230.       i_arg.wait_time         = trn_client_wait_time ;
  231.       i_arg.total_time        = total_transaction_time ;
  232.       i_arg.type              = required_service;
  233.       i_arg.need_gdb          = 0;
  234.       i_arg.x_server          = ":0.0";
  235.       vers_id = 1;
  236. #ifndef NOT_DEBUG
  237.       {
  238. i4_t c = 0;
  239.         char *s=NULL;
  240.         s = getenv("NEEDGDB");
  241.         if (!s)
  242.           {
  243.             fprintf(stderr,"Do you want to run gdb?");
  244.             do
  245.               c=getchar();
  246.             while (c=='n');
  247.           }
  248.         else if (*s=='y')
  249.           c = 'y';
  250.         
  251. if ( c == 'y' )
  252.   {
  253.     char buf[100], *b=getenv("DISPLAY");
  254.     i_arg.need_gdb = 1;
  255.     if ( b )
  256.       strcpy(buf,b);
  257.     else
  258.       {
  259.                 printf("Enter X display (host:0) >>");
  260.                 scanf("%s",buf);
  261.       }
  262.     i_arg.x_server = savestring(buf);
  263.   }
  264.       }
  265. #endif
  266.       last_client_asked_for_gdb = i_arg.need_gdb;
  267.       for(;;)
  268.         {
  269.           result = create_transaction_1(&i_arg,csvr->adm);
  270.           if ( !result)
  271.             {
  272.               store_err(clnt_spcreateerror(hostname));
  273.               return NULL;
  274.             }
  275.           if ( result->rpc_id > 0)
  276.             break;
  277.           if ( result->rpc_id != -NOCRTR )
  278.             {
  279.               store_err(SQL__err_msg(NOCRTR));
  280.               return NULL;
  281.             }
  282.           sleep(1);
  283.         }
  284.       clnt = clnt_create(hostname, result->rpc_id, vers_id,"tcp");
  285.       if (clnt == (CLIENT *) NULL) 
  286. {
  287.   store_err(clnt_spcreateerror(hostname));
  288.   return NULL;
  289. }
  290.       clnt->cl_auth = authunix_create_default();
  291.       if (answer_wait_time > 0)
  292. clnt_control(clnt,CLSET_TIMEOUT,(char*)&tv);
  293.       if (i_arg.need_gdb)
  294.         {
  295.   tv.tv_sec = DEFAULT_MAX_WAIT_TIME;
  296.   clnt_control(clnt,CLSET_TIMEOUT,(char*)&tv);
  297.   tv.tv_sec  = answer_wait_time;
  298.         }
  299.       csvc = xmalloc(sizeof(svc_t));
  300.       
  301.       csvc->prev = NULL;
  302.       csvc->next = csvr->svcs;
  303.       csvc->svc  = clnt;
  304.       csvc->svc_type = required_service;
  305.       csvc->proc_id.opq_len = result->proc_id.opq_len;
  306.       csvc->proc_id.opq_val = (char*) xmalloc(result->proc_id.opq_len);
  307.       bcopy(result->proc_id.opq_val,
  308.     csvc->proc_id.opq_val,
  309.     result->proc_id.opq_len);
  310.       if (csvr->svcs)
  311. csvr->svcs->prev = csvc;
  312.       csvr->svcs = csvc;
  313.     }
  314.   return csvc->svc;
  315. }
  316. static int
  317. find_svc(CLIENT *cl,svr_t **svrp,svc_t **svcp)
  318. {
  319.   register svc_t *csvc;
  320.   register svr_t *csvr;
  321.   for ( csvr = svrs; csvr; csvr = csvr->next )
  322.     for ( csvc = csvr->svcs ; csvc ; csvc = csvc->next )
  323.       if (csvc->svc == cl)
  324. {
  325.   *svrp = csvr;
  326.   *svcp = csvc;
  327.   return 1;
  328. }
  329.   *svrp = NULL;
  330.   *svcp = NULL;
  331.   return 0;
  332. }
  333. static int
  334. valid_info(svr_t *svr, svc_t *svc)
  335. {
  336.   svc_t *csvc;
  337.   svr_t *csvr;
  338.   
  339.   if (!find_svc(svc->svc,&csvr,&csvc))
  340.     return 0; /* it has already destroyed */
  341.   
  342.   assert( svr == csvr && svc == csvc);
  343.   return 1;
  344. }
  345. static void
  346. destroy_svc_info(svr_t *csvr, svc_t *csvc)
  347. {
  348.   if (!valid_info(csvr,csvc))
  349.     return ; /* it has already destroyed */
  350.   
  351.   if ( csvc->next )
  352.     csvc->next->prev = csvc->prev; 
  353.   if ( csvc->prev )
  354.     csvc->prev->next = csvc->next;
  355.   else
  356.     csvr->svcs = csvc->next;
  357.   auth_destroy(csvc->svc->cl_auth);
  358.   clnt_destroy(csvc->svc);
  359.   xfree(csvc->proc_id.opq_val);
  360.   xfree(csvc);
  361. }
  362. static void  
  363. destroy_svr_info(svr_t *csvr)
  364. {
  365.   while(csvr->svcs)
  366.     destroy_svc_info(csvr,csvr->svcs);
  367.   if ( csvr->next )
  368.     csvr->next->prev = csvr->prev; 
  369.   if ( csvr->prev )
  370.     csvr->prev->next = csvr->next;
  371.   else
  372.     svrs = csvr->next;
  373.   auth_destroy(csvr->adm->cl_auth);
  374.   clnt_destroy(csvr->adm);
  375.   xfree(csvr->host);
  376.   xfree(csvr);
  377. }
  378. static commit_down_mode = 0;
  379. static int
  380. down_service(svr_t *csvr, svc_t *csvc)
  381. {
  382.   int *res;
  383.   if (!valid_info(csvr,csvc))
  384.     return 1; /* it has already destroyed */
  385.   
  386.   if (commit_down_mode)
  387.     {
  388.       result_t  *ret;
  389.       insn_t     arg;
  390.       bzero(&arg,sizeof(arg));
  391.       arg.sectnum = commit_down_mode;
  392.   
  393.       ret = execute_stmt_1 (&arg, csvc->svc);
  394.       
  395.       if (!ret)
  396.         {
  397.           i4_t ready = svc_ready(csvc->svc,1,4,16);
  398.           if (ready > 0)
  399.             ret = retry_1 (NULL, csvc->svc);
  400.         }
  401.       if(!ret)
  402.         store_err("service crash");
  403.     }
  404.   if (!valid_info(csvr,csvc))
  405.     return 1; /* it has already destroyed */
  406.   res = trn_kill_1(&(csvc->proc_id),csvr->adm);
  407.   /* If server not respond - unlink it */
  408.   if ( !res )
  409.     {
  410.       store_err("Server crash");
  411.       destroy_svr_info(csvr);
  412.       return 0;
  413.     }
  414.   else
  415.     destroy_svc_info(csvr,csvc);
  416.   return 1;
  417. }
  418. static void
  419. down_server(svr_t *csvr)
  420. {
  421.   while (csvr->svcs)
  422.     if( !down_service(csvr,csvr->svcs) )
  423.       {
  424. fprintf(STDERR,clnt_error_msg());
  425. return;
  426.       }
  427.   destroy_svr_info(csvr);
  428. }
  429. static void 
  430. global_disconnect(void)
  431. {
  432.   while(svrs)
  433.     down_server(svrs);
  434. }
  435. void  
  436. down_svc(CLIENT *svc)
  437. {
  438.   svc_t *csvc;
  439.   svr_t *csvr;
  440.   i4_t    rc = 0;
  441.   
  442.   if (find_svc(svc,&csvr,&csvc))
  443.     rc = down_service(csvr,csvc);
  444.   else
  445.     store_err("Required service not found");
  446.   if (!rc)
  447.     fprintf(STDERR,clnt_error_msg());
  448. }
  449. i4_t   
  450. svc_ready(CLIENT *cl_handle, i4_t min_delay, i4_t max_delay, i4_t max_wait_time)
  451. {
  452.   svc_t *csvc;
  453.   svr_t *csvr;
  454.   register i4_t    cdelay;
  455.   register i4_t    waited;
  456.   
  457.   if (!find_svc(cl_handle,&csvr,&csvc))
  458.     {
  459.       store_err("incorrect service required");
  460.       return -1;
  461.     }
  462.   if ( min_delay <= 0 )
  463.     min_delay = DEFAULT_MIN_DELAY;
  464.   if ( max_delay <= 0 )
  465.     max_delay = DEFAULT_MAX_DELAY;
  466.   if ( max_wait_time <= 0 )
  467.     max_wait_time = DEFAULT_MAX_WAIT_TIME;
  468.   
  469.   for ( cdelay  = waited = 0; waited < max_wait_time; waited += cdelay )
  470.     {
  471.       int *ready;
  472.       ready = is_ready_1(&(csvc->proc_id), csvr->adm);
  473.       if (!ready)
  474. {
  475.   store_err(clnt_sperror(csvr->adm,csvr->host));
  476.   destroy_svr_info(csvr);
  477.   return -1;
  478. }
  479.       if (*ready < 0 ) /* if error occured */
  480. {
  481.     store_err("service crash");
  482.           destroy_svc_info(csvr,csvc);
  483.   return -1;
  484. }
  485.       if (*ready == 0 ) /* result is ready */
  486. return 1;
  487.       if (cdelay < min_delay ) cdelay = min_delay;
  488.       else                    cdelay *= 2;
  489.       if (cdelay > max_delay ) cdelay = max_delay;
  490.       sleep (cdelay);
  491.     }
  492.   return 0;
  493. }
  494. void
  495. SQL__disconnect_pass2(i4_t commit)
  496. {
  497.   commit_down_mode = commit;
  498.   global_disconnect();
  499.   commit_down_mode = 0;
  500. }
  501. char *
  502. get_host(CLIENT *cl)
  503. {
  504.   svc_t *csvc;
  505.   svr_t *csvr;
  506.   
  507.   if (!find_svc(cl,&csvr,&csvc))
  508.     return NULL; /* it has already destroyed */
  509.   
  510.   return csvr->host;
  511. }