1*46131Smao /*- 2*46131Smao * Copyright (c) 1990 The Regents of the University of California. 3*46131Smao * All rights reserved. 4*46131Smao * 5*46131Smao * This code is derived from software contributed to Berkeley by 6*46131Smao * Mike Olson. 7*46131Smao * 8*46131Smao * %sccs.include.redist.c% 9*46131Smao */ 10*46131Smao 11*46131Smao #if defined(LIBC_SCCS) && !defined(lint) 12*46131Smao static char sccsid[] = "@(#)bt_put.c 5.1 (Berkeley) 01/23/91"; 13*46131Smao #endif /* LIBC_SCCS and not lint */ 14*46131Smao 15*46131Smao #include <sys/types.h> 16*46131Smao #include <db.h> 17*46131Smao #include "btree.h" 18*46131Smao 19*46131Smao /* 20*46131Smao * _BT_INSERT -- Insert a new user datum in the btree. 21*46131Smao * 22*46131Smao * This routine is called by bt_put, the public interface, once the 23*46131Smao * location for the new item is known. We do the work here, and 24*46131Smao * handle splits if necessary. 25*46131Smao * 26*46131Smao * Parameters: 27*46131Smao * t -- btree in which to do the insertion. 28*46131Smao * item -- BTITEM describing location of new datum 29*46131Smao * key -- key to insert 30*46131Smao * data -- data associated with key 31*46131Smao * flag -- magic cookie passed recursively to bt_put if we 32*46131Smao * have to do a split 33*46131Smao * 34*46131Smao * Returns: 35*46131Smao * RET_SUCCESS, RET_ERROR. 36*46131Smao */ 37*46131Smao 38*46131Smao int 39*46131Smao _bt_insert(t, item, key, data, flag) 40*46131Smao BTREE_P t; 41*46131Smao BTITEM *item; 42*46131Smao DBT *key; 43*46131Smao DBT *data; 44*46131Smao int flag; 45*46131Smao { 46*46131Smao index_t index; 47*46131Smao BTHEADER *h; 48*46131Smao DATUM *d; 49*46131Smao int nbytes; 50*46131Smao int status; 51*46131Smao pgno_t pgno; 52*46131Smao int keysize, datasize; 53*46131Smao int bigkey, bigdata; 54*46131Smao 55*46131Smao if (_bt_getpage(t, item->bti_pgno) == RET_ERROR) 56*46131Smao return (RET_ERROR); 57*46131Smao h = t->bt_curpage; 58*46131Smao 59*46131Smao if (TOOBIG(t, data->size)) { 60*46131Smao bigdata = TRUE; 61*46131Smao datasize = sizeof(pgno_t); 62*46131Smao } else { 63*46131Smao bigdata = FALSE; 64*46131Smao datasize = data->size; 65*46131Smao } 66*46131Smao 67*46131Smao if (TOOBIG(t, key->size)) { 68*46131Smao bigkey = TRUE; 69*46131Smao keysize = sizeof(pgno_t); 70*46131Smao } else { 71*46131Smao bigkey = FALSE; 72*46131Smao keysize = key->size; 73*46131Smao } 74*46131Smao 75*46131Smao nbytes = keysize + datasize + (sizeof(DATUM) - sizeof(char)); 76*46131Smao nbytes = LONGALIGN(nbytes) + sizeof(index_t); 77*46131Smao 78*46131Smao /* if there's not enough room here, split the page */ 79*46131Smao if ((h->h_upper - h->h_lower) < nbytes) { 80*46131Smao if (_bt_split(t) == RET_ERROR) 81*46131Smao return (RET_ERROR); 82*46131Smao 83*46131Smao /* okay, try again */ 84*46131Smao return (bt_put((BTREE) t, key, data, flag)); 85*46131Smao } 86*46131Smao 87*46131Smao /* put together a leaf page datum from the key/data pair */ 88*46131Smao index = item->bti_index; 89*46131Smao nbytes = keysize + datasize + (sizeof(DATUM) - sizeof(char)); 90*46131Smao 91*46131Smao if ((d = (DATUM *) malloc((unsigned) nbytes)) == (DATUM *) NULL) 92*46131Smao return (RET_ERROR); 93*46131Smao 94*46131Smao d->d_ksize = keysize; 95*46131Smao d->d_dsize = datasize; 96*46131Smao d->d_flags = 0; 97*46131Smao 98*46131Smao if (bigkey) { 99*46131Smao if (_bt_indirect(t, key, &pgno) == RET_ERROR) 100*46131Smao return (RET_ERROR); 101*46131Smao (void) bcopy((char *) &pgno, &(d->d_bytes[0]), sizeof(pgno)); 102*46131Smao d->d_flags |= D_BIGKEY; 103*46131Smao if (_bt_getpage(t, item->bti_pgno) == RET_ERROR) 104*46131Smao return (RET_ERROR); 105*46131Smao } else { 106*46131Smao if (d->d_ksize > 0) { 107*46131Smao (void) bcopy((char *) key->data, 108*46131Smao (char *) &(d->d_bytes[0]), 109*46131Smao (int) d->d_ksize); 110*46131Smao } 111*46131Smao } 112*46131Smao 113*46131Smao if (bigdata) { 114*46131Smao if (_bt_indirect(t, data, &pgno) == RET_ERROR) 115*46131Smao return (RET_ERROR); 116*46131Smao (void) bcopy((char *) &pgno, 117*46131Smao &(d->d_bytes[keysize]), 118*46131Smao sizeof(pgno)); 119*46131Smao d->d_flags |= D_BIGDATA; 120*46131Smao if (_bt_getpage(t, item->bti_pgno) == RET_ERROR) 121*46131Smao return (RET_ERROR); 122*46131Smao } else { 123*46131Smao if (d->d_dsize > 0) { 124*46131Smao (void) bcopy((char *) data->data, 125*46131Smao (char *) &(d->d_bytes[keysize]), 126*46131Smao (int) d->d_dsize); 127*46131Smao } 128*46131Smao } 129*46131Smao 130*46131Smao /* do the insertion */ 131*46131Smao status = _bt_insertat(t, (char *) d, index); 132*46131Smao 133*46131Smao (void) free((char *) d); 134*46131Smao 135*46131Smao return (status); 136*46131Smao } 137*46131Smao 138*46131Smao /* 139*46131Smao * _BT_INSERTI -- Insert IDATUM on current page in the btree. 140*46131Smao * 141*46131Smao * This routine handles insertions to internal pages after splits 142*46131Smao * lower in the tree. On entry, t->bt_curpage is the page to get 143*46131Smao * the new IDATUM. We are also given pgno, the page number of the 144*46131Smao * IDATUM that is immediately left of the new IDATUM's position. 145*46131Smao * This guarantees that the IDATUM for the right half of the page 146*46131Smao * after a split goes next to the IDATUM for its left half. 147*46131Smao * 148*46131Smao * Parameters: 149*46131Smao * t -- tree in which to do insertion. 150*46131Smao * id -- new IDATUM to insert 151*46131Smao * pgno -- page number of IDATUM left of id's position 152*46131Smao * 153*46131Smao * Returns: 154*46131Smao * RET_SUCCESS, RET_ERROR. 155*46131Smao */ 156*46131Smao 157*46131Smao int 158*46131Smao _bt_inserti(t, id, pgno) 159*46131Smao BTREE_P t; 160*46131Smao IDATUM *id; 161*46131Smao pgno_t pgno; 162*46131Smao { 163*46131Smao BTHEADER *h = t->bt_curpage; 164*46131Smao index_t next, i; 165*46131Smao IDATUM *idx; 166*46131Smao char *key; 167*46131Smao pgno_t chain; 168*46131Smao int free_key; 169*46131Smao int ignore; 170*46131Smao 171*46131Smao if (id->i_flags & D_BIGKEY) { 172*46131Smao free_key = TRUE; 173*46131Smao bcopy(&(id->i_bytes[0]), (char *) &chain, sizeof(chain)); 174*46131Smao if (_bt_getbig(t, chain, &key, &ignore) == RET_ERROR) 175*46131Smao return (RET_ERROR); 176*46131Smao } else { 177*46131Smao free_key = FALSE; 178*46131Smao key = &(id->i_bytes[0]); 179*46131Smao } 180*46131Smao i = _bt_binsrch(t, key); 181*46131Smao 182*46131Smao next = NEXTINDEX(h); 183*46131Smao while (i < next && _bt_cmp(t, key, i) >= 0) 184*46131Smao i++; 185*46131Smao 186*46131Smao if (free_key) 187*46131Smao (void) free(key); 188*46131Smao 189*46131Smao /* okay, now we're close; find adjacent IDATUM */ 190*46131Smao for (;;) { 191*46131Smao idx = (IDATUM *) GETDATUM(h,i); 192*46131Smao if (idx->i_pgno == pgno) { 193*46131Smao i++; 194*46131Smao break; 195*46131Smao } 196*46131Smao --i; 197*46131Smao } 198*46131Smao 199*46131Smao /* correctly positioned, do the insertion */ 200*46131Smao return (_bt_insertat(t, (char *) id, i)); 201*46131Smao } 202*46131Smao 203*46131Smao /* 204*46131Smao * _BT_INSERTAT -- Insert a datum at a given location on the current page. 205*46131Smao * 206*46131Smao * This routine does insertions on both leaf and internal pages. 207*46131Smao * 208*46131Smao * Parameters: 209*46131Smao * t -- tree in which to do insertion. 210*46131Smao * p -- DATUM or IDATUM to insert. 211*46131Smao * index -- index in line pointer array to put this item. 212*46131Smao * 213*46131Smao * Returns: 214*46131Smao * RET_SUCCESS, RET_ERROR. 215*46131Smao * 216*46131Smao * Side Effects: 217*46131Smao * Will rearrange line pointers to make space for the new 218*46131Smao * entry. This means that any scans currently active are 219*46131Smao * invalid after this. 220*46131Smao * 221*46131Smao * Warnings: 222*46131Smao * There must be sufficient room for the new item on the page. 223*46131Smao */ 224*46131Smao 225*46131Smao int 226*46131Smao _bt_insertat(t, p, index) 227*46131Smao BTREE_P t; 228*46131Smao char *p; 229*46131Smao index_t index; 230*46131Smao { 231*46131Smao IDATUM *id = (IDATUM *) p; 232*46131Smao DATUM *d = (DATUM *) p; 233*46131Smao BTHEADER *h; 234*46131Smao CURSOR *c; 235*46131Smao index_t nxtindex; 236*46131Smao char *src, *dest; 237*46131Smao int nbytes; 238*46131Smao 239*46131Smao /* insertion may confuse an active scan. fix it. */ 240*46131Smao c = &(t->bt_cursor); 241*46131Smao if (t->bt_flags & BTF_SEQINIT && t->bt_curpage->h_pgno == c->c_pgno) 242*46131Smao if (_bt_fixscan(t, index, d, INSERT) == RET_ERROR) 243*46131Smao return (RET_ERROR); 244*46131Smao 245*46131Smao h = t->bt_curpage; 246*46131Smao nxtindex = (index_t) NEXTINDEX(h); 247*46131Smao 248*46131Smao /* 249*46131Smao * If we're inserting at the middle of the line pointer array, 250*46131Smao * copy pointers that will follow the new one up on the page. 251*46131Smao */ 252*46131Smao 253*46131Smao if (index < nxtindex) { 254*46131Smao src = (char *) &(h->h_linp[index]); 255*46131Smao dest = (char *) &(h->h_linp[index + 1]); 256*46131Smao nbytes = (h->h_lower - (src - ((char *) h))) 257*46131Smao + sizeof(h->h_linp[0]); 258*46131Smao (void) bcopy(src, dest, nbytes); 259*46131Smao } 260*46131Smao 261*46131Smao /* compute size and copy data to page */ 262*46131Smao if (h->h_flags & F_LEAF) { 263*46131Smao nbytes = d->d_ksize + d->d_dsize 264*46131Smao + (sizeof(DATUM) - sizeof(char)); 265*46131Smao } else { 266*46131Smao nbytes = id->i_size + (sizeof(IDATUM) - sizeof(char)); 267*46131Smao } 268*46131Smao dest = (((char *) h) + h->h_upper) - LONGALIGN(nbytes); 269*46131Smao (void) bcopy((char *) p, dest, nbytes); 270*46131Smao 271*46131Smao /* update statistics */ 272*46131Smao dest -= (int) h; 273*46131Smao h->h_linp[index] = (index_t) dest; 274*46131Smao h->h_upper = (index_t) dest; 275*46131Smao h->h_lower += sizeof(index_t); 276*46131Smao 277*46131Smao /* we're done */ 278*46131Smao h->h_flags |= F_DIRTY; 279*46131Smao 280*46131Smao return (RET_SUCCESS); 281*46131Smao } 282