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

#include "db_config.h"

#ifndef lint
ram@mysql.r18.ru's avatar
ram@mysql.r18.ru committed
11
static const char revid[] = "$Id: lock_util.c,v 11.8 2002/03/27 04:32:20 bostic Exp $";
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"
ram@mysql.r18.ru's avatar
ram@mysql.r18.ru committed
21 22 23 24
#include "dbinc/db_page.h"
#include "dbinc/db_shash.h"
#include "dbinc/hash.h"
#include "dbinc/lock.h"
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);
}