Wireless Networking & Berkeley DB
by Ray Van Tassle and Marjorie Richardson


Listing One
/************** The layout for secondary keys ****************/
/* secondary key = ipaddr */
struct mob_ip_sec_key {
   unsigned long mis_sec_type;  /* The secondary type & flag. */
   unsigned long mis_ipaddr;    /* The ipaddr */
};
int mb_delete_mobile(int dcb_han, unsigned long lli)
{
   static char fn[] = "mb_delete_mobile";
   int st;
   int st1;
   DB_TXN *tid = NULL;          /* The transaction control block */
   int rtt = 0;                 /* Transaction retry count */
   struct mob_ip_sec_key msk;   /* The secondary key buffer */
   DBT mi_data_dbt = {0};       /* The data descriptor for mr_ipaddr.     */
   DBT ipkey_dbt = {0};         /* The key descriptor for the ip sec key. */
   DBT key_dbt = {0};           /* Key for the LLI */
   DBC *csr_mob = NULL;         /* cursor for the mobile (LLI) record.    */
   unsigned long mobs_ipaddr;   /* The ipaddr of the mobile (lli) */

   LOCK_SET(DB_LOCK_WRITE);     /* Set the high-level lock. */
   if (0) {                     /* Abort and retry */
      retry:;                   /* Repeat the aborted transaction */
      if (++rtt < 10 || (rtt % 100) == 1)
    printf("retry/txn_abort %d.\n", rtt);
      csr_mob->c_close(csr_mob);
      txn_abort(tid);
   }
   /* Begin a transaction block.  Either all or none of the updates 
    * will be written to the database. */
   st = txn_begin(dcb.dc_dbenv, NULL, &tid, 0);
   if (st != 0) {
      (*dcb.dc_db_err_rtn)(fn, dcb.dc_filename, st); /* user's error func */
      errno = st;
      dprintf("%s: txn_begin error st: %d", dcb.dc_progname, st);
      LOCK_RELEASE();
      return (-2);
   }
   /* Acquire a cursor for the mobile record. */
   st = dcb.dc_dbp->cursor(dcb.dc_dbp, tid, &csr_mob, 0);
   if (st != 0) {   /* NZ means some kind of error */
      (*dcb.dc_db_err_rtn)(fn, dcb.dc_filename, st);
      dprintf("cursor_open: %d\n", st);
      txn_abort(tid);
      LOCK_RELEASE();
      errno = st;
      return(-1);
   }
   /* Read the secondary key value(s), and delete the secondary key(s). */
   msk.mis_sec_type = SK_IPADDR_MAGIC;
   key_dbt.data = &lli; /* Set up the key descriptor */
   key_dbt.size = sizeof(lli);
   ipkey_dbt.data = &msk;   /* Set up the ip secondary key descriptor */
   ipkey_dbt.size = sizeof(msk);
   /* Set up the data descriptor, to only access (read/write) the
    * ipaddr field of the mobile's (LLI) record.  */
   mi_data_dbt.doff = SSZ(struct mob_keys, mr_ipaddr);
   mi_data_dbt.ulen = mi_data_dbt.dlen = sizeof(mobs_ipaddr);
   mi_data_dbt.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
   mi_data_dbt.data = &mobs_ipaddr;
   st = csr_mob->c_get(csr_mob, &key_dbt, &mi_data_dbt, DB_SET | DB_RMW);
   dprintf("mb_delete_mob: c_get rtn: %d\n", st);
   if (st == DB_LOCK_DEADLOCK)
      goto retry;
   if (st != 0) {       /* NZ means some kind of error */
      if (st != DB_NOTFOUND)
     (*dcb.dc_db_err_rtn)(fn, dcb.dc_filename, st);
      dprintf("mb_delete_mob: getcurrent: %d\n", st);
      st1 = csr_mob->c_close(csr_mob);  /* Discard the cursor. */
      txn_abort(tid);
      LOCK_RELEASE();
      errno = st;
      return ((st == DB_NOTFOUND) ? 0 : -2);
   }
   dprintf("mb_delete_mob: del_key: %08x\n", *(unsigned long *)key_dbt.data);
   dprintf("mb_delete_mob: has current ipaddr: %x\n", mobs_ipaddr);

   st = csr_mob->c_del(csr_mob, 0);
   dprintf("mb_delete_mob: c_del rtn: %d\n", st);
   if (st == DB_LOCK_DEADLOCK)
      goto retry;
   if (st != 0)     /* NZ means some kind of error */
      (*dcb.dc_db_err_rtn)(fn, dcb.dc_filename, st);

   /*** Delete the ipaddr_sec_key record ***/
   if (mobs_ipaddr != 0) {
      msk.mis_ipaddr = mobs_ipaddr;
      st1 = dcb.dc_dbp->del(dcb.dc_dbp, tid, &ipkey_dbt, 0);
      dprintf("mb_delete_mob: del old sec key. st: %d\n", st);
      if (st == DB_LOCK_DEADLOCK)
     goto retry;
      if (st1 != 0)
     (*dcb.dc_db_err_rtn)(fn, dcb.dc_filename, st1);
   }
   st1 = csr_mob->c_close(csr_mob); /* Discard the cursor. */
   txn_commit(tid, 0);
   if (st1 != 0)
      (*dcb.dc_db_err_rtn)(fn, dcb.dc_filename, st);
   LOCK_RELEASE();
   if (st == 0)
      return (1);
   (*dcb.dc_db_err_rtn)(fn, dcb.dc_filename, st);
   if (st > 0)
      return (-st);
   return (st);
}





3


