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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  int_cli.c  -  top level routine of GNU SQL client runtime library
  3.  *
  4.  *  This file is a part of GNU SQL Server
  5.  *
  6.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  7.  *  Developed at the Institute of System Programming
  8.  *  This file is written by Konstantin Dyshlevoi.
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  *
  24.  *  Contacts: gss@ispras.ru
  25.  *
  26.  */
  27. /* $Id: int_cli.c,v 1.246 1997/03/31 11:03:50 kml Exp $ */
  28. #include "setup_os.h"
  29. #if HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32. #include "global.h"
  33. #include "gsqltrn.h"
  34. #include "sql.h"
  35. #include "inprtyp.h"
  36. #include "cl_lib.h"
  37. struct sqlca gsqlca;
  38. i4_t    static_int_fl = 1;
  39. #define ANSWER_WAIT_TIME     200   /* time of waiting for a result  *
  40.    * from transaction & dispatcher */
  41. #define TRN_CLIENT_WAIT_TIME 300  /* time of transaction's waiting *
  42.    * for client's request          */
  43. /* definition for time (in seconds) of waiting *
  44.  * for transaction work's finishing            */
  45. #define FIRST_SLEEP 1
  46. #define MAX_SLEEP   10
  47. #define CNT_MAX_SLEEP 500 /* after sleeping with maximum delay (MAX_SLEEP)  *
  48.    * CNT_MAX_SLEEP times transaction will be killed */
  49. #define MAX_TRN_WAIT_TIME (MAX_SLEEP*(CNT_MAX_SLEEP+1))
  50. static i4_t prefetch_cache __P((struct module *mdl,gsql_parms *args,result_t **res));
  51. static struct A {
  52.   struct module *mdl;
  53.   struct A      *next;
  54. } *top = NULL;
  55. int
  56. SQL__disconnect(i4_t commit)
  57. {
  58.   extern void SQL__disconnect_pass2 __P((i4_t));
  59.   prefetch_cache(NULL,NULL,NULL); /* clear cache */
  60.   while(top)
  61.     {
  62.       struct A *c = top;
  63.       top = top->next;
  64.       c->mdl->svc = NULL;
  65.       xfree(c);
  66.     }
  67.   SQL__disconnect_pass2(commit);
  68.   SQLCODE = 0;
  69.   return 0;
  70. }
  71. int
  72. SQL__connect(struct module *mdl,i4_t svc_type,
  73.               i4_t answer_wait_time,i4_t client_wait_time)
  74. {
  75.   struct A    *cmdl;
  76.   for(cmdl = top; cmdl; cmdl = cmdl->next)
  77.     if (cmdl->mdl==mdl)
  78.       break;
  79.   if (!cmdl)
  80.     {
  81.       cmdl = (struct A*) xmalloc(sizeof(*cmdl));
  82.       cmdl->mdl = mdl;
  83.       cmdl->next = top;
  84.       top = cmdl;
  85.     }
  86.   if (!mdl->svc)
  87.     /* work with dispatcher & transaction initialization */
  88.     {
  89.       mdl->svc = (void*) create_service(mdl->db_host,svc_type,
  90.                                         answer_wait_time,
  91.                                         client_wait_time,
  92. -1);
  93.       if (!mdl->svc)
  94. return -ER_SERV;
  95.       mdl->segment = 0;
  96.     }
  97.   return 0;
  98. }
  99. /*
  100.  * cache level 
  101.  */
  102. int
  103. SQL__cache(i4_t new_cache_limit)
  104. {
  105.   static i4_t cache_limit = 0;
  106.   if (new_cache_limit==-1)
  107.     return cache_limit;
  108.   if (cache_limit <= new_cache_limit)
  109.     {
  110.       cache_limit = new_cache_limit;
  111.       return 0;
  112.     }
  113.   assert(cache_limit>new_cache_limit);
  114.   cache_limit = new_cache_limit;
  115.   SQL__runtime (NULL, NULL);
  116.   return SQLCODE;
  117. }
  118. /*
  119.  * prefetch caching
  120.  */
  121. typedef struct cache {
  122.   parm_row_t    *tbl;
  123.   i4_t            count;
  124.   i4_t            sqlcode;
  125.   struct module *mdl;
  126.   i4_t            sect;
  127.   i4_t            current;
  128.   struct cache  *next;
  129.   struct cache  *prev;
  130. } cache_t;
  131. static int
  132. purge_cache_tag(cache_t **fc,cache_t **top)
  133. {
  134.   i4_t i,l;
  135.   cache_t *c = *fc;
  136.   
  137.   if (c->next)
  138.     (*fc = c->next)->prev = c->prev;
  139.   if (c->prev)
  140.     (*fc = c->prev)->next = c->next;
  141.   else if (top)
  142.     *top = c->next;
  143.   
  144.   for ( i = 0 ; i < c->count ; i ++ )
  145.     for ( l = 0 ; l < c->tbl[i].parm_row_t_len ; l ++ )
  146.       if (c->tbl[i].parm_row_t_val[l].value.type == SQLType_Char)
  147.         xfree(c->tbl[i].parm_row_t_val[l].value.data_u.Str.Str_val);
  148.   xfree(c->tbl);
  149.   
  150.   xfree(c);
  151.   return 0;
  152. }
  153. static int
  154. prefetch_cache(struct module *mdl,gsql_parms *args,result_t **res)
  155. {
  156.   static cache_t *cache = NULL;
  157.   static result_t r;
  158.   cache_t *c;
  159.   /* global operation : freeing cache at all */
  160.   if (mdl==NULL)
  161.     {
  162.       while (cache)
  163.         purge_cache_tag(&cache,NULL);
  164.       return 0;
  165.     }
  166.   /* find required prefetch */
  167.   for(c = cache; c; c = c->next)
  168.     if (c->mdl==mdl && c->sect==args->sectnum)
  169.       break;
  170.   if (res==NULL || args->command !=1) /* request to purge cache */
  171.     {
  172.       if (c) /* if there is some cache for that section */
  173.         purge_cache_tag(&c,&cache);
  174.       return 0;
  175.     }
  176.   assert(mdl && res && args->command==1);
  177.   /* we check for cached data or probably save new data in cache */
  178.   /*
  179.    * we assume that request for storing data is impossible while we have some
  180.    * cached data for the same cursor (section)
  181.    */
  182.   if (*res) /* request for storing data */ 
  183.     {
  184.       assert(c==0 /* there is no cached data for this section */);
  185.       assert((*res)->info.rett==RET_TBL);
  186.       c = (cache_t*) xmalloc( sizeof(cache_t) );
  187.       /*
  188.        * the following 3 lines is unreliable and potentially dangerous(!!!!)
  189.        * way storing data, but i'm too lazy now to beautify it /kml
  190.        */
  191.       c->tbl     = (*res)->info.return_data_u.tbl.tbl_val;
  192.       c->count   = (*res)->info.return_data_u.tbl.tbl_len;
  193.       (*res)->info.rett=RET_VOID;
  194.       /* ======== */
  195.       c->sqlcode = (*res)->sqlcode;
  196.       c->mdl     = mdl;
  197.       c->sect    = args->sectnum;
  198.       c->current = 0;
  199.       /* data stored -- link it cache */
  200.       c->prev = NULL;
  201.       c->next = cache;
  202.       cache = cache->prev =  c;
  203.       return 1;
  204.     }
  205.   else if (c) /* if there is some cached data for this sectionr */ 
  206.     {
  207.       bzero(&r,sizeof(r));
  208.       if (c->current<c->count)
  209.         {
  210.           r.info.return_data_u.row.parm_row_t_val = c->tbl[c->current].parm_row_t_val;
  211.           r.info.return_data_u.row.parm_row_t_len = c->tbl[c->current].parm_row_t_len;
  212.           r.info.rett = RET_ROW;
  213.           if (++(c->current) == c->count && c->sqlcode!=100)
  214.             {
  215.               r.sqlcode = c->sqlcode;
  216.               c->sqlcode = 0;
  217.             }
  218.         }
  219.       else /* if there is no more data */
  220.         {
  221.           r.sqlcode = c->sqlcode;
  222.           purge_cache_tag(&c,&cache);
  223.           if (!r.sqlcode)
  224.             return 0;
  225.           assert(r.sqlcode==100);
  226.         }
  227.       *res = &r;
  228.       return 1;
  229.     }
  230.   /* we checked for cached data but there no data in cache */
  231.   return 0;
  232. }
  233. /*
  234.  * error code procesinng
  235.  */
  236. static void
  237. proc_ret (i4_t code, CLIENT **svc)
  238.   SQLCODE = code;
  239.   if (SQLCODE < 0)
  240.     {
  241.       if ( SQLCODE == -ER_SERV)
  242. gsqlca.errmsg = clnt_error_msg();
  243.       else
  244. gsqlca.errmsg = SQL__err_msg(-SQLCODE);
  245.       if ( SQLCODE == -ER_SERV || SQLCODE == -NOTRNANS)
  246.         { /* down service if connection is lost                     */
  247.           /* how about cache? Does it need to be purged here? Hmm...*/
  248.           down_svc(*svc);
  249.           *svc = NULL;
  250.         }
  251.     }
  252.   return;
  253. } /* proc_ret */
  254. /*
  255.  * client's part of interpretator 
  256.  */
  257. static int
  258. execute_it(insn_t *insn,CLIENT *svc,result_t **r)
  259. {
  260.   assert(r);
  261.   *r = execute_stmt_1 (insn, svc);
  262.   if (!*r)
  263.     {
  264.       i4_t ready = svc_ready(svc,FIRST_SLEEP,
  265.     MAX_SLEEP,MAX_TRN_WAIT_TIME);
  266.       if (ready > 0)
  267. *r = retry_1 (NULL, svc);
  268.       else if (ready <0)
  269.         return -ER_SERV;
  270.       else /* if (ready == 0) */
  271.         return -NOTRNANS;
  272.     }
  273.   if (!*r)
  274.     return -NOTRNANS;
  275.   return 0;
  276. }
  277. void
  278. SQL__runtime (struct module *mdl,gsql_parms *args)
  279. {
  280.   static i4_t     arg_hole_cnt = 0;
  281.   static parm_t *arg_hole     = NULL;
  282.   
  283.   static struct {
  284.     insn_t *head;
  285.     insn_t *tail;
  286.     i4_t     insns;
  287.     CLIENT *svc;
  288.   } icache = { NULL, NULL, 0 , NULL };
  289.   
  290.   int         rc;
  291.   insn_t     *i_arg = NULL;
  292.   result_t   *i_res = NULL;
  293.   gsql_parm  *parm = (args) ? args->prm : NULL;
  294.   i4_t        args_cnt = (args) ? args->count : 0;
  295.   i4_t        in_args_cnt, out_args_cnt, i, j, error;
  296. #define RET(code)  { proc_ret (code, (CLIENT**)&(mdl->svc)); return; }
  297. #define CHKRC      { if(rc) { proc_ret (rc, (CLIENT**)&(mdl->svc)); return; }}
  298.   if (!icache.tail && !mdl) /* if there is no cache and this call    */
  299.     RET(0);                 /* invoked by cache change call - return */ 
  300.   
  301.   if (args->sectnum == -3) /* if nothing was prepared */
  302.     RET(0);
  303.   
  304.   if (mdl)
  305.     {
  306.       rc = SQL__connect(mdl,INTERPR_SVC,ANSWER_WAIT_TIME,TRN_CLIENT_WAIT_TIME);
  307.       CHKRC;
  308.       /* module initialization */
  309.       if (!mdl->segment)
  310.         {
  311.           result_t *res_init = load_module_1 (&(mdl->modname), mdl->svc);
  312.           
  313.           if (!res_init)
  314.             RET (-ER_SERV);
  315.           assert(res_init->info.rett == RET_SEG);
  316.           if ((mdl->segment = res_init->info.return_data_u.segid) < 0)
  317.             RET (res_init->sqlcode);
  318.         }
  319.     }
  320.   /* Parameters handling : */
  321.   
  322.   for (in_args_cnt = i = 0; i < args_cnt; i++ )
  323.     if (!parm[i].flags)
  324.       in_args_cnt++;
  325.   
  326.   out_args_cnt = args_cnt - in_args_cnt;
  327.   /* check for prefetched data */
  328.   if (prefetch_cache(mdl,args,&i_res))
  329.     goto read_answer;
  330.   
  331.   /* iput parameters processing */
  332.   CHECK_ARR_SIZE (arg_hole, arg_hole_cnt, in_args_cnt, parm_t);
  333.     
  334.   for (j = i = 0; i < args_cnt; i++)
  335.     if (!parm[i].flags)
  336.       if ((error = user_to_rpc (parm + i, arg_hole + (j++))) < 0)
  337. RET (error);
  338.   
  339.   /* forming instruction */
  340.   if (mdl)
  341.     {
  342.       i_arg = (insn_t*)xmalloc(sizeof(insn_t));
  343.       i_arg->parms.parm_row_t_len = in_args_cnt;
  344.       i_arg->parms.parm_row_t_val = (in_args_cnt) ? arg_hole : NULL;
  345.       i_arg->vadr_segm = mdl->segment;
  346.       i_arg->sectnum = args->sectnum;
  347.       i_arg->command = args->command;
  348.       i_arg->options = gmin (args->options,SQL__cache(-1));
  349.     }
  350.   
  351.   /* check for possibility to cache instruction */
  352.   if ( SQL__cache(-1) > icache.insns && 
  353.        (!icache.head || !mdl || icache.svc==mdl->svc) &&
  354.        out_args_cnt == 0 &&
  355.        (!args || args->command >=0)
  356.        )
  357.     {
  358.       if (!mdl) /* if it's dummy command -- changing cache */
  359.         RET(0);
  360.       if (in_args_cnt) /* store parameters */
  361.         {
  362.           i4_t l = in_args_cnt * sizeof (parm_t);
  363.           assert (i_arg != NULL);
  364.           i_arg->parms.parm_row_t_val = (parm_t*) xmalloc(l);
  365.           bcopy (arg_hole,i_arg->parms.parm_row_t_val,l);
  366.           for ( l = 0 ; l < in_args_cnt ; l ++ )
  367.             if (arg_hole[l].value.type == SQLType_Char)
  368.               {
  369.                 parm_t *p = i_arg->parms.parm_row_t_val + l;
  370.                 char   *v = xmalloc(p->value.data_u.Str.Str_len);
  371.                 bcopy(p->value.data_u.Str.Str_val,v,p->value.data_u.Str.Str_len);
  372.                 p->value.data_u.Str.Str_val = v;
  373.               }
  374.         }
  375.       if (icache.head)
  376.         icache.tail = icache.tail->next = i_arg;
  377.       else
  378.         {
  379.           icache.tail = icache.head       = i_arg;
  380.           icache.svc = mdl->svc;
  381.         }
  382.       icache.insns ++;
  383.       i_arg = NULL;
  384.       if (SQL__cache(-1) > icache.insns)
  385.         RET(0);
  386.     }
  387.   /* flush cache */
  388.   if (icache.head)
  389.     {
  390.       rc = execute_it(icache.head,icache.svc,&i_res);
  391.       /* free cache */
  392.       while (icache.head) 
  393.         {
  394.           i4_t l;
  395.           icache.tail = icache.head;
  396.           icache.head = icache.head->next;
  397.           for ( l = 0 ; l < icache.tail->parms.parm_row_t_len ; l ++ )
  398.             if (icache.tail->parms.parm_row_t_val[l].value.type == SQLType_Char)
  399.               xfree(icache.tail->parms.parm_row_t_val[l].value.data_u.Str.Str_val);
  400.           xfree(icache.tail);
  401.           icache.insns--;
  402.         }
  403.       icache.tail = icache.head = NULL;
  404.       assert(icache.insns==0);
  405.       CHKRC;
  406.     }
  407.   
  408.   if (i_arg)
  409.     {
  410.       assert(i_res==NULL || i_res->info.rett==RET_VOID);
  411.       rc = execute_it(i_arg,mdl->svc,&i_res);
  412.       /* free in parms */
  413.       xfree(i_arg);
  414.       CHKRC;
  415.     }
  416.   if (i_res->info.rett==RET_VOID)
  417.     {
  418.       if ((i_res->sqlcode == 100) && out_args_cnt==0 &&
  419.           args && args->command==0)
  420.         RET (0); /* It's not CURSOR or SELECT but SQLCODE == 100 */
  421.       
  422.       RET (i_res->sqlcode); /* normal exit: may be on error */
  423.     }
  424.   assert(i_res->info.rett==RET_TBL || i_res->info.rett==RET_ROW);
  425.   if (i_res->info.rett==RET_TBL)
  426.     {
  427.       assert(prefetch_cache(mdl,args,&i_res)); /* put table in cache */
  428.       i_res = NULL;
  429.       assert(prefetch_cache(mdl,args,&i_res)); /* read fist row      */
  430.     }
  431.   
  432. read_answer:
  433.   {
  434.     parm_row_t *orow = &i_res->info.return_data_u.row;
  435.     rc = i_res->sqlcode;
  436.     if(rc==100 && args->command!=1) /* avoid eofscan report outside cursor */
  437.       rc = 0;
  438.     
  439.     if (rc==100) /* SQLCODE : End Of Scan */
  440.       RET (rc);
  441.     
  442.     /* checking of result data count */
  443.     if (orow->parm_row_t_len != out_args_cnt)
  444.       RET (-ER_CLNT);
  445.     
  446.     for (i = 0, j = 0; i < args_cnt; i++ )
  447.       if (parm[i].flags)
  448.         if ((error = rpc_to_user (orow->parm_row_t_val + (j++), parm + i)) < 0)
  449.           RET (error);
  450.   }
  451.   RET (rc);
  452.   
  453. #undef RET
  454. }