Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

db_dup.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: db_dup.c,v 12.2 2005/06/16 20:21:10 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 
00015 #include <string.h>
00016 #endif
00017 
00018 #include "db_int.h"
00019 #include "dbinc/db_page.h"
00020 #include "dbinc/db_shash.h"
00021 #include "dbinc/mp.h"
00022 #include "dbinc/db_am.h"
00023 
00024 /*
00025  * __db_ditem --
00026  *      Remove an item from a page.
00027  *
00028  * PUBLIC:  int __db_ditem __P((DBC *, PAGE *, u_int32_t, u_int32_t));
00029  */
00030 int
00031 __db_ditem(dbc, pagep, indx, nbytes)
00032         DBC *dbc;
00033         PAGE *pagep;
00034         u_int32_t indx, nbytes;
00035 {
00036         DB *dbp;
00037         DBT ldbt;
00038         db_indx_t cnt, *inp, offset;
00039         int ret;
00040         u_int8_t *from;
00041 
00042         dbp = dbc->dbp;
00043         if (DBC_LOGGING(dbc)) {
00044                 ldbt.data = P_ENTRY(dbp, pagep, indx);
00045                 ldbt.size = nbytes;
00046                 if ((ret = __db_addrem_log(dbp, dbc->txn,
00047                     &LSN(pagep), 0, DB_REM_DUP, PGNO(pagep),
00048                     (u_int32_t)indx, nbytes, &ldbt, NULL, &LSN(pagep))) != 0)
00049                         return (ret);
00050         } else
00051                 LSN_NOT_LOGGED(LSN(pagep));
00052 
00053         /*
00054          * If there's only a single item on the page, we don't have to
00055          * work hard.
00056          */
00057         if (NUM_ENT(pagep) == 1) {
00058                 NUM_ENT(pagep) = 0;
00059                 HOFFSET(pagep) = dbp->pgsize;
00060                 return (0);
00061         }
00062 
00063         inp = P_INP(dbp, pagep);
00064         /*
00065          * Pack the remaining key/data items at the end of the page.  Use
00066          * memmove(3), the regions may overlap.
00067          */
00068         from = (u_int8_t *)pagep + HOFFSET(pagep);
00069         DB_ASSERT(inp[indx] >= HOFFSET(pagep));
00070         memmove(from + nbytes, from, inp[indx] - HOFFSET(pagep));
00071         HOFFSET(pagep) += nbytes;
00072 
00073         /* Adjust the indices' offsets. */
00074         offset = inp[indx];
00075         for (cnt = 0; cnt < NUM_ENT(pagep); ++cnt)
00076                 if (inp[cnt] < offset)
00077                         inp[cnt] += nbytes;
00078 
00079         /* Shift the indices down. */
00080         --NUM_ENT(pagep);
00081         if (indx != NUM_ENT(pagep))
00082                 memmove(&inp[indx], &inp[indx + 1],
00083                     sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
00084 
00085         return (0);
00086 }
00087 
00088 /*
00089  * __db_pitem --
00090  *      Put an item on a page.
00091  *
00092  * PUBLIC: int __db_pitem
00093  * PUBLIC:     __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *));
00094  */
00095 int
00096 __db_pitem(dbc, pagep, indx, nbytes, hdr, data)
00097         DBC *dbc;
00098         PAGE *pagep;
00099         u_int32_t indx;
00100         u_int32_t nbytes;
00101         DBT *hdr, *data;
00102 {
00103         DB *dbp;
00104         BKEYDATA bk;
00105         DBT thdr;
00106         db_indx_t *inp;
00107         int ret;
00108         u_int8_t *p;
00109 
00110         dbp = dbc->dbp;
00111         if (nbytes > P_FREESPACE(dbp, pagep)) {
00112                 DB_ASSERT(nbytes <= P_FREESPACE(dbp, pagep));
00113                 return (EINVAL);
00114         }
00115         /*
00116          * Put a single item onto a page.  The logic figuring out where to
00117          * insert and whether it fits is handled in the caller.  All we do
00118          * here is manage the page shuffling.  We cheat a little bit in that
00119          * we don't want to copy the dbt on a normal put twice.  If hdr is
00120          * NULL, we create a BKEYDATA structure on the page, otherwise, just
00121          * copy the caller's information onto the page.
00122          *
00123          * This routine is also used to put entries onto the page where the
00124          * entry is pre-built, e.g., during recovery.  In this case, the hdr
00125          * will point to the entry, and the data argument will be NULL.
00126          *
00127          * !!!
00128          * There's a tremendous potential for off-by-one errors here, since
00129          * the passed in header sizes must be adjusted for the structure's
00130          * placeholder for the trailing variable-length data field.
00131          */
00132         if (DBC_LOGGING(dbc)) {
00133                 if ((ret = __db_addrem_log(dbp, dbc->txn,
00134                     &LSN(pagep), 0, DB_ADD_DUP, PGNO(pagep),
00135                     (u_int32_t)indx, nbytes, hdr, data, &LSN(pagep))) != 0)
00136                         return (ret);
00137         } else
00138                 LSN_NOT_LOGGED(LSN(pagep));
00139 
00140         if (hdr == NULL) {
00141                 B_TSET(bk.type, B_KEYDATA, 0);
00142                 bk.len = data == NULL ? 0 : data->size;
00143 
00144                 thdr.data = &bk;
00145                 thdr.size = SSZA(BKEYDATA, data);
00146                 hdr = &thdr;
00147         }
00148         inp = P_INP(dbp, pagep);
00149 
00150         /* Adjust the index table, then put the item on the page. */
00151         if (indx != NUM_ENT(pagep))
00152                 memmove(&inp[indx + 1], &inp[indx],
00153                     sizeof(db_indx_t) * (NUM_ENT(pagep) - indx));
00154         HOFFSET(pagep) -= nbytes;
00155         inp[indx] = HOFFSET(pagep);
00156         ++NUM_ENT(pagep);
00157 
00158         p = P_ENTRY(dbp, pagep, indx);
00159         memcpy(p, hdr->data, hdr->size);
00160         if (data != NULL)
00161                 memcpy(p + hdr->size, data->data, data->size);
00162 
00163         return (0);
00164 }

Generated on Sun Dec 25 12:14:19 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2