lock_util.c 3.6 KB
Newer Older
unknown's avatar
unknown committed
1 2 3
/*-
 * See the file LICENSE for redistribution information.
 *
unknown's avatar
unknown committed
4
 * Copyright (c) 1996-2002
unknown's avatar
unknown committed
5 6 7 8 9 10
 *	Sleepycat Software.  All rights reserved.
 */

#include "db_config.h"

#ifndef lint
unknown's avatar
unknown committed
11
static const char revid[] = "$Id: lock_util.c,v 11.8 2002/03/27 04:32:20 bostic Exp $";
unknown's avatar
unknown committed
12 13 14 15 16 17 18 19 20
#endif /* not lint */

#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>

#include <string.h>
#endif

#include "db_int.h"
unknown's avatar
unknown committed
21 22 23 24
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/hash.h"
#include "dbinc/lock.h"
unknown's avatar
unknown committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

/*
 * __lock_cmp --
 *	This function is used to compare a DBT that is about to be entered
 *	into a hash table with an object already in the hash table.  Note
 *	that it just returns true on equal and 0 on not-equal.  Therefore
 *	this function cannot be used as a sort function; its purpose is to
 *	be used as a hash comparison function.
 *
 * PUBLIC: int __lock_cmp __P((const DBT *, DB_LOCKOBJ *));
 */
int
__lock_cmp(dbt, lock_obj)
	const DBT *dbt;
	DB_LOCKOBJ *lock_obj;
{
	void *obj_data;

	obj_data = SH_DBT_PTR(&lock_obj->lockobj);
	return (dbt->size == lock_obj->lockobj.size &&
		memcmp(dbt->data, obj_data, dbt->size) == 0);
}

/*
 * PUBLIC: int __lock_locker_cmp __P((u_int32_t, DB_LOCKER *));
 */
int
__lock_locker_cmp(locker, sh_locker)
	u_int32_t locker;
	DB_LOCKER *sh_locker;
{
	return (locker == sh_locker->id);
}

/*
 * The next two functions are the hash functions used to store objects in the
 * lock hash tables.  They are hashing the same items, but one (__lock_ohash)
 * takes a DBT (used for hashing a parameter passed from the user) and the
 * other (__lock_lhash) takes a DB_LOCKOBJ (used for hashing something that is
 * already in the lock manager).  In both cases, we have a special check to
 * fast path the case where we think we are doing a hash on a DB page/fileid
 * pair.  If the size is right, then we do the fast hash.
 *
 * We know that DB uses DB_LOCK_ILOCK types for its lock objects.  The first
 * four bytes are the 4-byte page number and the next DB_FILE_ID_LEN bytes
 * are a unique file id, where the first 4 bytes on UNIX systems are the file
 * inode number, and the first 4 bytes on Windows systems are the FileIndexLow
 * bytes.  So, we use the XOR of the page number and the first four bytes of
 * the file id to produce a 32-bit hash value.
 *
 * We have no particular reason to believe that this algorithm will produce
 * a good hash, but we want a fast hash more than we want a good one, when
 * we're coming through this code path.
 */
#define	FAST_HASH(P) {			\
	u_int32_t __h;			\
	u_int8_t *__cp, *__hp;		\
	__hp = (u_int8_t *)&__h;	\
	__cp = (u_int8_t *)(P);		\
	__hp[0] = __cp[0] ^ __cp[4];	\
	__hp[1] = __cp[1] ^ __cp[5];	\
	__hp[2] = __cp[2] ^ __cp[6];	\
	__hp[3] = __cp[3] ^ __cp[7];	\
	return (__h);			\
}

/*
 * __lock_ohash --
 *
 * PUBLIC: u_int32_t __lock_ohash __P((const DBT *));
 */
u_int32_t
__lock_ohash(dbt)
	const DBT *dbt;
{
	if (dbt->size == sizeof(DB_LOCK_ILOCK))
		FAST_HASH(dbt->data);

	return (__ham_func5(NULL, dbt->data, dbt->size));
}

/*
 * __lock_lhash --
 *
 * PUBLIC: u_int32_t __lock_lhash __P((DB_LOCKOBJ *));
 */
u_int32_t
__lock_lhash(lock_obj)
	DB_LOCKOBJ *lock_obj;
{
	void *obj_data;

	obj_data = SH_DBT_PTR(&lock_obj->lockobj);

	if (lock_obj->lockobj.size == sizeof(DB_LOCK_ILOCK))
		FAST_HASH(obj_data);

	return (__ham_func5(NULL, obj_data, lock_obj->lockobj.size));
}

/*
 * __lock_locker_hash --
 *	Hash function for entering lockers into the locker hash table.
 *	Since these are simply 32-bit unsigned integers, just return
 *	the locker value.
 *
 * PUBLIC: u_int32_t __lock_locker_hash __P((u_int32_t));
 */
u_int32_t
__lock_locker_hash(locker)
	u_int32_t locker;
{
	return (locker);
}