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

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  ind_ins.c  - Index Control Programm
  3.  *               functions dealing with insertion into an index
  4.  *               Kernel of GNU SQL-server 
  5.  *
  6.  * This file is a part of GNU SQL Server
  7.  *
  8.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  9.  *  Developed at the Institute of System Programming
  10.  *  This file is written by  Vera Ponomarenko
  11.  *
  12.  *  This program is free software; you can redistribute it and/or modify
  13.  *  it under the terms of the GNU General Public License as published by
  14.  *  the Free Software Foundation; either version 2 of the License, or
  15.  *  (at your option) any later version.
  16.  *
  17.  *  This program is distributed in the hope that it will be useful,
  18.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  *  GNU General Public License for more details.
  21.  *
  22.  *  You should have received a copy of the GNU General Public License
  23.  *  along with this program; if not, write to the Free Software
  24.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25.  *
  26.  *  Contacts:   gss@ispras.ru
  27.  *
  28.  */
  29. /* $Id: ind_ins.c,v 1.247 1997/04/15 11:45:41 vera Exp $ */
  30. #include "xmem.h"
  31. #include <assert.h>
  32. #include "destrn.h"
  33. #include "strml.h"
  34. #include "fdcltrn.h"
  35. struct des_field *d_f, *d_f2;
  36. u2_t *afn;
  37. u2_t k_n;
  38. u2_t seg_n;
  39. i4_t k2sz;
  40. i4_t inf_size;
  41. u2_t uniq_key;
  42. ARR_DECL     (thread_s,u2_t,no_static); /* declaration of dynamic stack/array 'thread_s'. */
  43. ARR_PROC_DECL(thread_s,u2_t,no_static); /* declaration of routines for it                 */
  44. #define FIND_LAST_KEY(asp,elsz,lkey,lkey2,keysz)
  45. {
  46.   char *pnt, *lastb;
  47.   u2_t n;
  48.   lastb = asp + ((struct ind_page *) asp)->ind_off;
  49.   pnt = asp + indphsize;
  50.   assert(pnt < lastb);
  51.   while (pnt < lastb)
  52.     {
  53.       n = t2bunpack (pnt);
  54.       pnt += size2b;
  55.       lkey = pnt;
  56.       keysz = kszcal (lkey, afn, d_f);
  57.       pnt += keysz + n * elsz;
  58.     }
  59.   lkey2 = pnt - elsz;
  60. }
  61. int
  62. check_ind_page (char *asp)
  63. {
  64.   char *cur_key, *prev_key, *a, *lastb;
  65.   u2_t n;
  66.   i4_t ksz, elsz;
  67.   struct ind_page *indph;
  68.   indph = (struct ind_page *) asp;
  69.   if (indph->ind_wpage == LEAF)
  70.     elsz = k2sz + inf_size;
  71.   else
  72.     elsz = k2sz + size2b;
  73.   lastb = asp + indph->ind_off;
  74.   a = asp + indphsize;
  75.   n = t2bunpack (a);
  76.   a += size2b;
  77.   prev_key = a;
  78.   ksz = kszcal (prev_key, afn, d_f);
  79.   a += ksz + n * elsz;
  80.   while (a < lastb)
  81.     {
  82.       n = t2bunpack (a);
  83.       a += size2b;
  84.       cur_key = a;
  85.       ksz = kszcal (cur_key, afn, d_f);
  86.       if (cmpkeys (k_n, afn, d_f, cur_key, prev_key) <= 0)
  87.         return -1;
  88.       a += ksz + n * elsz;
  89.       prev_key = cur_key;
  90.     }
  91.   return 0;
  92. }
  93. static int
  94. insrep (char *asp, char *lastb, char *key, char *key2,
  95.         i4_t elsz, char **bbeg, char **loc)
  96. {
  97.   char *a, *ckey;
  98.   u2_t n;
  99.   i4_t agsz = 0, keysz, ksz, l, l2;
  100.   keysz = kszcal (key, afn, d_f);
  101.   a = asp + indphsize;
  102.   for (; a < lastb; a += agsz)
  103.     {
  104.       *bbeg = a;
  105.       n = t2bunpack (a);
  106.       assert (n < BD_PAGESIZE / 2);
  107.       ckey = a + size2b;
  108.       ksz = kszcal (ckey, afn, d_f);
  109.       if ((l = cmpkeys (k_n, afn, d_f, ckey, key)) == 0)
  110. {
  111.   if (uniq_key == UNIQ)
  112.     return (0);
  113.   a += size2b + ksz;
  114.   for (; n != 0; n--, a += elsz)
  115.             {
  116.               if ((l2 = cmp2keys (d_f2->field_type, a, key2)) > 0)
  117.                 break;
  118.               assert (l2 != 0);      /* Tne second key isn't unique */
  119.             }
  120.   *loc = a;
  121.   return (elsz);
  122. }
  123.       else if (l > 0)
  124. {
  125.   *loc = a;
  126.   return (size2b + keysz + elsz);
  127. }
  128.       agsz = size2b + ksz + n * elsz;
  129.     }
  130.   *bbeg = a;
  131.   *loc = a;
  132.   return (size2b + keysz + elsz);
  133. }
  134. static void
  135. icp_insrec (char *key, char *key2, char *inf, i4_t infsz, char *beg,
  136.             char *loc, char *lastb, u2_t pn, char *asp, i4_t idm)
  137. {
  138.   char *src, *dst;
  139.   u2_t fs;
  140.   i4_t sz;
  141.   fs = lastb - loc;
  142.   if (beg == loc)
  143.     {
  144.       i4_t keysz;
  145.       keysz = kszcal (key, afn, d_f);
  146.       sz = size2b + keysz + k2sz + infsz;
  147.       if (asp != NULL)
  148. recmjform (SHF, seg_n, pn, idm, loc - asp, fs, NULL, -sz);
  149.       for (src = lastb - 1, dst = src + sz; fs != 0; fs--)
  150. *dst-- = *src--;
  151.       t2bpack (1, beg);
  152.       loc += size2b;
  153.       bcopy (key, loc, keysz);
  154.       loc += keysz;
  155.     }
  156.   else
  157.     {
  158.       sz = k2sz + infsz;
  159.       if (asp != NULL)
  160. recmjform (SHF, seg_n, pn, idm, loc - asp, fs, NULL, -sz);
  161.       for (src = lastb - 1, dst = src + sz; fs != 0; fs--)
  162. *dst-- = *src--;
  163.       if (asp != NULL)
  164. recmjform (OLD, seg_n, pn, idm, beg - asp, size2b, beg, 0);
  165.       mod_nels (1, beg);
  166.     }
  167.   bcopy (key2, loc, k2sz);
  168.   bcopy (inf, loc + k2sz, infsz);
  169. }
  170. static int
  171. repet1 (char *asp, char *bbeg, char *a, i4_t elsz, char *middleb, char **lkey,
  172.         char **lkey2, char **lnkey, char **lnkey2, i4_t *n1, u2_t *nels,
  173.         i4_t *lbeg, i4_t *lnbeg, i4_t *pr, char *frkey)
  174. {
  175.   char *lastb, *ckey;
  176.   i4_t ksz, agsz, n2;
  177.   u2_t n;
  178.   lastb = asp + ((struct ind_page *) asp)->ind_off;
  179.   ckey = *lnkey;
  180.   n = t2bunpack (bbeg);
  181.   assert (n < BD_PAGESIZE / 2);
  182.   ksz = kszcal (bbeg + size2b, afn, d_f);
  183.   if (bbeg != a)
  184.     { /* not new element */
  185.       char *b;
  186.       b = bbeg;
  187.       b += size2b + ksz;
  188.       for (; b != a; n--)
  189. b += elsz;
  190.       for (; n != 0; n--)
  191. if (a + elsz < middleb)
  192.   {
  193.     *lnkey2 = a;
  194.     a += elsz;
  195.   }
  196. else
  197.   goto m1;
  198.     }
  199.   for (; a < lastb;)
  200.     {
  201.       bbeg = a;
  202.       n = t2bunpack (a);
  203.       assert (n < BD_PAGESIZE / 2);
  204.       ksz = kszcal (a + size2b, afn, d_f);
  205.       agsz = size2b + ksz + n * elsz;
  206.       if (a + agsz < middleb)
  207. {
  208.   *lnkey = a + size2b;
  209.   a += agsz;
  210.   *lnkey2 = a - elsz;
  211. }
  212.       else
  213. break;
  214.     }
  215.   ckey = a + size2b;
  216.   agsz = size2b + ksz + elsz;
  217.   if (a + agsz < middleb)
  218.     {
  219.       *lnkey = a + size2b;
  220.       a += agsz;
  221.       *lnkey2 = a - elsz;
  222.       for (n--; n != 0; n--)
  223. if (a + elsz < middleb)
  224.   {
  225.     *lnkey2 = a;
  226.     a += elsz;
  227.   }
  228. else
  229.   break;
  230.     }
  231.   else
  232.     n = 0;
  233. m1:
  234.   n2 = lastb - a;
  235.   *n1 = a - asp;
  236.   *lnbeg = bbeg - asp;
  237.   if (n != 0)
  238.     {
  239.       ksz = kszcal (*lnkey, afn, d_f);
  240.       n2 += size2b + ksz;
  241.       *nels = n;
  242.       a += n * elsz;
  243.     }
  244.   else
  245.     *nels = 0;
  246.   for (; a < lastb; a += ksz + n * elsz)
  247.     {
  248.       bbeg = a;
  249.       n = t2bunpack (a);
  250.       assert (n < BD_PAGESIZE / 2);
  251.       a += size2b;
  252.       ckey = a;
  253.       ksz = kszcal (a, afn, d_f);
  254.     }
  255.   *lbeg = a - bbeg;
  256.   if (frkey != NULL)
  257.     if (cmpkeys (k_n, afn, d_f, ckey, frkey) == 0)
  258.       {
  259. *pr = 0;
  260. n2 -= ksz + size2b;
  261.       }
  262.     else
  263.       *pr = 1;
  264.   *lkey = ckey;
  265.   *lkey2 = lastb - elsz;
  266.   return (n2);
  267. }
  268. static int
  269. repttn (char *mas, char *lastb, i4_t elsz, char *middleb, char **lkey,
  270.         char **lkey2, char **lnkey, char **lnkey2, i4_t *n1,
  271.         u2_t *nels, i4_t *lbeg, i4_t *lnbeg, i4_t *pr, char *frkey)
  272. {
  273.   char *a, *bbeg, *ckey;
  274.   i4_t agsz = 0, ksz, n2;
  275.   u2_t n;
  276.   a = mas;
  277.   do      
  278.     {
  279.       n = t2bunpack (a);
  280.       assert (n < BD_PAGESIZE / 2);
  281.       bbeg = a - agsz;
  282.       ksz = kszcal (a + size2b, afn, d_f);
  283.       agsz = size2b + ksz + n * elsz;
  284.       if (a + agsz > middleb)
  285. break;
  286.       a += agsz;
  287.     }
  288.   while( a < lastb);
  289.   *lnkey = bbeg + size2b;
  290.   *lnkey2 = a - elsz;
  291.   *lnbeg = bbeg - mas;
  292.   bbeg = a;
  293.   agsz = size2b + ksz + elsz;
  294.   if (a + agsz < middleb)
  295.     {
  296.       *lnkey = a + size2b;
  297.       *lnbeg = a - mas;
  298.       a += agsz;
  299.       *lnkey2 = a - elsz;
  300.       for (n--; n != 0; n--)
  301. if (a + elsz < middleb)
  302.   {
  303.     *lnkey2 = a;
  304.     a += elsz;
  305.   }
  306. else
  307.   break;
  308.     }
  309.   else
  310.     n = 0;
  311.   *n1 = a - mas;
  312.   n2 = lastb - a;
  313.   if (n != 0)
  314.     {
  315.       n2 += size2b + ksz;
  316.       *nels = n;
  317.       a += n * elsz;
  318.     }
  319.   else
  320.     *nels = 0;
  321.   for (; a < lastb; a += ksz + n * elsz)
  322.     {
  323.       bbeg = a;
  324.       n = t2bunpack (a);
  325.       assert (n < BD_PAGESIZE / 2);
  326.       a += size2b;
  327.       ksz = kszcal (a, afn, d_f);
  328.     }
  329.   ckey = bbeg + size2b;
  330.   *lbeg = a - bbeg;
  331.   if (frkey != NULL)
  332.     {
  333.       if (cmpkeys (k_n, afn, d_f, ckey, frkey) == 0)
  334. {
  335.   *pr = 0;
  336.   n2 -= ksz + size2b;
  337. }
  338.       else
  339. *pr = 1;
  340.     }
  341.   *lkey = ckey;
  342.   *lkey2 = lastb - elsz;
  343.   return (n2);
  344. }
  345. static char *
  346. pereliv (char *asp, i4_t n, u2_t nels, char *key, char *mas, i4_t massz)
  347.                 /* n - a number of bytes from the first page */
  348.       /* nels - element number from the first page */
  349. {
  350.   char *a, *b, *c, *lastb;
  351.   lastb = asp + ((struct ind_page *) asp)->ind_off;
  352.   for (b = lastb - 1, a = b + n, c = asp + indphsize; b >= c;)
  353.     *a-- = *b--;
  354.   a = asp + indphsize;
  355.   if (nels != 0)
  356.     {
  357.       i4_t ksz;
  358.       t2bpack (nels, a);
  359.       a += size2b;
  360.       ksz = kszcal (key, afn, d_f);
  361.       bcopy (key, a, ksz);
  362.       a += ksz;
  363.     }
  364.   bcopy (mas, a, massz);
  365.   return (a + massz);
  366. }
  367. static void
  368. per22 (u2_t pn, u2_t rbrpn, i4_t n1, i4_t n2, u2_t nels, i4_t lbeg, i4_t lnbeg,
  369.        i4_t pr, i4_t prpg, i4_t sz, char *key, char *key2, char *inf, char *lnkey,
  370.        i4_t offbeg, i4_t offloc)         /* if pr==0 then lastkey==frkey */
  371. {
  372.   char *a, *lastb, *asp, *aspr, *end1;
  373.   u2_t fnels;  /* element number of the first aggregate of a right brother */
  374.   struct ind_page *indph, *indphr;
  375.   i4_t idm, idmr;
  376.   struct A pg, pgr;
  377.   asp = getwl (&pg, seg_n, pn); /* get pn without lock */
  378.   aspr = getwl (&pgr, seg_n, rbrpn); /* get pn without lock */
  379.   indph = (struct ind_page *) asp;
  380.   indphr = (struct ind_page *) aspr;
  381.   idm = ++((struct p_head *) asp)->idmod;
  382.   idmr = ++((struct p_head *) aspr)->idmod;
  383.   if (pr == 0)
  384.     recmjform (OLD, seg_n, rbrpn, idmr, indphsize, size2b, aspr + indphsize, 0);
  385.   fnels = t2bunpack (aspr + indphsize);
  386.   if (nels != 0)
  387.     {
  388.       recmjform (OLD, seg_n, pn, idm, lnbeg, size2b, asp + lnbeg, 0);
  389.       mod_nels ((-nels), asp + lnbeg);
  390.     } 
  391.   lastb = asp + indph->ind_off;
  392.   end1 = asp + n1;
  393.   recmjform (OLD, seg_n, pn, idm, n1, lastb - end1, end1, 0);
  394.   recmjform (SHF, seg_n, rbrpn, idmr, n2 + indphsize,
  395.              indphr->ind_off - indphsize, NULL, -n2);
  396.   a = pereliv (aspr, n2, nels, lnkey, end1, indph->ind_off - n1);
  397.   if (pr == 0)
  398.     {
  399.       if (lbeg > n2)
  400. lbeg = n2;
  401.       mod_nels (fnels, a - lbeg);
  402.       if (lbeg == n2)
  403. {
  404.           char *b;
  405.           i4_t size;
  406.   b = a + size2b + kszcal (aspr + indphsize + size2b, afn, d_f);
  407.           size = aspr + indphr->ind_off + n2 - b;
  408.           bcopy (b, a, size);
  409. }
  410.     }
  411.   if (prpg == 1)
  412.     { /* An insertion in the first page */
  413.       icp_insrec (key, key2, inf, inf_size, asp + offbeg,
  414.                   asp + offloc, end1, pn, asp, idm);
  415.       n1 += sz;
  416.     }
  417.   else /* An insertion in the right brother page */
  418.     icp_insrec (key, key2, inf, inf_size, aspr + offbeg,
  419.                 aspr + offloc, a, rbrpn, aspr, idmr);
  420.   a = (char *) &indph->ind_off;
  421.   recmjform (OLD, seg_n, pn, idm, a - asp, size2b, a, 0);
  422.   indph->ind_off = n1;
  423.   a = (char *) &indphr->ind_off;
  424.   recmjform (OLD, seg_n, rbrpn, idmr, a - aspr, size2b, a, 0);
  425.   indphr->ind_off += n2;
  426.   assert (check_ind_page (asp) == 0);
  427.   putwul (&pg, 'm'); /* put page without unlock */
  428.   assert (check_ind_page (aspr) == 0);
  429.   putwul (&pgr, 'm');
  430. }
  431. static int
  432. rep_2_3 (char *mas, i4_t massz, i4_t elsz, char *aspr, i4_t *n1, u2_t * nels,
  433.          i4_t *lbeg, i4_t *lnbeg, char **nkey, char **nkey2, i4_t *pr)
  434. {
  435.   char *middleb, *frkey, *lkey, *lkey2, *lnkey, *lnkey2;
  436.   i4_t off, n2, middle;
  437.   off = ((struct ind_page *) aspr)->ind_off;
  438.   middleb = mas + (massz + off - indphsize) / 3;
  439.   frkey = aspr + indphsize + size2b;
  440.   n2 = repttn (mas, mas + massz, elsz, middleb, &lkey, &lkey2, &lnkey,
  441.                &lnkey2, n1, nels, lbeg, lnbeg, pr, frkey);
  442.   middle = (n2 + off - indphsize) / 2;
  443.   if (off - middle > indphsize)
  444.     {
  445.       char *a;
  446.       u2_t n, agsz = 0;
  447.       middleb = aspr + ((n2 + off) / 2 - n2);
  448.       for (a = aspr + indphsize; a + agsz < middleb;)
  449. {
  450.   a += agsz;
  451.   n = t2bunpack (a);
  452.           assert (n < BD_PAGESIZE / 2);
  453.   a += size2b;
  454.   agsz = kszcal (a, afn, d_f) + n * elsz;
  455. }
  456.       *nkey = a;
  457.       *nkey2 = a + agsz - elsz;
  458.       n2 = a + agsz - aspr;
  459.       if (n2 == indphsize)
  460. n2 = 0;
  461.     }
  462.   else
  463.     n2 = 0;
  464.   return (n2);
  465. }
  466. static int
  467. crnlev (struct A *pg, char *mas, char *lastb, i4_t wpage)
  468. { /* a creation of a new level */
  469.   char *a, *b, *middleb, *asp;
  470.   char *lnkey, *lnkey2, *lkey, *lkey2, *inf1, *inf2;
  471.   i4_t n1, lbeg, lnbeg, pr, ksz, size, elsz;
  472.   u2_t newpn1, newpn2, nels, offn;
  473.   struct A pgn;
  474.   struct ind_page *indph;
  475.   i4_t idm;
  476.   if (wpage == LEAF)
  477.     elsz = k2sz + inf_size;
  478.   else
  479.     elsz = k2sz + size2b;
  480.   middleb = mas + (lastb - mas) / 2;
  481.   repttn (mas, lastb, elsz, middleb, &lkey, &lkey2, &lnkey,
  482.           &lnkey2, &n1, &nels, &lbeg, &lnbeg, &pr, NULL);
  483.   if (lenforce ()< 0)
  484.     {
  485.       putwul (pg, 'n');
  486.       return (-1);
  487.     }
  488.   newpn1 = getempt (seg_n);
  489.   asp = getnew (&pgn, seg_n, newpn1); /* get new page */
  490.   indph = (struct ind_page *) asp;
  491.   bcopy (mas, asp + indphsize, n1);
  492.   indph->ind_off = n1 + indphsize;
  493.   if (nels != 0)
  494.     mod_nels ((-nels), asp + lnbeg + indphsize);
  495.   newpn2 = getempt (seg_n);
  496.   indph->ind_nextpn = newpn2;
  497.   indph->ind_wpage = wpage;
  498.   offn = indph->ind_off;
  499.   assert (check_ind_page (asp) == 0);
  500.   putwul (&pgn, 'm');
  501.   asp = getnew (&pgn, seg_n, newpn2); /* get new page */
  502.   indph = (struct ind_page *) asp;
  503.   a = asp + indphsize;
  504.   ksz = kszcal (lnkey, afn, d_f);
  505.   if (nels != 0)
  506.     {
  507.       /*      write_key (nels, a, lnkey, ksz);*/
  508.       t2bpack (nels, a);
  509.       a += size2b;
  510.       bcopy (lnkey, a, ksz);
  511.       a += ksz;
  512.     }
  513.   b = mas + n1;
  514.   size = lastb - b;
  515.   bcopy (b, a, size);
  516.   a += size;
  517.   indph->ind_nextpn = (u2_t) ~ 0;
  518.   indph->ind_off = a - asp;
  519.   indph->ind_wpage = wpage;
  520.   offn = indph->ind_off;
  521.   assert (check_ind_page (asp) == 0);
  522.   putwul (&pgn, 'm');
  523.   inf1 = (char *) &newpn1;
  524.   inf2 = (char *) &newpn2;
  525.   asp = pg->p_shm;
  526.   indph = (struct ind_page *) asp;
  527.   idm = ++((struct p_head *) asp)->idmod;
  528.   a = asp + sizeof (struct p_head);
  529.   b = asp + indph->ind_off;
  530.   recmjform (OLD, seg_n, pg->p_pn, idm, a - asp, b - a, a, 0);
  531.   a = asp + indphsize + size2b;
  532.   bcopy (lnkey, a, ksz);
  533.   a += ksz;
  534.   bcopy (lnkey2, a, k2sz);
  535.   a += k2sz;
  536.   t2bpack (newpn1, a);
  537.   a += size2b;
  538.   if (cmpkeys (k_n, afn, d_f, lkey, lnkey) == 0)
  539.     nels = 2;
  540.   else
  541.     {
  542.       nels = 1;
  543.       t2bpack (nels, a);
  544.       a += size2b;
  545.       ksz = kszcal (lkey, afn, d_f);
  546.       bcopy (lkey, a, ksz);
  547.       a += ksz;
  548.     }
  549.   t2bpack (nels, asp + indphsize);
  550.   bcopy (lkey2, a, k2sz);
  551.   a += k2sz;
  552.   t2bpack (newpn2, a);
  553.   a += size2b;
  554.   indph->ind_nextpn = (u2_t) ~ 0;
  555.   indph->ind_off = a - asp;
  556.   indph->ind_wpage = IROOT;
  557.   assert (check_ind_page (asp) == 0);
  558.   putwul (pg, 'm');
  559.   return (0);
  560. }
  561. static i4_t rbrup (u2_t pn, u2_t rbrpn, char *mas, i4_t massz,
  562.                   char *last_key, char *last_k2);
  563. static char *
  564. findkey (char *asp, char *key, char *key2, i4_t elsz, char **loc)
  565. {
  566.   char *a, *lastb, *bbeg;
  567.   u2_t n;
  568.   i4_t ksz;
  569.   lastb = asp + ((struct ind_page *) asp)->ind_off;
  570.   for (a = asp + indphsize; a < lastb; a += ksz + n * elsz)
  571.     {
  572.       bbeg = a;
  573.       n = t2bunpack (a);
  574.       a += size2b;
  575.       ksz = kszcal (a, afn, d_f);
  576.       if (cmpkeys (k_n, afn, d_f, a, key) == 0)
  577. {
  578.   a += ksz;
  579.   for (; n != 0; n--, a += elsz)
  580.     if (cmp2keys (d_f2->field_type, a, key2) == 0)
  581.       {
  582. *loc = a;
  583. return (bbeg);
  584.       }
  585. }
  586.     }
  587.   return (NULL);
  588. }
  589. static int
  590. div_upmod (char *lkey, char *lkey2, char *lnkey,
  591.            char *lnkey2, u2_t pn, u2_t * newpn)
  592. {
  593.   char *asp, *a, *inf, *lastb;
  594.   char *beg, *loc;
  595.   i4_t elsz, insz, off;
  596.   struct ind_page *indph;
  597.   struct A pg;
  598.   i4_t idm;
  599.   char ninf[size2b];
  600.   t2bpack (pn, ninf);
  601.   pn = *(--thread_s.u);
  602.   asp = getwl (&pg, seg_n, pn); /* get pn without lock */
  603.   indph = (struct ind_page *) asp;
  604.   elsz = k2sz + size2b;
  605.   beg = findkey (asp, lkey, lkey2, elsz, &loc);
  606.   inf = loc + k2sz;
  607.   off = indph->ind_off;
  608.   lastb = asp + off;
  609.   insz = insrep (asp, lastb, lnkey, lnkey2, elsz, &beg, &loc);
  610.   assert (insz != 0);
  611.   if (off + insz > BD_PAGESIZE)
  612.     {
  613.       char *mas, *d;
  614.       i4_t massz, ans;
  615.       massz = off + insz - indphsize;
  616.       mas = (char *) xmalloc (massz);
  617.       d = asp + indphsize;
  618.       bcopy (d, mas, off - indphsize);
  619.       *newpn = getempt (seg_n);
  620.       t2bpack (*newpn, mas + (inf - d));
  621.       beg = mas + (beg - d);
  622.       loc = mas + (loc - d);
  623.       lastb = mas + massz - insz;
  624.       icp_insrec (lnkey, lnkey2, ninf, size2b, beg, loc, lastb, 0, NULL, 0);
  625.       if (indph->ind_wpage != IROOT)
  626. {
  627.           char last_key[BD_PAGESIZE];
  628.           char last_k2[BD_PAGESIZE];
  629.           u2_t rbrpn, keysz = 0 ;
  630.           
  631.           FIND_LAST_KEY (asp, elsz, lkey, lkey2, keysz);
  632.           assert (keysz != 0 );
  633.           bcopy (lkey, last_key, keysz);
  634.           bcopy (lkey2, last_k2, k2sz);
  635.           rbrpn = indph->ind_nextpn;
  636.   putwul (&pg, 'n');
  637.   ans = rbrup (pn, rbrpn, mas, massz, last_key, last_k2);
  638. }
  639.       else
  640.         ans = crnlev (&pg, mas, lastb + insz, BTWN);
  641.       if (ans < 0)
  642. emptypg (seg_n, *newpn, 'n');
  643.       xfree ((void *) mas);
  644.       return (ans);
  645.     }
  646.   upunlock ();
  647.   if (lenforce ()< 0)
  648.     {
  649.       putwul (&pg, 'n');
  650.       return (-1);
  651.     }
  652.   *newpn = getempt (seg_n);
  653.   idm = ++((struct p_head *) asp)->idmod;
  654.   recmjform (OLD, seg_n, pn, idm, inf - asp, size2b, inf, 0);
  655.   t2bpack (*newpn, inf);
  656.   icp_insrec (lnkey, lnkey2, ninf, size2b, beg, loc, lastb, pn, asp, idm);
  657.   a = (char *) &indph->ind_off;
  658.   recmjform (OLD, seg_n, pn, idm, a - asp, size2b, a, 0);
  659.   indph->ind_off += insz;
  660.   assert (check_ind_page (asp) == 0);
  661.   putwul (&pg, 'm');
  662.   return (0);
  663. }
  664. static int
  665. divsn (u2_t pn, char *mas, i4_t massz, u2_t nextpn,
  666.        i4_t wpage, char *last_key, char *last_key2)
  667. {
  668.   char *lastb, *a, *b, *middleb, *asp;
  669.   i4_t n1, lbeg, lnbeg, pr, elsz;
  670.   char *lkey, *lkey2, *lnkey, *lnkey2;
  671.   u2_t nels, newpn;
  672.   i4_t idm;
  673.   struct ind_page *indph;
  674.   struct A pg;
  675.   lastb = mas + massz;
  676.   middleb = mas + massz / 2;
  677.   if (wpage == LEAF)
  678.     elsz = k2sz + inf_size;
  679.   else
  680.     elsz = k2sz + size2b;
  681.   repttn (mas, lastb, elsz, middleb, &lkey, &lkey2, &lnkey, &lnkey2,
  682.           &n1, &nels, &lbeg, &lnbeg, &pr, (char *) NULL);
  683.   if (div_upmod (last_key, last_key2, lnkey, lnkey2, pn, &newpn) < 0)
  684.     return (-1);
  685.   asp = getwl (&pg, seg_n, pn); /* get pn without lock */
  686.   indph = (struct ind_page *) asp;
  687.   idm = ++((struct p_head *) asp)->idmod;
  688.   a = asp + sizeof (struct p_head);
  689.   b = asp + indph->ind_off;
  690.   recmjform (OLD, seg_n, pn, idm, a - asp, b - a, a, 0);
  691.   bcopy (mas, asp + indphsize, n1);
  692.   if (nels != 0) 
  693.     mod_nels ((-nels), asp + lnbeg);
  694.   indph->ind_off = n1 + indphsize;
  695.   indph->ind_nextpn = newpn;
  696.   assert (check_ind_page (asp) == 0);
  697.   putwul (&pg, 'm');
  698.   asp = getnew (&pg, seg_n, newpn); /* get newpn without lock */
  699.   indph = (struct ind_page *) asp;
  700.   lkey = lastb - lbeg + size2b;
  701.   indph->ind_off = indphsize;
  702.   b = pereliv (asp, 0, nels, lkey, mas + n1, massz - n1);
  703.   indph->ind_off = b - asp;
  704.   indph->ind_nextpn = nextpn;
  705.   indph->ind_wpage = wpage;
  706.   assert (check_ind_page (asp) == 0);
  707.   putwul (&pg, 'm'); /* put page without unlock */
  708.   return (0);
  709. }
  710. static int
  711. mlrep1 (char *asp, char *key, char *key2, char *nkey, i4_t *orbeg,
  712.         i4_t *orloc, i4_t *oibeg, i4_t *oiloc, i4_t *sz)
  713. {
  714.   i4_t remsz, elsz, offbef;
  715.   char *rbeg, *rloc;
  716.   elsz = k2sz + size2b;
  717.   remsz = remrep (asp, key, key2, elsz, &rbeg, &rloc, &offbef);
  718.   *orbeg = rbeg - asp;
  719.   *orloc = rloc - asp;
  720.   if (cmpkeys (k_n, afn, d_f, key, nkey) == 0)
  721.     {
  722.       *oibeg = *orbeg;
  723.       *oiloc = *orloc;
  724.       *sz = remsz;
  725.     }
  726.   else
  727.     {
  728.       char *a;
  729.       u2_t n;
  730.       a = asp + offbef;
  731.       *oibeg = offbef;
  732.       n = t2bunpack (a);
  733.       assert (n < BD_PAGESIZE / 2);
  734.       a += size2b;
  735.       *oiloc = *oibeg;
  736.       if (cmpkeys (k_n, afn, d_f, a, nkey) == 0)
  737.         {
  738.           *oiloc += size2b + kszcal (nkey, afn, d_f) + n * elsz;
  739.           *sz = elsz;
  740.         }
  741.       else
  742.         {
  743.           *oibeg = *oiloc = *orbeg;
  744.           *sz = size2b + kszcal (nkey, afn, d_f) + elsz;
  745.         }
  746.     }
  747.   return (remsz);
  748. }
  749. static int
  750. upmod_2_3 (char *lkey, char *lkey2, char *lnkey, char *lnkey2,
  751.            char *nkey, char *nkey2, u2_t * newpn)
  752. { /* a repetition of a modification of an uplevel for a division 2 on 3 */
  753.   char *a, *asp, *lastb;
  754.   u2_t uppn;
  755.   struct ind_page *indph;
  756.   struct A pg;
  757.   i4_t rbeg, rloc, ibeg1, iloc1, ibeg2, iloc2;
  758.   i4_t remsz, sz1, sz2, elsz, ksz_lnkey, ksz_nkey, off, dopsz;
  759.   char inf1[size2b], inf2[size2b], *beg, *loc;
  760.   i4_t idm;
  761.   uppn = *(--thread_s.u);
  762.   asp = getwl (&pg, seg_n, uppn); /* get pn without lock */
  763.   indph = (struct ind_page *) asp;
  764.   elsz = k2sz + size2b;
  765.   remsz = mlrep1 (asp, lkey, lkey2, lnkey, &rbeg, &rloc, &ibeg1, &iloc1, &sz1);
  766.   ksz_nkey = kszcal (nkey, afn, d_f);
  767.   ksz_lnkey = kszcal (lnkey, afn, d_f);
  768.   if (cmpkeys (k_n, afn, d_f, lnkey, nkey) == 0)
  769.     {
  770.       sz2 = elsz;
  771.       ibeg2 = ibeg1;
  772.       if (ibeg1 == iloc1)
  773.         iloc2 = ibeg1 + sz1 + elsz;
  774.       else
  775.         iloc2 = iloc1 + elsz;
  776.     }
  777.   else
  778.     {
  779.       sz2 = size2b + ksz_nkey + elsz;
  780.       ibeg2 = iloc2 = iloc1 + sz1;
  781.     }
  782.   bcopy (asp + rloc + k2sz, inf1, size2b);
  783.   off = indph->ind_off;
  784.   dopsz = sz1 + sz2 - remsz;
  785.   if (off + dopsz > BD_PAGESIZE)
  786.     {
  787.       char *mas;
  788.       i4_t massz, ans, size;
  789.       
  790.       lastb = asp + off;
  791.       massz = off + dopsz - indphsize;
  792.       mas = (char *) xmalloc (massz);
  793.       size = off - indphsize;
  794.       bcopy (asp + indphsize, mas, size);
  795.       lastb = mas + size;
  796.       beg = mas + rbeg - indphsize;
  797.       loc = mas + rloc - indphsize; 
  798.       icp_remrec (beg, loc, remsz, lastb, elsz, 0, NULL, 0);
  799.       lastb -= remsz;
  800.       beg = mas + ibeg1 - indphsize;
  801.       loc = mas + iloc1 - indphsize;
  802.       icp_insrec (lnkey, lnkey2, inf1, size2b, beg, loc, lastb, 0, NULL, 0);
  803.       lastb += sz1;
  804.       *newpn = getempt (seg_n);
  805.       beg = mas + ibeg2 - indphsize;
  806.       loc = mas + iloc2 - indphsize;
  807.       t2bpack (*newpn, inf2);
  808.       icp_insrec (nkey, nkey2, inf2, size2b, beg, loc, lastb, 0, NULL, 0);
  809.       if (indph->ind_wpage != IROOT)
  810. {
  811.           char last_key[BD_PAGESIZE];
  812.           char last_k2[BD_PAGESIZE];
  813.           u2_t rbrpn, keysz = 0 ;
  814.           
  815.           if (rloc + elsz != off)     /* lkey isn't the last key in pn */
  816.             {
  817.               FIND_LAST_KEY (asp, elsz, lkey, lkey2, keysz);
  818.             }
  819.           else
  820.             keysz = kszcal (lkey, afn, d_f);
  821.           assert ( keysz != 0 ) ;
  822.           bcopy (lkey, last_key, keysz);
  823.           bcopy (lkey2, last_k2, k2sz);
  824.   rbrpn = indph->ind_nextpn;
  825.   putwul (&pg, 'n');
  826.   ans = rbrup (uppn, rbrpn, mas, massz, last_key, last_k2);
  827. }
  828.       else
  829.         ans = crnlev (&pg, mas, mas + massz, BTWN);
  830.       if (ans < 0)
  831. emptypg (seg_n, *newpn, 'n');
  832.       xfree ((void *) mas);
  833.       return (ans);
  834.     }
  835.   else if (rloc + elsz == off && indph->ind_wpage != IROOT)
  836.     {
  837.       putwul (&pg, 'n');
  838.       if (mlreddi (lkey, lkey2, nkey, nkey2, uppn) < 0)
  839.         return (-1);
  840.       asp = getwl (&pg, seg_n, uppn);
  841.     }
  842.   else
  843.     {
  844.       upunlock ();
  845.       if (lenforce ()< 0)
  846. {
  847.   putwul (&pg, 'n');
  848.   return (-1);
  849. }
  850.     }
  851.   *newpn = getempt (seg_n);
  852.   idm = ++((struct p_head *) asp)->idmod;
  853.   lastb = asp + off;
  854.   icp_remrec (asp + rbeg, asp + rloc, remsz, lastb, elsz, uppn, asp, idm);
  855.   lastb -= remsz;
  856.   beg = asp + ibeg1;
  857.   loc = asp + iloc1;
  858.   icp_insrec (lnkey, lnkey2, inf1, size2b, beg, loc, lastb, uppn, asp, idm);
  859.   lastb += sz1;
  860.   insrep (asp, lastb, nkey, nkey2, elsz, &beg, &loc);
  861.   t2bpack (*newpn, inf2);
  862.   icp_insrec (nkey, nkey2, inf2, size2b, beg, loc, lastb, uppn, asp, idm);
  863.   a = (char *) &indph->ind_off;
  864.   recmjform (OLD, seg_n, uppn, idm, a - asp, size2b, a, 0);
  865.   indph->ind_off += dopsz;
  866.   assert (check_ind_page (asp) == 0);
  867.   putwul (&pg, 'm');
  868.   return (0);
  869. }
  870. static void
  871. per_2_3 (u2_t pn, u2_t newpn, u2_t rbrpn, char *mas, i4_t massz, i4_t n1,
  872.          i4_t n2, u2_t nels, i4_t pr, i4_t lbeg, i4_t lnbeg, i4_t wpage)
  873. {
  874.   char *a, *b, *b1, *asp, *aspn, *lkey;
  875.   struct ind_page *indph, *indphn;
  876.   i4_t idm;
  877.   struct A pg, pgn;
  878.   i4_t size;
  879.   asp = getwl (&pg, seg_n, pn); /* get pn without lock */
  880.   indph = (struct ind_page *) asp;
  881.   idm = ++((struct p_head *) asp)->idmod;
  882.   a = asp + sizeof (struct p_head);
  883.   b = asp + indph->ind_off;
  884.   recmjform (OLD, seg_n, pn, idm, a - asp, b - a, a, 0);
  885.   bcopy (mas, asp + indphsize, n1);
  886.   indph->ind_off = n1 + indphsize;
  887.   if (nels != 0)
  888.     mod_nels ((-nels), asp + lnbeg);
  889.   indph->ind_nextpn = newpn;
  890.   assert (check_ind_page (asp) == 0);
  891.   putwul (&pg, 'm');
  892.   aspn = getnew (&pgn, seg_n, newpn); /* get new page */
  893.   indphn = (struct ind_page *) aspn;
  894.   indphn->ind_off = indphsize;
  895.   lkey = mas + lnbeg + size2b;
  896.   b = pereliv (aspn, 0, nels, lkey, mas + n1, massz - n1);
  897.   asp = getwl (&pg, seg_n, rbrpn); /* get rbrpn without lock */
  898.   indph = (struct ind_page *) asp;
  899.   idm = ++((struct p_head *) asp)->idmod;
  900.   a = asp + sizeof (struct p_head);
  901.   b1 = asp + indph->ind_off;
  902.   recmjform (OLD, seg_n, rbrpn, idm, a - asp, b1 - a, a, 0);
  903.   a = asp + indphsize;
  904.   if (pr == 0)
  905.     {
  906.       u2_t fnels;
  907.       fnels = t2bunpack (a);
  908.       a += size2b;
  909.       a += kszcal (a, afn, d_f);
  910.       mod_nels (fnels, b - lbeg);
  911.     }
  912.   size = asp + n2 - a;
  913.   bcopy (a, b, size);
  914.   b += size;
  915.   bcopy (asp + n2, asp + indphsize, indph->ind_off - n2);
  916.   indphn->ind_off = b - aspn;
  917.   indphn->ind_nextpn = rbrpn;
  918.   indphn->ind_wpage = wpage;
  919.   assert (check_ind_page (aspn) == 0);
  920.   putwul (&pgn, 'm');
  921.   indph->ind_off -= n2 - indphsize;
  922.   assert (check_ind_page (asp) == 0);
  923.   putwul (&pg, 'm');
  924. }
  925. static int
  926. rbrnup (u2_t pn, struct A *pgr, char *mas, i4_t massz,
  927.         char *last_key, char *last_k2)
  928. {  /* need rbrpn and a new page for a deletion and an insertion */
  929.   i4_t elsz, n1, n2, pr, lbeg, lnbeg;
  930.   char *lnkey, *lnkey2, *nkey, *nkey2, *aspr;
  931.   u2_t newpn, nels;
  932.   char newkey[BD_PAGESIZE];
  933.   char newk2[BD_PAGESIZE];  
  934.   aspr = pgr->p_shm;
  935.   elsz = k2sz + size2b;
  936.   n2 = rep_2_3 (mas, massz, elsz, aspr, &n1, &nels,
  937.                 &lbeg, &lnbeg, &nkey, &nkey2, &pr);
  938.   if (n2 == 0)
  939.     {
  940.       putwul (pgr, 'n');
  941.       return (divsn (pn, mas, massz, pgr->p_pn, BTWN, last_key, last_k2));
  942.     }
  943.   bcopy ( nkey, newkey, kszcal (nkey, afn, d_f));
  944.   bcopy ( nkey2, newk2, k2sz);
  945.   putwul (pgr, 'n');
  946.   lnkey = mas + lnbeg + size2b;
  947.   lnkey2 = mas + n1 - elsz;
  948.   if (upmod_2_3 (last_key, last_k2, lnkey, lnkey2, newkey, newk2, &newpn) < 0)
  949.     return (-1);
  950.   per_2_3 (pn, newpn, pgr->p_pn, mas, massz, n1, n2, nels, pr, lbeg, lnbeg, BTWN);
  951.   return (0);
  952. }
  953. static int
  954. rbrup (u2_t pn, u2_t rbrpn, char *mas, i4_t massz,
  955.        char *last_key, char *last_k2)
  956. /* rbrobr with a deletion and an insertion */
  957. {
  958.   i4_t off2, dopsz, n1, lbeg, lnbeg, pr, rfreesz, n2;
  959.   char *frkey, *middleb, *lkey, *lkey2, *lnkey, *lnkey2, *asp, *a, *b;
  960.   u2_t nels, fnels;
  961.   struct A pg;
  962.   struct ind_page *indph;
  963.   i4_t idm;
  964.   if (rbrpn == (u2_t) ~ 0)
  965.     return (divsn (pn, mas, massz, (u2_t) ~ 0, BTWN, last_key, last_k2));
  966.   if ((asp = getpg (&pg, seg_n, rbrpn, 's')) == NULL)
  967.     return ( -1);
  968.   thread_s_put (rbrpn);
  969.   frkey = asp + indphsize + size2b;
  970.   off2 = ((struct ind_page *) asp)->ind_off;
  971.   dopsz = massz + indphsize - BD_PAGESIZE;
  972.   rfreesz = BD_PAGESIZE - off2;
  973.   if (rfreesz < dopsz)
  974.     return (rbrnup (pn, &pg, mas, massz, last_key, last_k2));
  975.   /* A location is enough in the right brother */
  976.   middleb = mas + (massz + off2 - indphsize) / 2;
  977.   n2 = repttn (mas, mas + massz, k2sz + size2b, middleb, &lkey, &lkey2,
  978.                &lnkey, &lnkey2, &n1, &nels, &lbeg, &lnbeg, &pr, frkey);
  979.   if (n2 > rfreesz)
  980.     return (rbrnup (pn, &pg, mas, massz, last_key, last_k2));
  981.   putwul (&pg, 'n');
  982.   if (mlreddi (last_key, last_k2, lnkey, lnkey2, pn) < 0)
  983.     return (-1);
  984.   asp = getwl (&pg, seg_n, pn);   /* get pn without lock */
  985.   indph = (struct ind_page *) asp;
  986.   idm = ++((struct p_head *) asp)->idmod;
  987.   a = asp + sizeof (struct p_head);
  988.   b = asp + indph->ind_off;
  989.   recmjform (OLD, seg_n, pn, idm, a - asp, b - a, a, 0);
  990.   bcopy (mas, asp + indphsize, n1);
  991.   indph->ind_off = indphsize + n1;
  992.   if (nels != 0)
  993.     mod_nels ((-nels), asp + lnbeg);
  994.   assert (check_ind_page (asp) == 0);
  995.   putwul (&pg, 'm');
  996.   
  997.   asp = getwl (&pg, seg_n, rbrpn);/* get rbrpn without lock */
  998.   indph = (struct ind_page *) asp;
  999.   idm = ++((struct p_head *) asp)->idmod;
  1000.   a = asp + sizeof (struct p_head);
  1001.   b = asp + indph->ind_off;
  1002.   recmjform (OLD, seg_n, rbrpn, idm, a - asp, b - a, a, 0);
  1003.   fnels = t2bunpack (asp + indphsize);
  1004.   lkey = mas + lnbeg + size2b;
  1005.   a = pereliv (asp, n2, nels, lkey, mas + n1, massz - n1);
  1006.   if (pr == 0)
  1007.     mod_nels (fnels, a - lbeg);
  1008.   indph->ind_off += n2;
  1009.   assert (check_ind_page (asp) == 0);
  1010.   putwul (&pg, 'm'); /* put page without unlock */
  1011.   return (0);
  1012. }
  1013. static int
  1014. rbrnew (struct A *pg, struct A *pgr, i4_t sz, char *key,
  1015.         char *key2, char *inf, i4_t ibeg, i4_t iloc)
  1016.      /* a division 2 on 3 with an insertion at the last level */
  1017. {
  1018.   char *mas, *lastb, *beg, *loc;
  1019.   i4_t massz, n1, n2, lbeg, lnbeg, pr, elsz, ans, size;
  1020.   char *lkey, *lkey2, *nkey, *nkey2, *asp, *aspr;
  1021.   u2_t newpn, nels;
  1022.   
  1023.   asp = pg->p_shm;
  1024.   aspr = pgr->p_shm;
  1025.   size = ((struct ind_page *) asp)->ind_off - indphsize;
  1026.   massz = size + sz;
  1027.   mas = (char *) xmalloc (massz);
  1028.   bcopy (asp + indphsize, mas, size);
  1029.   beg = mas + ibeg - indphsize;
  1030.   loc = mas + iloc - indphsize;
  1031.   lastb = mas + size;
  1032.   icp_insrec (key, key2, inf, inf_size, beg, loc, lastb, 0, NULL, 0);
  1033.   elsz = k2sz + inf_size;
  1034.   putwul (pg, 'n');
  1035.   n2 = rep_2_3 (mas, massz, elsz, aspr, &n1, &nels, &lbeg, &lnbeg, &nkey, &nkey2, &pr);
  1036.   lastb = mas + massz;
  1037.   lkey = lastb - lbeg + size2b;
  1038.   lkey2 = lastb - elsz;
  1039.   if (n2 == 0)
  1040.     {
  1041.       putwul (pgr, 'n');
  1042.       ans = divsn (pg->p_pn, mas, massz, pgr->p_pn, LEAF, lkey, lkey2);
  1043.     }
  1044.   else
  1045.     {
  1046.       char *lnkey, *lnkey2;
  1047.       char newkey[BD_PAGESIZE];
  1048.       char newk2[BD_PAGESIZE];
  1049.       lnkey = mas + lnbeg + size2b;
  1050.       lnkey2 = mas + n1 - elsz;
  1051.       bcopy (nkey, newkey, kszcal (nkey, afn, d_f));
  1052.       bcopy (nkey2, newk2, k2sz);
  1053.       putwul (pgr, 'n');
  1054.       ans = upmod_2_3 (lkey, lkey2, lnkey, lnkey2, newkey, newk2, &newpn);
  1055.       if (ans >= 0)
  1056.         per_2_3 (pg->p_pn, newpn, pgr->p_pn, mas, massz,
  1057.                  n1, n2, nels, pr, lbeg, lnbeg, LEAF);
  1058.     }
  1059.   xfree ((void *) mas);
  1060.   return (ans);
  1061. }
  1062. static int
  1063. div12 (struct A *pg, i4_t sz, char *key, char *key2,
  1064.        char *inf, char *beg, char *loc)
  1065. {
  1066.   char *a, *b, *asp, *aspn, *lastb, *middleb, *lastb2;
  1067.   i4_t elsz, pr, off, n1, lbeg, lnbeg, middle, n2, prpg, ans;
  1068.   struct ind_page *indph, *indphn;
  1069.   struct A pgn;
  1070.   char *lnkey, *lnkey2, *lkey, *lkey2;
  1071.   u2_t nels, newpn, pn;
  1072.   i4_t idm;
  1073.   
  1074.   asp = pg->p_shm;
  1075.   indph = (struct ind_page *) asp;
  1076.   elsz = k2sz + inf_size;
  1077.   off = indph->ind_off;
  1078.   lastb = asp + off;
  1079.   middle = (off + sz + indphsize) / 2;
  1080.   if (loc - asp + sz <= middle)
  1081.     { /* An insertion in the first page */
  1082.       middleb = asp + middle - sz;
  1083.       lnkey = key;
  1084.       lnkey2 = key2;
  1085.       n2 = repet1 (asp, beg, loc, elsz, middleb, &lkey, &lkey2, &lnkey,
  1086.                    &lnkey2, &n1, &nels, &lbeg, &lnbeg, &pr, NULL);
  1087.       prpg = 1;
  1088.     }
  1089.   else
  1090.     { /* An insertion in the second page */
  1091.       middleb = asp + middle;
  1092.       n2 = repttn (asp + indphsize, lastb, elsz, middleb, &lkey, &lkey2,
  1093.                    &lnkey, &lnkey2, &n1, &nels, &lbeg, &lnbeg, &pr, NULL);
  1094.       n1 += indphsize;
  1095.       prpg = 2;
  1096.     }
  1097.   pn = pg->p_pn;
  1098.   ans = (div_upmod (lkey, lkey2, lnkey, lnkey2, pn, &newpn) < 0);
  1099.   if (ans == -1)
  1100.     {
  1101.       putwul (pg, 'n');
  1102.       return (-1);
  1103.     }
  1104.   idm = ++((struct p_head *) asp)->idmod;
  1105.   a = asp + sizeof (struct p_head);
  1106.   b = asp + indph->ind_off;
  1107.   recmjform (OLD, seg_n, pn, idm, a - asp, b - a, a, 0);
  1108.   if (nels != 0)
  1109.     mod_nels ((-nels), asp + lnbeg);
  1110.   lastb = asp + n1;
  1111.   aspn = getnew (&pgn, seg_n, newpn); /* get newpn */
  1112.   indphn = (struct ind_page *) aspn;
  1113.   indphn->ind_off = indphsize;
  1114.   lastb2 = pereliv (aspn, 0, nels, lnkey, lastb, off - n1);
  1115.   if (prpg == 1)
  1116.     { /* An insertion in the first page */
  1117.       icp_insrec (key, key2, inf, inf_size, beg, loc, lastb, 0, NULL, 0);
  1118.       n1 += sz;
  1119.     }
  1120.   else
  1121.     {
  1122.       sz = insrep (aspn, lastb2, key, key2, elsz, &beg, &loc);
  1123.       icp_insrec (key, key2, inf, inf_size, beg, loc, lastb2, 0, NULL, 0);
  1124.       n2 += sz; 
  1125.     }
  1126.   indph->ind_off = n1;
  1127.   indph->ind_nextpn = newpn;
  1128.   assert (check_ind_page (asp) == 0);
  1129.   putwul (pg, 'm'); /* put page without unlock */
  1130.   indphn->ind_off = n2 + indphsize;
  1131.   indphn->ind_nextpn = (u2_t) ~ 0;
  1132.   indphn->ind_wpage = LEAF;
  1133.   assert (check_ind_page (aspn) == 0);
  1134.   putwul (&pgn, 'm'); /* put new page */
  1135.   return (0);
  1136. }
  1137. static int
  1138. rbrobr (struct A *pg, i4_t sz, char *key, char *key2,
  1139.         char *inf, char *beg, char *loc)
  1140. { /* right brother request for an insertion */
  1141.   char *aspr, *frkey, *asp;
  1142.   char *middleb, *lnkey, *lnkey2, *lkey, *lkey2;
  1143.   i4_t elsz, n1, n2, rfreesz, lbeg, ans, off1, off2;
  1144.   i4_t lnbeg, prpg, pr, ksz, offbeg, offloc, middle;
  1145.   u2_t nels, rbrpn, pn;
  1146.   struct A pgr;
  1147.   char oldkey[BD_PAGESIZE];
  1148.   char oldk2[BD_PAGESIZE];  
  1149.   char nkey[BD_PAGESIZE];
  1150.   char nkey2[BD_PAGESIZE];
  1151.   asp = pg->p_shm;
  1152.   rbrpn = ((struct ind_page *) asp)->ind_nextpn;
  1153.   if (rbrpn == (u2_t) ~ 0)
  1154.     return (div12 (pg, sz, key, key2, inf, beg, loc));
  1155.   if ((aspr = getpg (&pgr, seg_n, rbrpn, 's')) == NULL)
  1156.     return ( -1);
  1157.   thread_s_put (rbrpn);
  1158.   off2 = ((struct ind_page *) aspr)->ind_off;
  1159.   rfreesz = BD_PAGESIZE - off2;
  1160.   offbeg = beg - asp;
  1161.   offloc = loc - asp;
  1162.   if (rfreesz < sz)
  1163.     return (rbrnew (pg, &pgr, sz, key, key2, inf, offbeg, offloc));
  1164.   /* A location is enough in the right brother */
  1165.   elsz = k2sz + inf_size;
  1166.   off1 = ((struct ind_page *) asp)->ind_off;
  1167.   middle = (off1 + off2 + sz) / 2;
  1168.   frkey = aspr + indphsize + size2b;
  1169.   if (offloc + sz <= middle)
  1170.     { /* An insertion in the first page */
  1171.       middleb = asp + middle - sz;
  1172.       lnkey = key;
  1173.       lnkey2 = key2;
  1174.       n2 = repet1 (asp, beg, loc, elsz, middleb, &lkey, &lkey2, &lnkey, &lnkey2,
  1175.    &n1, &nels, &lbeg, &lnbeg, &pr, frkey);
  1176.       if (n2 > rfreesz)
  1177. return (rbrnew (pg, &pgr, sz, key, key2, inf, offbeg, offloc));
  1178.       ksz = kszcal (lnkey, afn, d_f);
  1179.       prpg = 1;
  1180.     }
  1181.   else
  1182.     { /* An insertion in the right brother page */
  1183.       char * mas, *a, *b, *lastb;
  1184.       i4_t massz, size;
  1185.       middleb = asp + middle;
  1186.       lastb = asp + off1;
  1187.       n2 = repttn (asp + indphsize, lastb, elsz, middleb, &lkey, &lkey2, &lnkey,
  1188.    &lnkey2, &n1, &nels, &lbeg, &lnbeg, &pr, frkey);
  1189.       ksz = kszcal (lnkey, afn, d_f);
  1190.       n1 += indphsize;
  1191.       lnbeg += indphsize;
  1192.       massz = off1 - n1 + size2b + ksz + elsz + indphsize;
  1193.       mas = (char *) xmalloc (massz);
  1194.       a = mas + indphsize;
  1195.       if (nels != 0)
  1196. {
  1197.   t2bpack (nels, a);
  1198.   a += size2b;
  1199.           bcopy (lnkey, a, ksz);
  1200.           a += ksz;
  1201. }
  1202.       b = asp + n1;
  1203.       size = lastb - b;
  1204.       bcopy (b, a, size);
  1205.       sz = insrep (mas, mas + massz, key, key2, elsz, &beg, &loc);
  1206.       n2 += sz;
  1207.       if (n2 > rfreesz)
  1208. {
  1209.   xfree ((void *) mas);
  1210.   return (rbrnew (pg, &pgr, sz, key, key2, inf, offbeg, offloc));
  1211. }
  1212.       offbeg = beg - mas;
  1213.       offloc = loc - mas;
  1214.       xfree ((void *) mas);
  1215.       prpg = 2;
  1216.     }
  1217.   bcopy (lkey, oldkey, kszcal (lkey, afn, d_f));
  1218.   bcopy (lkey2, oldk2, k2sz);
  1219.   bcopy (lnkey, nkey, ksz);
  1220.   bcopy (lnkey2, nkey2, k2sz);
  1221.   putwul (pg, 'n'); /* put pn without unlock */
  1222.   putwul (&pgr, 'n'); /* put rbrpn without unlock */
  1223.   pn = pg->p_pn;
  1224.   ans = mlreddi (oldkey, oldk2, nkey, nkey2, pn);
  1225.   if (ans == -1)
  1226.     return (-1);
  1227.   per22 (pn, rbrpn, n1, n2, nels, lbeg, lnbeg, pr, prpg,
  1228.          sz, key, key2, inf, nkey, offbeg, offloc);
  1229.   return (0);
  1230. }
  1231. static int
  1232. inroot (struct A *pg, i4_t insz, char *key, char *key2,
  1233.         char *inf, char *bbeg, char *loc, i4_t wpage)
  1234. {
  1235.   char *a, *b, *lastb;
  1236.   i4_t off, size, ans, infsz, ibeg, iloc;
  1237.   char *mas;
  1238.   char *asp;
  1239.   if (wpage == LEAF)
  1240.     infsz = inf_size;
  1241.   else
  1242.     infsz = size2b;
  1243.   asp = pg->p_shm;
  1244.   ibeg = bbeg - asp;
  1245.   iloc = loc - asp;
  1246.   off = ((struct ind_page *) asp)->ind_off;
  1247.   size = off - indphsize;
  1248.   mas = (char *) xmalloc (size + insz);
  1249.   bcopy (asp + indphsize, mas, size);
  1250.   lastb = mas + size;
  1251.   a = mas + ibeg - indphsize;
  1252.   b = mas + iloc - indphsize;
  1253.   icp_insrec (key, key2, inf, infsz, a, b, lastb, 0, NULL, 0);
  1254.   ans = crnlev (pg, mas, lastb + insz, wpage);
  1255.   xfree ((void *) mas);
  1256.   return (ans);
  1257. }
  1258. static int
  1259. largest_key (struct A *pg, char *key, char *key2, char *inf, i4_t wpage);
  1260. static int
  1261. addlast (char *key, char *key2, u2_t * newpn)
  1262. {
  1263.   u2_t uppn;
  1264.   struct A pg;
  1265.   char *asp;
  1266.   char inf[size2b];
  1267.   uppn = *(--thread_s.u);
  1268.   asp = getwl (&pg, seg_n, uppn); /* get uppn without lock */
  1269.   *newpn = getempt (seg_n);
  1270.   t2bpack (*newpn, inf);
  1271.   if (largest_key (&pg, key, key2, inf, BTWN) < 0)
  1272.     {
  1273.       emptypg (seg_n, *newpn, 'n');
  1274.       return (-1);
  1275.     }
  1276.   return (0);
  1277. }
  1278. static int
  1279. largest_key (struct A *pg, char *key, char *key2, char *inf, i4_t wpage)
  1280. {
  1281.   char *lastb, *bbeg, *loc, *asp;
  1282.   i4_t elsz, sz, off, infsz;
  1283.   u2_t pn;
  1284.   i4_t idm;
  1285.   struct ind_page *indph;
  1286.   asp = pg->p_shm;
  1287.   indph = (struct ind_page *) asp;
  1288.   if (wpage == LEAF)
  1289.     infsz = inf_size;
  1290.   else
  1291.     infsz = size2b;
  1292.   elsz = k2sz + infsz;
  1293.   off = indph->ind_off;
  1294.   lastb = asp + off;
  1295.   sz = insrep (asp, lastb, key, key2, elsz, &bbeg, &loc);
  1296.   if (sz == 0 )
  1297.     return (1);
  1298.   pn = pg->p_pn;
  1299.   if (sz + off > BD_PAGESIZE)
  1300.     {
  1301.       if (indph->ind_wpage == IROOT)
  1302.         {
  1303.           return (inroot (pg, sz, key, key2, inf, bbeg, loc, wpage));
  1304.         }
  1305.       else
  1306. {
  1307.           u2_t newpn, keysz;
  1308.   putwul (pg, 'n');
  1309.   if (addlast (key, key2, &newpn) < 0)
  1310.     return (-1);
  1311.   asp = getnew (pg, seg_n, newpn); /* get pn without lock */
  1312.   loc = asp + indphsize;
  1313.   t2bpack (1, loc);
  1314.           loc += size2b;
  1315.           keysz = kszcal (key, afn, d_f);
  1316.           bcopy (key, loc, keysz);
  1317.           loc += keysz;
  1318.           bcopy (key2, loc, k2sz);
  1319.           loc += k2sz;
  1320.           bcopy (inf, loc, infsz);
  1321.   indph = (struct ind_page *) asp;
  1322.   indph->ind_nextpn = (u2_t) ~ 0;
  1323.   indph->ind_off = indphsize + size2b + keysz + k2sz + infsz;
  1324.   indph->ind_wpage = wpage;
  1325.           assert (check_ind_page (asp) == 0);
  1326.   putwul (pg, 'm');
  1327.   asp = getwl (pg, seg_n, pn); /* get pn without lock */
  1328.   indph = (struct ind_page *) asp;
  1329.   idm = ++((struct p_head *) asp)->idmod;
  1330.   loc = (char *) &indph->ind_nextpn;
  1331.   recmjform (OLD, seg_n, pn, idm, loc - asp, size2b, loc, 0);
  1332.   indph->ind_nextpn = newpn;
  1333. }
  1334.     }
  1335.   else
  1336.     {
  1337.       if (indph->ind_wpage != IROOT)
  1338. { /* pn is not root */
  1339.           char *oldkey;
  1340.           char old_key[BD_PAGESIZE];
  1341.           char oldk2[BD_PAGESIZE];
  1342.           i4_t offbeg, offloc;
  1343.   offbeg = bbeg - asp;
  1344.   offloc = loc - asp;
  1345.   if (sz != elsz)
  1346.     {
  1347.               char *a;
  1348.               u2_t keysz = 0 , n;
  1349.               for (a = asp + indphsize; a < lastb; a += keysz + n * elsz)
  1350.                 {
  1351.                   n = t2bunpack (a);
  1352.                   a += size2b;
  1353.                   loc = a;
  1354.                   keysz = kszcal (a, afn, d_f);
  1355.                 }
  1356.       oldkey = old_key;
  1357.               assert ( keysz != 0 );
  1358.               bcopy (loc, oldkey, keysz);
  1359.     }
  1360.   else
  1361.     oldkey = key;
  1362.           bcopy (lastb - elsz, oldk2, k2sz);
  1363.   putwul (pg, 'n');
  1364.   if (modlast (oldkey, oldk2, key, key2, pn) < 0)
  1365.     return (-1);
  1366.   asp = getwl (pg, seg_n, pn); /* get pn without lock */
  1367.   indph = (struct ind_page *) asp;
  1368.   bbeg = offbeg + asp;
  1369.   loc = offloc + asp;
  1370.           lastb = asp + indph->ind_off;
  1371. }
  1372.       else
  1373. {
  1374.   upunlock ();
  1375.   if (lenforce ()< 0)
  1376.     {
  1377.       putwul (pg, 'n');
  1378.       return (-1);
  1379.     }
  1380. }
  1381.       idm = ++((struct p_head *) asp)->idmod;
  1382.       icp_insrec (key, key2, inf, infsz, bbeg, loc, lastb, pn, asp, idm);
  1383.       loc = (char *) &indph->ind_off;
  1384.       recmjform (OLD, seg_n, pn, idm, loc - asp, size2b, loc, 0);
  1385.       indph->ind_off += sz;
  1386.     }
  1387.   assert (check_ind_page (asp) == 0);
  1388.   putwul (pg, 'm');
  1389.   return (0);
  1390. }
  1391. static char *
  1392. find_largest_key (struct A *pg)
  1393. {
  1394.   char  *a, *asp;
  1395.   u2_t  pn;
  1396.   struct ind_page *indph;
  1397.   asp = pg->p_shm;
  1398.   indph = (struct ind_page *) asp;
  1399.   do
  1400.     {
  1401.       a = asp + indph->ind_off - size2b;
  1402.       pn = t2bunpack (a);
  1403.       putwul (pg, 'n');
  1404.       thread_s_put (pn);
  1405.       if ((asp = getpg (pg, seg_n, pn, 's')) == NULL)
  1406. return (NULL); /* Lock and request */
  1407.       indph = (struct ind_page *) asp;
  1408.     }
  1409.   while (indph->ind_wpage != LEAF);
  1410.   thread_s.u = thread_s.d - 1;
  1411.   return (asp);
  1412. }
  1413. static int
  1414. divsn_modlast (char *key, char *key2, u2_t pn, char *mas, i4_t massz);
  1415. static int
  1416. divup_modlast (char *key, char *key2, char *nkey, char *nkey2,
  1417.                char *lnkey, char *lnkey2, u2_t * newpn)
  1418. {
  1419.   char *a, *asp, *lastb;
  1420.   u2_t uppn;
  1421.   struct ind_page *indph;
  1422.   struct A pg;
  1423.   i4_t rbeg, rloc, ibeg1, iloc1, ibeg2, iloc2;
  1424.   i4_t remsz, sz1, sz2, elsz, off, dopsz;
  1425.   char inf1[size2b], inf2[size2b], *beg, *loc;
  1426.   i4_t idm;
  1427.   uppn = *(--thread_s.u);
  1428.   asp = getwl (&pg, seg_n, uppn); /* get pn without lock */
  1429.   indph = (struct ind_page *) asp;
  1430.   elsz = k2sz + size2b;
  1431.   remsz = mlrep1 (asp, key, key2, nkey, &rbeg, &rloc, &ibeg1, &iloc1, &sz1);
  1432.   if (cmpkeys (k_n, afn, d_f, lnkey, nkey) == 0)
  1433.     {
  1434.       sz2 = elsz;
  1435.       ibeg2 = ibeg1;
  1436.       if (ibeg1 == iloc1)
  1437.         iloc2 = ibeg1 + sz1 +elsz;
  1438.       else
  1439.         iloc2 = iloc1 + elsz;
  1440.     }
  1441.   else
  1442.     {
  1443.       sz2 = size2b + kszcal (lnkey, afn, d_f) + elsz;
  1444.       ibeg2 = iloc2 = iloc1 + sz1;
  1445.     }
  1446.   bcopy (asp + rloc + k2sz, inf1, size2b);
  1447.   off = indph->ind_off;
  1448.   dopsz = sz1 + sz2 - remsz;
  1449.   if ((off + dopsz) > BD_PAGESIZE)
  1450.     {
  1451.       char *mas;
  1452.       i4_t massz, ans, size;
  1453.       lastb = asp + off;
  1454.       massz = off + dopsz - indphsize;
  1455.       mas = (char *) xmalloc (massz);
  1456.       size = off - indphsize;
  1457.       bcopy (asp + indphsize, mas, size);
  1458.       lastb = mas + size;
  1459.       beg = mas + rbeg - indphsize;
  1460.       loc = mas + rloc - indphsize; 
  1461.       icp_remrec (beg, loc, remsz, lastb, elsz, 0, NULL, 0);
  1462.       lastb -= remsz;
  1463.       beg = mas + ibeg1 - indphsize;
  1464.       loc = mas + iloc1 - indphsize;
  1465.       icp_insrec (nkey, nkey2, inf1, size2b, beg, loc, lastb, 0, NULL, 0);
  1466.       lastb += sz1;
  1467.       *newpn = getempt (seg_n);
  1468.       beg = mas + ibeg2 - indphsize;
  1469.       loc = mas + iloc2 - indphsize;
  1470.       t2bpack (*newpn, inf2);
  1471.       icp_insrec (nkey, nkey2, inf2, size2b, beg, loc, lastb, 0, NULL, 0);
  1472.       if (indph->ind_wpage != IROOT)
  1473.         {
  1474.           putwul (&pg, 'n');
  1475.           ans = divsn_modlast (key, key2, uppn, mas, massz);
  1476.         }
  1477.       else
  1478.         ans = crnlev (&pg, mas, mas + massz, BTWN);
  1479.       if (ans < 0)
  1480. emptypg (seg_n, *newpn, 'n');
  1481.       xfree ((void *) mas);
  1482.       return (ans);
  1483.     }
  1484.   else
  1485.     {
  1486.       if (indph->ind_wpage != IROOT)
  1487. { /* pn is not root */
  1488.   putwul (&pg, 'n');
  1489.   if (modlast (key, key2, nkey, nkey2, uppn) < 0)
  1490.     return (-1);
  1491.   asp = getwl (&pg, seg_n, uppn); /* get pn without lock */
  1492.   indph = (struct ind_page *) asp;
  1493. }
  1494.       else
  1495. {
  1496.   upunlock ();
  1497.   if (lenforce ()< 0)
  1498.     {
  1499.       putwul (&pg, 'n');
  1500.       return (-1);
  1501.     }
  1502. }
  1503.     }
  1504.   *newpn = getempt (seg_n);
  1505.   idm = ++((struct p_head *) asp)->idmod;
  1506.   lastb = asp + off;
  1507.   icp_remrec (asp + rbeg, asp + rloc, remsz, lastb, elsz, uppn, asp, idm);
  1508.   lastb -= remsz;
  1509.   beg = asp + ibeg1;
  1510.   loc = asp + iloc1;
  1511.   icp_insrec (lnkey, lnkey2, inf1, size2b, beg, loc, lastb, uppn, asp, idm);
  1512.   lastb += sz1;
  1513.   insrep (asp, lastb, nkey, nkey2, elsz, &beg, &loc);
  1514.   t2bpack (*newpn, inf2);
  1515.   icp_insrec (nkey, nkey2, inf2, size2b, beg, loc, lastb, uppn, asp, idm);
  1516.   a = (char *) &indph->ind_off;
  1517.   recmjform (OLD, seg_n, uppn, idm, a - asp, size2b, a, 0);
  1518.   indph->ind_off += dopsz;
  1519.   assert (check_ind_page (asp) == 0);
  1520.   putwul (&pg, 'm');
  1521.   return (0);
  1522. }
  1523. static int
  1524. divsn_modlast (char *key, char *key2, u2_t pn, char *mas, i4_t massz)
  1525. {
  1526.   char *lastb, *a, *b, *middleb, *asp;
  1527.   i4_t n1, lbeg, lnbeg, pr;
  1528.   char *nkey, *nkey2, *lnkey, *lnkey2;
  1529.   u2_t nels, newpn;
  1530.   i4_t idm;
  1531.   struct ind_page *indph;
  1532.   struct A pg;
  1533.   lastb = mas + massz;
  1534.   middleb = mas + massz / 2;
  1535.   repttn (mas, lastb, k2sz + size2b, middleb, &nkey, &nkey2, &lnkey,
  1536.           &lnkey2, &n1, &nels, &lbeg, &lnbeg, &pr, (char *) NULL);
  1537.   if (divup_modlast (key, key2, nkey, nkey2, lnkey, lnkey2, &newpn) < 0)
  1538.     return (-1);
  1539.   asp = getwl (&pg, seg_n, pn); /* get pn without lock */
  1540.   indph = (struct ind_page *) asp;
  1541.   idm = ++((struct p_head *) asp)->idmod;
  1542.   a = asp + sizeof (struct p_head);
  1543.   b = asp + indph->ind_off;
  1544.   recmjform (OLD, seg_n, pn, idm, a - asp, b - a, a, 0);
  1545.   bcopy (mas, asp + indphsize, n1);
  1546.   if (nels != 0)
  1547.     mod_nels ((-nels), asp + lnbeg);
  1548.   indph->ind_off = n1 + indphsize;
  1549.   indph->ind_nextpn = newpn;
  1550.   assert (check_ind_page (asp) == 0);
  1551.   putwul (&pg, 'm');
  1552.   asp = getnew (&pg, seg_n, newpn); /* get newpn without lock */
  1553.   indph = (struct ind_page *) asp;
  1554.   nkey = lastb - lbeg + size2b;
  1555.   indph->ind_off = indphsize;
  1556.   b = pereliv (asp, 0, nels, nkey, mas + n1, massz - n1);
  1557.   indph->ind_off = b - asp;
  1558.   indph->ind_nextpn = (u2_t) ~0;
  1559.   indph->ind_wpage = BTWN;
  1560.   assert (check_ind_page (asp) == 0);
  1561.   putwul (&pg, 'm'); /* put page without unlock */
  1562.   return (0);
  1563. }
  1564. int
  1565. icp_insrtn (struct ldesind *desind, char *key, char *key2,
  1566.             char *inf, i4_t infsz)
  1567. {
  1568.   i4_t lagelsz, agelsz, sz, off, ans, ans_lk;
  1569.   u2_t rootpn, d_fn;
  1570.   char *asp = NULL, *lastb, *bbeg, *loc;
  1571.   struct ind_page *indph;
  1572.   i4_t idm;
  1573.   struct A pg;
  1574.   thread_s_ini_check();
  1575.   
  1576.   seg_n = desind->i_segn;
  1577.   afn = (u2_t *) (desind + 1);
  1578.   k_n = desind->ldi.kifn & ~UNIQ & MSK21B;
  1579.   uniq_key = UNIQ & desind->ldi.kifn;
  1580.   d_f = desind->pdf;
  1581.   d_fn = k_n;
  1582.   if ((k_n % 2) != 0)
  1583.     d_fn += 1;
  1584.   d_f2 = (struct des_field *) (afn + d_fn);
  1585.   k2sz = d_f2->field_size;
  1586.   inf_size = infsz;
  1587.   lagelsz = k2sz + infsz;
  1588.   agelsz = k2sz + size2b;
  1589.   rootpn = desind->ldi.rootpn;
  1590.   beg_mop ();
  1591. try_again:
  1592.   while ((asp = getpg (&pg, seg_n, rootpn, 's')) == NULL); /* Lock and request */
  1593.   
  1594.   thread_s_ini();
  1595.   thread_s_put (rootpn);
  1596.   indph = (struct ind_page *) asp;
  1597.   if (indph->ind_wpage == LEAF)
  1598.     { /* root-leaf */
  1599.       off = indph->ind_off;
  1600.       lastb = asp + off;
  1601.       sz = insrep (asp, lastb, key, key2, lagelsz, &bbeg, &loc);
  1602.       if (sz == 0)
  1603. {
  1604.   putpg (&pg, 'n');
  1605.           thread_s_ini();
  1606.   return (NU);
  1607. }
  1608.       if (BD_PAGESIZE - off < sz)
  1609. {
  1610.   if (inroot (&pg, sz, key, key2, inf, bbeg, loc, LEAF) < 0)
  1611.     goto try_again;
  1612. }
  1613.       else
  1614. {
  1615.   if (lenforce ()< 0)
  1616.     {
  1617.       all_unlock ();
  1618.       goto try_again;
  1619.     }
  1620.   idm = ++((struct p_head *) asp)->idmod;
  1621.   icp_insrec (key, key2, inf, infsz, bbeg, loc, lastb,
  1622.       rootpn, asp, idm);
  1623.   loc = (char *) &indph->ind_off;
  1624.   recmjform (OLD, seg_n, rootpn, idm, loc - asp, size2b, loc, 0);
  1625.   indph->ind_off += sz;
  1626.           assert (check_ind_page (asp) == 0);
  1627.   putwul (&pg, 'm');
  1628. }
  1629.     }
  1630.   else
  1631.     {
  1632.       if ((ans = icp_spusk (&pg, agelsz, key, key2)) == -1)
  1633. {
  1634.   all_unlock ();
  1635.   goto try_again;
  1636. }
  1637.       else if (ans == 1)
  1638. {
  1639.   if ((ans_lk = largest_key (&pg, key, key2, inf, LEAF)) < 0)
  1640.             {
  1641.               all_unlock ();
  1642.               goto try_again;
  1643.             }
  1644.           else
  1645.             if (ans_lk == 1)
  1646.               {
  1647.                 putpg (&pg, 'n');
  1648.                 all_unlock ();
  1649.                 thread_s_ini();
  1650.                 return (NU);
  1651.               }
  1652. }
  1653.       else
  1654. {
  1655.   /* for the leaf */
  1656.           asp = pg.p_shm;
  1657.   indph = (struct ind_page *) asp;
  1658.   off = indph->ind_off;
  1659.   lastb = asp + off;
  1660.   sz = insrep (asp, lastb, key, key2, lagelsz, &bbeg, &loc);
  1661.   if (sz == 0)
  1662.     {
  1663.               putpg (&pg, 'n');
  1664.       all_unlock ();
  1665.               thread_s_ini();
  1666.       return (NU);
  1667.     }
  1668.   if (BD_PAGESIZE - off < sz)
  1669.     {
  1670.       if (rbrobr (&pg, sz, key, key2, inf, bbeg, loc) < 0)
  1671. goto try_again;
  1672.     }
  1673.           else
  1674.             {
  1675.               assert (loc != lastb);
  1676.               upunlock ();
  1677.               if (lenforce ()< 0)
  1678.                 {
  1679.                   all_unlock ();
  1680.                   goto try_again;
  1681.                 }
  1682.               idm = ++((struct p_head *) asp)->idmod;
  1683.       icp_insrec (key, key2, inf, infsz, bbeg, loc, lastb,
  1684.   pg.p_pn, asp, idm);
  1685.       loc = (char *) &indph->ind_off;
  1686.       recmjform (OLD, seg_n, pg.p_pn, idm, loc - asp, size2b, loc, 0);
  1687.       indph->ind_off += sz;
  1688.               assert (check_ind_page (asp) == 0);
  1689.       putwul (&pg, 'm');
  1690.     }
  1691. }
  1692.     }
  1693.   MJ_PUTBL ();
  1694.   downunlock ();
  1695.   
  1696.   thread_s_ini();
  1697.   
  1698.   return (OK);
  1699. }
  1700. int
  1701. icp_spusk (struct A *pg, i4_t elsz, char *key, char *key2)
  1702. {
  1703.   char *a, *lastb, *asp;
  1704.   u2_t n, pn;
  1705.   i4_t l, l2=0, ksz, i;
  1706.   struct ind_page *indph;
  1707.   asp = pg->p_shm;
  1708.   indph = (struct ind_page *)asp;
  1709.   lastb = asp + indph->ind_off;
  1710.   a = asp + indphsize;
  1711.   for (i = 0; indph->ind_wpage != LEAF; i++)
  1712.     {
  1713.       lastb = asp + indph->ind_off;
  1714.       for (a = asp + indphsize; a < lastb; )
  1715. {
  1716.   n = t2bunpack (a);
  1717.           assert (n < BD_PAGESIZE / 2);
  1718.   a += size2b;
  1719.   ksz = kszcal (a, afn, d_f);
  1720.   if ((l = cmpkeys (k_n, afn, d_f, a, key)) == 0)
  1721.     {
  1722.       a += ksz;
  1723.       for (; n != 0; n--, a += elsz)
  1724.                 if ((l2 = cmp2keys (d_f2->field_type, a, key2)) >= 0)
  1725.                   break;
  1726.               if (n == 0 && l2 < 0)
  1727.                 {
  1728.                   if (a == lastb)
  1729.                     assert (indph->ind_nextpn == (u2_t) ~0);
  1730.                   continue;
  1731.                 }
  1732.               if (n == 0)
  1733.                 a -= elsz;
  1734.       break;
  1735.     }
  1736.   else if (l > 0)
  1737.     {
  1738.       a += ksz;
  1739.       break;
  1740.     }
  1741.           a += ksz + n * elsz;
  1742. }
  1743.       if (a == lastb)
  1744. {
  1745.           assert (i==0);
  1746.   if ((asp = find_largest_key (pg)) == NULL)
  1747.     return (-1);
  1748.   return (1);
  1749. }
  1750.       a += k2sz;
  1751.       pn = t2bunpack (a);
  1752.       putwul (pg, 'n');
  1753.       if ((asp = getpg (pg, seg_n, pn, 's')) == NULL)
  1754. return (-1);
  1755.       thread_s_put (pn);
  1756.       indph = (struct ind_page *) asp;
  1757.     }
  1758.   thread_s.u = thread_s.d - 1;
  1759.   return (0);
  1760. }
  1761. int
  1762. remrep (char *asp, char *key, char *key2, i4_t elsz,
  1763.         char ** rbeg, char **rloc, i4_t *offbef)
  1764. {
  1765.   char *a, *lastb, *ckey, *bbeg;
  1766.   i4_t i, keysz, agsz = 0;
  1767.   u2_t n;
  1768.   lastb = asp + ((struct ind_page *) asp)->ind_off;
  1769.   for (a = asp + indphsize; a < lastb; a += agsz)
  1770.     {
  1771.       bbeg = a;
  1772.       n = t2bunpack (a);
  1773.       assert (n < BD_PAGESIZE / 2);
  1774.       ckey = a + size2b;
  1775.       keysz = kszcal (ckey, afn, d_f);
  1776.       if (cmpkeys (k_n, afn, d_f, ckey, key) == 0)
  1777. {
  1778.   a += size2b + keysz;
  1779.   for (i = 0; i != n; i++, a += elsz)
  1780.     if (cmp2keys (d_f2->field_type, a, key2) == 0)
  1781.       {
  1782. *rbeg = bbeg;
  1783. *offbef = bbeg - asp - agsz;
  1784. *rloc = a;
  1785. if (n == 1)
  1786.   return (size2b + keysz + elsz);
  1787. else
  1788.   return (elsz);
  1789.       }
  1790.           assert (i != n);
  1791. }
  1792.       agsz = size2b + keysz + n * elsz;
  1793.       assert (agsz < BD_PAGESIZE);
  1794.     }
  1795.   assert (a < lastb);
  1796.   return (0);
  1797. }
  1798. void
  1799. icp_remrec (char *beg, char *loc, i4_t sz, char *lastb,
  1800.             i4_t elsz, u2_t pn, char *asp, i4_t idm)
  1801. {
  1802.   char *b;
  1803.   i4_t size;
  1804.   if (sz == elsz)
  1805.     {
  1806.       b = loc + sz;
  1807.       size = lastb - b;
  1808.       if (asp != NULL)
  1809. recmjform (COMBL, seg_n, pn, idm, loc - asp, size, loc, sz);
  1810.       bcopy (b, loc, size);
  1811.       if (asp != NULL)
  1812. recmjform (OLD, seg_n, pn, idm, beg - asp, size2b, beg, 0);
  1813.       mod_nels (-1, beg);
  1814.     }
  1815.   else
  1816.     {
  1817.       b = beg + sz;
  1818.       size = lastb - b;
  1819.       if (asp != NULL)
  1820. recmjform (COMBL, seg_n, pn, idm, beg - asp, size, beg, sz);
  1821.       bcopy (b, beg, size);
  1822.     }
  1823. }
  1824. int
  1825. mlreddi (char *lkey, char *lkey2, char *lnkey, char *lnkey2, u2_t pn)
  1826. {
  1827.   char *asp, *pnt;
  1828.   i4_t sz, remsz, insz, off, orbeg, orloc, oibeg, oiloc, elsz, dopsz;
  1829.   struct ind_page *indph;
  1830.   i4_t idm;
  1831.   struct A pg;
  1832.   char ninf[size2b];
  1833.   t2bpack (pn, ninf);
  1834.   pn = *(--thread_s.u);
  1835.   asp = getwl (&pg, seg_n, pn); /* get pn without lock */
  1836.   remsz = mlrep1 (asp, lkey, lkey2, lnkey, &orbeg, &orloc, &oibeg, &oiloc, &insz);
  1837.   indph = (struct ind_page *) asp;
  1838.   off = indph->ind_off;
  1839.   dopsz = insz - remsz;
  1840.   sz = off + dopsz;
  1841.   elsz = k2sz + size2b;
  1842.   if (sz > BD_PAGESIZE)
  1843.     {
  1844.       char *mas, *b, *beg, *loc, *lastb;
  1845.       i4_t massz, ans, size;
  1846.       massz = sz - indphsize;
  1847.       mas = (char *) xmalloc (massz);
  1848.       size = off - indphsize;
  1849.       bcopy (asp + indphsize, mas, size);
  1850.       b = mas + size;
  1851.       beg = mas + orbeg - indphsize;
  1852.       loc = mas + orloc - indphsize;
  1853.       icp_remrec (beg, loc, remsz, b, elsz, 0, NULL, 0);
  1854.       lastb = b - remsz;
  1855.       beg = mas + oibeg - indphsize;
  1856.       loc = mas + oiloc - indphsize;
  1857.       icp_insrec (lnkey, lnkey2, ninf, size2b, beg, loc, lastb, 0, NULL, 0);
  1858.       if (indph->ind_wpage == IROOT)
  1859. { /* uppn is root */
  1860.   ans = crnlev (&pg, mas, mas + massz, BTWN);
  1861. }
  1862.       else
  1863. {
  1864.           char last_key[BD_PAGESIZE];
  1865.           char last_k2[BD_PAGESIZE];
  1866.           u2_t rbrpn, keysz = 0 ;
  1867.           
  1868.           if (orloc + elsz != off)     /* lkey isn't the last key in pn */
  1869.             {
  1870.               FIND_LAST_KEY (asp, elsz, lkey, lkey2, keysz);
  1871.             }
  1872.           else
  1873.             keysz = kszcal (lkey, afn, d_f);
  1874.           assert ( keysz != 0 );
  1875.           bcopy (lkey, last_key, keysz);
  1876.           bcopy (lkey2, last_k2, k2sz);
  1877.   rbrpn = indph->ind_nextpn;
  1878.   putwul (&pg, 'n');
  1879.   ans = rbrup (pn, rbrpn, mas, massz, last_key, last_k2);
  1880. }
  1881.       xfree ((void *) mas);
  1882.       return (ans);
  1883.     }
  1884.   if (orloc + elsz == off && indph->ind_wpage != IROOT)
  1885.     {
  1886.       putwul (&pg, 'n');
  1887.       if (mlreddi (lkey, lkey2, lnkey, lnkey2, pn) < 0)
  1888. return (-1);
  1889.       asp = getwl (&pg, seg_n, pn);
  1890.     }
  1891.   else
  1892.     {
  1893.       upunlock ();
  1894.       if (lenforce ()< 0)
  1895. {
  1896.   putwul (&pg, 'n');
  1897.   return (-1);
  1898. }
  1899.     }
  1900.   idm = ++((struct p_head *) asp)->idmod;
  1901.   indph = (struct ind_page *) asp;
  1902.   if (orloc == oiloc)
  1903.     { /* keys match */
  1904.       pnt = asp + orloc;
  1905.       recmjform (OLD, seg_n, pn, idm, orloc, k2sz, pnt, 0);
  1906.       bcopy (lnkey2, pnt, k2sz);
  1907.     }
  1908.   else
  1909.     {
  1910.       pnt = asp + indph->ind_off;
  1911.       icp_remrec (asp + orbeg, asp + orloc, remsz, pnt, elsz, pn, asp, idm);
  1912.       icp_insrec (lnkey, lnkey2, ninf, size2b, asp + oibeg,
  1913.   asp + oiloc, pnt - remsz, pn, asp, idm);
  1914.     }
  1915.   if (dopsz != 0)
  1916.     {
  1917.       pnt = (char *) &indph->ind_off;
  1918.       recmjform (OLD, seg_n, pn, idm, pnt - asp, size2b, pnt, 0);
  1919.       indph->ind_off += dopsz;
  1920.     }
  1921.   assert (check_ind_page (asp) == 0);
  1922.   putwul (&pg, 'm'); /* put page without unlock */
  1923.   return (0);
  1924. }
  1925. int
  1926. modlast (char *key, char *key2, char *nkey, char *nkey2, u2_t pn)
  1927. {
  1928.   char *lastb, *asp, *beg, *loc;
  1929.   struct ind_page *indph;
  1930.   i4_t sz = 0, remsz = 0, elsz, off;
  1931.   i4_t orbeg, orloc, oibeg, oiloc;
  1932.   i4_t idm;
  1933.   struct A pg;
  1934.   char ninf[size2b];
  1935.   t2bpack (pn, ninf);
  1936.   pn = *(--thread_s.u);
  1937.   asp = getwl (&pg, seg_n, pn); /* get uppn without lock */
  1938.   indph = (struct ind_page *) asp;
  1939.   off = indph->ind_off;
  1940.   elsz = k2sz + size2b;
  1941.   if (key != nkey)
  1942.     {
  1943.       if (cmpkeys (k_n, afn, d_f, key, nkey) == 0)
  1944.         nkey = key;
  1945.       else
  1946.         {
  1947.           i4_t insz;
  1948.           remsz = mlrep1 (asp, key, key2, nkey, &orbeg, &orloc, &oibeg, &oiloc, &insz);
  1949.           assert (insz != 0);
  1950.           sz = insz - remsz;
  1951.           if (sz + off > BD_PAGESIZE)
  1952.             {
  1953.               char *mas;
  1954.               i4_t massz, ans;
  1955.               massz = off + insz - indphsize;
  1956.               mas = (char *) xmalloc (massz);
  1957.               sz = off - indphsize;
  1958.               bcopy (asp + indphsize, mas, sz);
  1959.               lastb = mas + sz;
  1960.               icp_remrec (mas + orbeg, mas + orloc, remsz, lastb, elsz, 0, NULL, 0);
  1961.               lastb -= remsz;
  1962.               icp_insrec (nkey, nkey2, ninf, size2b, mas + oibeg, mas + oiloc,
  1963.                           lastb, 0, NULL, 0);
  1964.               if (indph->ind_wpage != IROOT)
  1965.                 {
  1966.                   putwul (&pg, 'n');
  1967.                   ans = divsn_modlast (key, key2, pn, mas, massz);
  1968.                 }
  1969.               else
  1970.                 ans = crnlev (&pg, mas, mas + massz, BTWN);
  1971.               xfree ((void *) mas);
  1972.               return (ans);
  1973.             }
  1974.         }
  1975.     }
  1976.   if (indph->ind_wpage != IROOT)
  1977.     { /* pn is not root */
  1978.       putwul (&pg, 'n');
  1979.       if (modlast (key, key2, nkey, nkey2, pn) < 0)
  1980.         return (-1);
  1981.       asp = getwl (&pg, seg_n, pn); /* get pn without lock */
  1982.       indph = (struct ind_page *) asp;
  1983.     }
  1984.   else
  1985.     {
  1986.       upunlock ();
  1987.       if (lenforce ()< 0)
  1988.         {
  1989.           putwul (&pg, 'n');
  1990.           return (-1);
  1991.         }
  1992.     }
  1993.   idm = ++((struct p_head *) asp)->idmod;
  1994.   lastb = asp + off;
  1995.   if (key == nkey)
  1996.     {
  1997.       loc = lastb - elsz;
  1998.       recmjform (OLD, seg_n, pn, idm, loc - asp, size2b, loc, 0);
  1999.       bcopy (nkey2, loc, k2sz);
  2000.     }
  2001.   else
  2002.     {
  2003.       beg = asp + orbeg;
  2004.       loc = asp + orloc;
  2005.       icp_remrec (beg, loc, remsz, lastb, elsz, pn, asp, idm);
  2006.       lastb -= remsz;
  2007.       beg = asp + oibeg;
  2008.       loc = asp + oiloc;
  2009.       icp_insrec (nkey, nkey2, ninf, size2b, beg, loc, lastb, pn, asp, idm);
  2010.     }
  2011.   if (sz != 0)
  2012.     {
  2013.       char *a;
  2014.       a = (char *) &indph->ind_off;
  2015.       recmjform (OLD, seg_n, pn, idm, a - asp, size2b, a, 0);
  2016.       indph->ind_off += sz;
  2017.     }
  2018.   assert (check_ind_page (asp) == 0);
  2019.   putwul (&pg, 'm');
  2020.   return (0);
  2021. }
  2022. void
  2023. all_unlock ()
  2024. {
  2025.   BUF_unlock (seg_n, thread_s.count, thread_s.arr);
  2026. }
  2027. void
  2028. upunlock ()
  2029. {
  2030.   i4_t i;
  2031.   i = thread_s.u - thread_s.arr;
  2032.   if (i)
  2033.     BUF_unlock (seg_n, i, thread_s.arr);
  2034. }
  2035. void
  2036. downunlock ()
  2037. {
  2038.   i4_t i;
  2039.   i = thread_s.d - thread_s.u;
  2040.   if (i)
  2041.     BUF_unlock (seg_n, i, thread_s.u);
  2042. }
  2043. int
  2044. lenforce ()
  2045. {
  2046.   u2_t *a;
  2047.   for (a = thread_s.u; a < thread_s.d; a++)
  2048.     if (BUF_enforce (seg_n, *a) < 0)
  2049.       {
  2050. downunlock ();
  2051. return (-1);
  2052.       }
  2053.   return (0);
  2054. }