예제 #1
0
파일: gdbmseq.c 프로젝트: Distrotech/gdbm
datum
gdbm_nextkey (GDBM_FILE dbf, datum key)
{
  datum  return_val;		/* The return value. */
  int    elem_loc;		/* The location in the bucket. */
  char  *find_data;		/* Data pointer returned by _gdbm_findkey. */
  int    hash_val;		/* Returned by _gdbm_findkey. */

  /* Initialize the gdbm_errno variable. */
  gdbm_errno = GDBM_NO_ERROR;

  /* Set the default return value for no next entry. */
  return_val.dptr = NULL;

  /* Do we have a valid key? */
  if (key.dptr == NULL) return return_val;

  /* Find the key.  */
  elem_loc = _gdbm_findkey (dbf, key, &find_data, &hash_val);
  if (elem_loc == -1) return return_val;

  /* Find the next key. */  
  get_next_key (dbf, elem_loc, &return_val);

  return return_val;
}
예제 #2
0
int
gdbm_exists (GDBM_FILE dbf, datum key)
{
  char *find_data;		/* Dummy */
  int hash_val;			/* Dummy */

  return (_gdbm_findkey (dbf, key, &find_data, &hash_val) >= 0);
}
예제 #3
0
파일: gdbmstore.c 프로젝트: 4honor/QConf
int
gdbm_store (GDBM_FILE dbf, datum key, datum content, int flags)
{
  int  new_hash_val;		/* The new hash value. */
  int  elem_loc;		/* The location in hash bucket. */
  off_t file_adr;		/* The address of new space in the file.  */
  off_t file_pos;		/* The position after a lseek. */
  off_t free_adr;		/* For keeping track of a freed section. */
  int  free_size;
  int   new_size;		/* Used in allocating space. */
  char *temp;			/* Used in _gdbm_findkey call. */
  int rc;

  /* First check to make sure this guy is a writer. */
  if (dbf->read_write == GDBM_READER)
    {
      gdbm_errno = GDBM_READER_CANT_STORE;
      return -1;
    }

  /* Check for illegal data values.  A NULL dptr field is illegal because
     NULL dptr returned by a lookup procedure indicates an error. */
  if ((key.dptr == NULL) || (content.dptr == NULL))
    {
      gdbm_errno = GDBM_ILLEGAL_DATA;
      return -1;
    }

  /* Initialize the gdbm_errno variable. */
  gdbm_errno = GDBM_NO_ERROR;

  /* Look for the key in the file.
     A side effect loads the correct bucket and calculates the hash value. */
  elem_loc = _gdbm_findkey (dbf, key, &temp, &new_hash_val);

  /* Initialize these. */
  file_adr = 0;
  new_size = key.dsize + content.dsize;

  /* Did we find the item? */
  if (elem_loc != -1)
    {
      if (flags == GDBM_REPLACE)
	{
	  /* Just replace the data. */
	  free_adr = dbf->bucket->h_table[elem_loc].data_pointer;
	  free_size = dbf->bucket->h_table[elem_loc].key_size
	              + dbf->bucket->h_table[elem_loc].data_size;
	  if (free_size != new_size)
	    {
	      _gdbm_free (dbf, free_adr, free_size);
	    }
	  else
	    {
	      /* Just reuse the same address! */
	      file_adr = free_adr;
	    }
	}
      else
	{
	  gdbm_errno = GDBM_CANNOT_REPLACE;
	  return 1;
	}
    }


  /* Get the file address for the new space.
     (Current bucket's free space is first place to look.) */
  if (file_adr == 0)
    file_adr = _gdbm_alloc (dbf, new_size);

  /* If this is a new entry in the bucket, we need to do special things. */
  if (elem_loc == -1)
    {
      if (dbf->bucket->count == dbf->header->bucket_elems)
	{
	  /* Split the current bucket. */
	  _gdbm_split_bucket (dbf, new_hash_val);
	}
      
      /* Find space to insert into bucket and set elem_loc to that place. */
      elem_loc = new_hash_val % dbf->header->bucket_elems;
      while (dbf->bucket->h_table[elem_loc].hash_value != -1)
	elem_loc = (elem_loc + 1) % dbf->header->bucket_elems;

      /* We now have another element in the bucket.  Add the new information.*/
      dbf->bucket->count++;
      dbf->bucket->h_table[elem_loc].hash_value = new_hash_val;
      memcpy (dbf->bucket->h_table[elem_loc].key_start, key.dptr,
	     (SMALL < key.dsize ? SMALL : key.dsize));
    }


  /* Update current bucket data pointer and sizes. */
  dbf->bucket->h_table[elem_loc].data_pointer = file_adr;
  dbf->bucket->h_table[elem_loc].key_size = key.dsize;
  dbf->bucket->h_table[elem_loc].data_size = content.dsize;

  /* Write the data to the file. */
  file_pos = __lseek (dbf, file_adr, SEEK_SET);
  if (file_pos != file_adr)
    _gdbm_fatal (dbf, _("lseek error"));
  rc = _gdbm_full_write (dbf, key.dptr, key.dsize);
  if (rc)
    _gdbm_fatal (dbf, gdbm_strerror (rc));
  rc = _gdbm_full_write (dbf, content.dptr, content.dsize);
  if (rc)
    _gdbm_fatal (dbf, gdbm_strerror (rc));

  /* Current bucket has changed. */
  dbf->cache_entry->ca_changed = TRUE;
  dbf->bucket_changed = TRUE;

  /* Write everything that is needed to the disk. */
  _gdbm_end_update (dbf);
  return 0;
  
}
예제 #4
0
int
gdbm_delete (GDBM_FILE dbf, datum key)
{
  int elem_loc;		/* The location in the current hash bucket. */
  int last_loc;		/* Last location emptied by the delete.  */
  int home;		/* Home position of an item. */
  bucket_element elem;  /* The element to be deleted. */
  char *find_data;	/* Return pointer from findkey. */
  int   hash_val;	/* Returned by findkey. */
  off_t free_adr;       /* Temporary stroage for address and size. */
  int   free_size;

  /* First check to make sure this guy is a writer. */
  if (dbf->read_write == GDBM_READER)
    {
      gdbm_errno = GDBM_READER_CANT_DELETE;
      return -1;
    }

  /* Initialize the gdbm_errno variable. */
  gdbm_errno = GDBM_NO_ERROR;

  /* Find the item. */
  elem_loc = _gdbm_findkey (dbf, key, &find_data, &hash_val);
  if (elem_loc == -1)
    {
      gdbm_errno = GDBM_ITEM_NOT_FOUND;
      return -1;
    }

  /* Save the element.  */
  elem = dbf->bucket->h_table[elem_loc];

  /* Delete the element.  */
  dbf->bucket->h_table[elem_loc].hash_value = -1;
  dbf->bucket->count -= 1;

  /* Move other elements to guarantee that they can be found. */
  last_loc = elem_loc;
  elem_loc = (elem_loc + 1) % dbf->header->bucket_elems;
  while (elem_loc != last_loc
	 && dbf->bucket->h_table[elem_loc].hash_value != -1)
    {
      home = dbf->bucket->h_table[elem_loc].hash_value
	     % dbf->header->bucket_elems;
      if ( (last_loc < elem_loc && (home <= last_loc || home > elem_loc))
	  || (last_loc > elem_loc && home <= last_loc && home > elem_loc))
	
	{
	  dbf->bucket->h_table[last_loc] = dbf->bucket->h_table[elem_loc];
	  dbf->bucket->h_table[elem_loc].hash_value = -1;
	  last_loc = elem_loc;
	}
      elem_loc = (elem_loc + 1) % dbf->header->bucket_elems;
    }

  /* Free the file space. */
  free_adr = elem.data_pointer;
  free_size = elem.key_size + elem.data_size;
  _gdbm_free (dbf, free_adr, free_size);

  /* Set the flags. */
  dbf->bucket_changed = TRUE;

  /* Clear out the data cache for the current bucket. */
  if (dbf->cache_entry->ca_data.dptr != NULL)
    {
      free (dbf->cache_entry->ca_data.dptr);
      dbf->cache_entry->ca_data.dptr = NULL;
    }
  dbf->cache_entry->ca_data.hash_val = -1;
  dbf->cache_entry->ca_data.key_size = 0;
  dbf->cache_entry->ca_data.elem_loc = -1;

  /* Do the writes. */
  _gdbm_end_update (dbf);
  return 0;  
}