home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / ingres04.lzh / source / dbu / update.c < prev   
Encoding:
C/C++ Source or Header  |  1992-09-18  |  10.9 KB  |  386 lines

  1. # include    <stdio.h>
  2. # include    <ingres.h>
  3. # include    <resp.h>
  4. # include    <aux.h>
  5. # include    <symbol.h>
  6. # include    <access.h>
  7. # include    <batch.h>
  8. # include    <opsys.h>
  9. # include    <catalog.h>
  10. # include    <btree.h>
  11. # include    <version.h>
  12. # include    <sccs.h>
  13. # include    <errors.h>
  14.  
  15. SCCSID(@(#)update.c    8.4    2/8/85)
  16.  
  17. /*
  18. **    Update reads a batch file written by the
  19. **    access method routines (openbatch, addbatch, closebatch)
  20. **    and performs the updates stored in the file.
  21. **
  22. **    It assumes that it is running in the database. It
  23. **    is driven by the data in the Batchhd struct (see ../batch.h).
  24. **    If the relation has a secondary index then update calls
  25. **    secupdate. As a last step the batch file is removed.
  26. **
  27. **    The global flag Batch_recovery is tested in case
  28. **    of an error. It should be FALSE if update is being
  29. **    run as the dbu deferred update processor. It should
  30. **    be TRUE if it is being used as part of the recovery
  31. **    procedure.
  32. */
  33.  
  34. update()
  35. {
  36.     register int    i, mode;
  37.     DESC        rel, d;
  38.     long        oldtid, tupcnt;
  39.     char        oldtup[MAXTUP], newtup[MAXTUP], tuple[MAXTUP];
  40.     char        *batchname(), *trim_relname();
  41.     char        *tp;
  42.     long        bad_lid[MAXLID], lid, old_lid[MAXLID], new_lid;
  43.     char        bad[MAXLID][10], *locv();
  44.     char        delbtree[MAXNAME + 4], replbtree[MAXNAME + 4];
  45.     char        tup_buf[3 * LIDSIZE], lid_buf[LIDSIZE];
  46.     char        btree[MAXNAME + 4], out[MAXNAME + 4];
  47.     char        filname[MAXNAME+4];
  48.     TID        tidpos;
  49.     struct stat    sbuf;
  50.     long        num;
  51.     int        first, end, batchcnt, j, k;
  52.     FILE        *fp;
  53.     long        temp;
  54.     long        del_cnt;
  55.     extern int    Btree_fd;
  56.     extern DESC    Btreesec;
  57.     extern char    *ztack();
  58.  
  59. #    ifdef xZTR1
  60.     if (tTf(48, -1))
  61.         printf("Update on %s\n", batchname());
  62. #    endif
  63.     /* set up to read batchhd */
  64.     Batch_cnt = BATCHSIZE;    /* force a read on next getbatch */
  65.     Batch_dirty = FALSE;
  66.     if ((Batch_fp = open(batchname(), O_RDWR)) < 0)
  67.         syserr("prim:can't open %s", batchname());
  68.     getbatch(&Batchhd, sizeof Batchhd);
  69.  
  70.     tupcnt = Batchhd.num_updts;
  71. #    ifdef xZTR1
  72.     if (tTf(48, 0))
  73.         printf("rel=%s tups=%ld\n", Batchhd.rel_name, tupcnt);
  74. #    endif
  75.     Resp.resp_tups = 0;
  76.     if (!tupcnt)
  77.     {
  78.         rmbatch();
  79.         return (1);
  80.     }
  81.  
  82.     /* update the primary relation */
  83.     if (i = openr(&rel, OR_WRITE, Batchhd.rel_name))
  84.         syserr("prim:can't openr %s %d", Batchhd.rel_name, i);
  85.     if (rel.reldum.reldim > 0)
  86.     {
  87.         bmove(rel.relbtree, &Btreesec, sizeof(Btreesec));
  88.         Btree_fd = rel.btree_fd;
  89.     }
  90.  
  91.     mode = Batchhd.mode_up;
  92.  
  93.     if (rel.reldum.reldim > 0)
  94.     /* create files necessary for updating btrees in specified order */
  95.     {
  96.         concat(REPL_IN, Fileset, replbtree);
  97.         if ((Repl_infp = fopen(replbtree, "w")) == NULL)
  98.             syserr("can't open %s", replbtree);
  99.         concat(DEL_IN, Fileset, delbtree);
  100.         if ((Del_infp = fopen(delbtree, "w")) == NULL)
  101.             syserr("can't open %s", delbtree);
  102.     }
  103.     Del_cnt = 0;
  104.     for (i = 0; i < MAXLID; ++i)
  105.     {
  106.         Prev_lid[i] = 0;
  107.         Repl_cnt[i] = 0;
  108.     }
  109.  
  110.     if (rel.reldum.reldim > 0)
  111.     {
  112.         if (tupcnt <= 1 || (mode != mdREPL && mode != mdAPP))
  113.             fclose(Repl_infp);
  114.         else
  115.         /* do replace's in ascending lid-value order */
  116.         {
  117.             d.reloff[1] = 0;
  118.             d.reloff[2] = Batchhd.tido_size + Batchhd.tupo_size + Batchhd.tupn_size - LIDSIZE;
  119.             for (i = 1; i <= rel.reldum.reldim; ++i)
  120.             {
  121.                 d.reloff[i+2] = d.reloff[i+1] + LIDSIZE;
  122.                 d.relfrmt[i+1] = INT;
  123.                 d.relfrml[i+1] = LIDSIZE;
  124.                 d.relgiven[i+1] = i;
  125.             }
  126.             d.relfrmt[i+1] = CHAR;
  127.             d.relfrml[i+1] = Batchhd.tidn_size;
  128.             d.relgiven[0] = 0;
  129.             d.relgiven[1] = i;
  130.             d.relgiven[i+1] = i + 1;
  131.             d.relfrmt[1] = CHAR;
  132.             d.relfrml[1] = d.reloff[2];
  133.             d.reldum.relspec = M_ORDER;
  134.             d.reldum.relatts = 2 + rel.reldum.reldim;
  135.             d.reldum.relwid = d.reloff[2] + LIDSIZE + Batchhd.tidn_size;
  136.             /* extract information about tuples from batch file */
  137.             if (stat(batchname(), &sbuf) < 0)
  138.                 syserr("bad file for stat %s", batchname());
  139.             num = sbuf.st_size / (BATCHSIZE + IDSIZE);
  140.             if (num >= 1)
  141.                 first = BATCHSIZE - Batch_cnt;
  142.             else
  143.                 first = sbuf.st_size - sizeof Batchhd - IDSIZE;
  144.             if ((i = fwrite(&Batchbuf.bbuf[Batch_cnt], 1, first, Repl_infp)) != first)
  145.                 syserr("can't write replace file");
  146.             for (i = 2; i <= num; ++i)
  147.             {
  148.                 Batch_cnt = BATCHSIZE;
  149.                 readbatch();
  150.                 if (fwrite(Batchbuf.bbuf, 1, BATCHSIZE, Repl_infp) != BATCHSIZE)
  151.                     syserr("can't write to replace file");
  152.             }
  153.             Batch_cnt = BATCHSIZE;
  154.             readbatch();
  155.             end = ((sbuf.st_size - BATCHSIZE - IDSIZE) % (BATCHSIZE + IDSIZE)) - IDSIZE;
  156.             if (end > 0)
  157.                 if (fwrite(Batchbuf.bbuf, 1, end, Repl_infp) != end)
  158.                     syserr("can't write to replace file 2");
  159.             fclose(Repl_infp);
  160.             sortfile(replbtree, &d, FALSE);
  161.             if ((Repl_outfp = fopen(ztack(REPL_OUT, Fileset), "r")) == (FILE *)NULL)
  162.                 syserr("can't open replace file in update for reading\n");
  163.             concat("_SYStemp", Fileset, filname);
  164.             /* rewrite in batch file in sorted order */
  165.             if ((fp = fopen(filname, "w")) == NULL)
  166.                 syserr("can't open %s", filname);
  167.             if ((k = fread(Batchbuf.bbuf, 1, first, Repl_outfp)) != first)
  168.                 syserr("read error0 from replace file %d", k);
  169.             if (fwrite(Batchbuf.file_id, 1, IDSIZE, fp) != IDSIZE)
  170.                 syserr("write error in batch file");
  171.             if (fwrite(&Batchhd, 1, sizeof Batchhd, fp) != sizeof Batchhd)
  172.                 syserr("write error in batch file");
  173.             if (fwrite(Batchbuf.bbuf, 1, first, fp) != first)
  174.                 syserr("write error in batch file");
  175.             for (i = 2; i <= num; ++i)
  176.             {
  177.                 if ((k = fread(Batchbuf.bbuf, 1, BATCHSIZE, Repl_outfp)) != BATCHSIZE)
  178.                     syserr("read error1 in replace file %d",  k);
  179.                 if (fwrite(&Batchbuf, 1, BATCHSIZE + IDSIZE, fp) != BATCHSIZE + IDSIZE)
  180.                     syserr("write error into temp repl file");
  181.             }
  182.             if (end > 0)
  183.             {
  184.                 if ((k = fread(Batchbuf.bbuf, 1, end, Repl_outfp)) != end)
  185.                     syserr("read error2 from replace file %d", k);
  186.                 if (fwrite(&Batchbuf, 1, end + IDSIZE, fp) != end + IDSIZE)
  187.                     syserr("write error into temp repl file");
  188.             }
  189.             fclose(fp);
  190.             fclose(Repl_outfp);
  191.             unlink(ztack(REPL_OUT, Fileset));
  192.             rmbatch();
  193.             if (link(filname, batchname()) == -1)
  194.                 syserr("can't link %s", batchname());
  195.             unlink(filname);
  196.             Batch_cnt = BATCHSIZE;
  197.             Batch_dirty = FALSE;
  198.             if ((Batch_fp = open(batchname(), O_RDWR)) < 0)
  199.                 syserr("can't open new batch file");
  200.             getbatch(&Batchhd, sizeof Batchhd);
  201.         }
  202.         unlink(replbtree);
  203.     }
  204.  
  205.     while (tupcnt--)
  206.     {
  207.         getbatch(&oldtid, Batchhd.tido_size);    /* read old tid */
  208.         getbatch(oldtup, Batchhd.tupo_size);    /* and portions of old tuple */
  209.         if (!rel.reldum.reldim)
  210.             getbatch(newtup, Batchhd.tupn_size);    /* and the newtup */
  211.         else
  212.         {
  213.             if (Batchhd.tupn_size > 0)
  214.             {
  215.                 getbatch(newtup, Batchhd.tupn_size - rel.reldum.reldim * LIDSIZE);
  216.                 batchcnt = Batch_cnt;
  217.                 tp = newtup + Batchhd.tupn_size - rel.reldum.reldim * LIDSIZE;
  218.                 getbatch(tp, rel.reldum.reldim * LIDSIZE);
  219.             }
  220.         }
  221.  
  222.         switch (mode)
  223.         {
  224.  
  225.           case mdDEL:
  226.             if ((i = delete(&rel, &oldtid)) < 0)
  227.                 syserr("prim:bad del %d %s", i, Batchhd.rel_name);
  228.             break;
  229.  
  230.           case mdREPL:
  231.             if (i = replace(&rel, &oldtid, newtup, TRUE))
  232.             {
  233.                 /* if newtuple is a duplicate, then ok */
  234.                 if (i == 1)
  235.                 {
  236.                     if (rel.reldum.reldim)
  237.                         ++Resp.resp_tups;
  238.                     break;
  239.                 }
  240.                 if (i == 3)
  241.                 {
  242.                     bmove(newtup + rel.reldum.relwid - LIDSIZE, &new_lid, LIDSIZE);
  243.                     bmove(tp, bad_lid, LIDSIZE * rel.reldum.reldim);
  244.                     for(j = 0; j < rel.reldum.reldim; ++j)
  245.                         strcpy(bad[j], locv(bad_lid[j]));
  246.                     switch (rel.reldum.reldim)
  247.                     {
  248.                     case 1:
  249.                         nferror(BADLID1, trim_relname(rel.reldum.relid), bad[0], 0);
  250.                         break;
  251.                     case 2:
  252.                         nferror(BADLID2, trim_relname(rel.reldum.relid), bad[0], bad[1], 0);
  253.                         break;
  254.                     case 3:
  255.                         nferror(BADLID3, trim_relname(rel.reldum.relid), bad[0], bad[1], bad[2], 0);
  256.                         break;
  257.                     }                    
  258.                     Batch_cnt = batchcnt + LIDSIZE * (rel.reldum.reldim - 1);
  259.                     lid = -1;
  260.                     putbatch(&lid, LIDSIZE);
  261.                     break;
  262.                 }
  263.                 /* if this is recovery and oldtup not there, try to insert newtup */
  264.                 if (Batch_recovery && i == 2)
  265.                     goto upinsert;
  266.                 syserr("prim:Non-functional replace on %s (%d)", i, Batchhd.rel_name);
  267.             }
  268.             Resp.resp_tups++;
  269.             break;
  270.  
  271.           case mdAPP:
  272.           upinsert:
  273.             if ((i = insert(&rel, &oldtid, newtup, TRUE)) < 0)
  274.                 syserr("prim:bad insert %d %s", i, Batchhd.rel_name);
  275.              if (i == 2)
  276.             {
  277.                 tp = newtup + rel.reldum.relwid - rel.reldum.reldim * LIDSIZE;
  278.                 bmove(tp, bad_lid, LIDSIZE * rel.reldum.reldim);
  279.                 for (j = 0; j < rel.reldum.reldim; ++j)
  280.                     strcpy(bad[j], locv(bad_lid[j]));
  281.                 switch (rel.reldum.reldim)
  282.                 {
  283.                 case 1:
  284.                     nferror(BADLID1, trim_relname(rel.reldum.relid), bad[0], 0);
  285.                     break;
  286.                 case 2:
  287.                     nferror(BADLID2, trim_relname(rel.reldum.relid), bad[0], bad[1], 0);
  288.                     break;
  289.                 case 3:
  290.                     nferror(BADLID3, trim_relname(rel.reldum.relid), bad[0], bad[1], bad[2], 0);
  291.                     break;
  292.                 }                    
  293.                 oldtid = -1;
  294.             }
  295.             else if (rel.reldum.reldim > 0)
  296.             {
  297.                 if (batchcnt + rel.reldum.reldim * LIDSIZE > BATCHSIZE)
  298.                 {
  299.                     if ((j = lseek(Batch_fp, (long) -(Batch_cnt + BATCHSIZE + 2 * IDSIZE), 1)) < 0)
  300.                         syserr("Lseek error in update");
  301.                     readbatch();
  302.                 }
  303.                 Batch_cnt = batchcnt;
  304.                 tp  =  newtup + rel.reldum.relwid - LIDSIZE * rel.reldum.reldim;
  305.                 putbatch(tp, rel.reldum.reldim * LIDSIZE);
  306.             }
  307.             break;
  308.  
  309.           default:
  310.             syserr("prim:impossible mode %d", mode);
  311.         }
  312.         putbatch(&oldtid, Batchhd.tidn_size);    /* write new tid if necessary */
  313.     }
  314.     if (rel.reldum.reldim > 0)
  315.     /* do deletions in decending lid-value order */
  316.     {
  317.         fclose(Del_infp);
  318.         if (Del_cnt != 0)
  319.         {
  320.             if (Del_cnt > 1)
  321.             {
  322.                 d.reloff[0] = -LIDSIZE;
  323.                 d.relgiven[0] = 0;
  324.                 for (i = 1; i <= rel.reldum.reldim; ++i)
  325.                 {
  326.                     d.reloff[i] = d.reloff[i-1] + LIDSIZE;
  327.                     d.relfrmt[i] = INT;
  328.                     d.relfrml[i] = LIDSIZE;
  329.                     d.relgiven[i] = -i;
  330.                 }
  331.                 d.reldum.relspec = -M_ORDER;
  332.                 d.reldum.relatts = rel.reldum.reldim;
  333.                 d.reldum.relwid = LIDSIZE * rel.reldum.reldim;
  334.                 sortfile(delbtree, &d, TRUE);
  335.             }
  336.             btreename(rel.reldum.relid, btree);
  337.             del_cnt = Del_cnt;
  338.             if (del_cnt == 1)
  339.                 concat(DEL_IN, Fileset, out);
  340.             else
  341.                 concat(DEL_OUT, Fileset, out);
  342.             if ((Del_outfp = fopen(out, "r")) == NULL)
  343.                 syserr("can't open delete file in update for reading\n");
  344.             while (del_cnt--)
  345.             {
  346.                 if (fread(old_lid, 1, LIDSIZE * rel.reldum.reldim, Del_outfp) != LIDSIZE * rel.reldum.reldim)
  347.                     syserr("tup_buf read error");
  348.  
  349.                 if (delete_btree(old_lid, rel.reldum.reldim) < 0)
  350.                 {
  351.                     printf("DELETE ERROR: %s: bad lid(s)\n", trim_relname(rel.reldum.relid));
  352.                     for (i = 0; i < rel.reldum.reldim; ++i)
  353.                         printf("\tlid%d=%ld\n", i + 1, old_lid[i]);
  354.                     syserr("DELETE ERROR");
  355.                 }
  356.             }
  357.             fclose(Del_outfp);
  358.             unlink(out);
  359.         }
  360.         unlink(delbtree);
  361.     }
  362.  
  363.     /* fix the tupchanged count if delete or append */
  364.     if (mode != mdREPL)
  365.         Resp.resp_tups = rel.reladds >= 0 ? rel.reladds : -rel.reladds;
  366.     /* close the relation but secupdate will still use the decriptor */
  367.     temp = rel.reladds;
  368.     if (i = closer(&rel))
  369.         syserr("prim:close err %d %s", i, Batchhd.rel_name);
  370.     rel.reladds = temp;
  371.     batchflush();
  372.  
  373.     /* if this relation is indexed, update the indexes */
  374.     if (rel.reldum.relindxd > 0)
  375.         secupdate(&rel);
  376.     if (rel.reldum.reldim > 0)
  377.         btreeupdate(&rel);
  378.     rmbatch();
  379.  
  380. #    ifdef xZTR1
  381.     if (tTf(48, 2))
  382.         printf("%ld tups changed\n", Resp.resp_tups);
  383. #    endif
  384.     return (0);
  385. }
  386.