1 /*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996, 1997, 1998 5 * Sleepycat Software. All rights reserved. 6 */ 7 8 #include "config.h" 9 10 #ifndef lint 11 static const char sccsid[] = "@(#)lock_util.c 10.10 (Sleepycat) 9/20/98"; 12 #endif /* not lint */ 13 14 #ifndef NO_SYSTEM_INCLUDES 15 #include <sys/types.h> 16 17 #include <string.h> 18 #endif 19 20 #include "db_int.h" 21 #include "shqueue.h" 22 #include "db_page.h" 23 #include "db_shash.h" 24 #include "hash.h" 25 #include "lock.h" 26 27 /* 28 * __lock_cmp -- 29 * This function is used to compare a DBT that is about to be entered 30 * into a hash table with an object already in the hash table. Note 31 * that it just returns true on equal and 0 on not-equal. Therefore 32 * this function cannot be used as a sort function; its purpose is to 33 * be used as a hash comparison function. 34 * 35 * PUBLIC: int __lock_cmp __P((const DBT *, DB_LOCKOBJ *)); 36 */ 37 int 38 __lock_cmp(dbt, lock_obj) 39 const DBT *dbt; 40 DB_LOCKOBJ *lock_obj; 41 { 42 void *obj_data; 43 44 if (lock_obj->type != DB_LOCK_OBJTYPE) 45 return (0); 46 47 obj_data = SH_DBT_PTR(&lock_obj->lockobj); 48 return (dbt->size == lock_obj->lockobj.size && 49 memcmp(dbt->data, obj_data, dbt->size) == 0); 50 } 51 52 /* 53 * PUBLIC: int __lock_locker_cmp __P((u_int32_t, DB_LOCKOBJ *)); 54 */ 55 int 56 __lock_locker_cmp(locker, lock_obj) 57 u_int32_t locker; 58 DB_LOCKOBJ *lock_obj; 59 { 60 void *obj_data; 61 62 if (lock_obj->type != DB_LOCK_LOCKER) 63 return (0); 64 65 obj_data = SH_DBT_PTR(&lock_obj->lockobj); 66 return (memcmp(&locker, obj_data, sizeof(u_int32_t)) == 0); 67 } 68 69 /* 70 * The next two functions are the hash functions used to store objects in the 71 * lock hash table. They are hashing the same items, but one (__lock_ohash) 72 * takes a DBT (used for hashing a parameter passed from the user) and the 73 * other (__lock_lhash) takes a DB_LOCKOBJ (used for hashing something that is 74 * already in the lock manager). In both cases, we have a special check to 75 * fast path the case where we think we are doing a hash on a DB page/fileid 76 * pair. If the size is right, then we do the fast hash. 77 * 78 * We know that DB uses DB_LOCK_ILOCK types for its lock objects. The first 79 * four bytes are the 4-byte page number and the next DB_FILE_ID_LEN bytes 80 * are a unique file id, where the first 4 bytes on UNIX systems are the file 81 * inode number, and the first 4 bytes on Windows systems are the FileIndexLow 82 * bytes. So, we use the XOR of the page number and the first four bytes of 83 * the file id to produce a 32-bit hash value. 84 * 85 * We have no particular reason to believe that this algorithm will produce 86 * a good hash, but we want a fast hash more than we want a good one, when 87 * we're coming through this code path. 88 */ 89 #define FAST_HASH(P) { \ 90 u_int32_t __h; \ 91 u_int8_t *__cp, *__hp; \ 92 __hp = (u_int8_t *)&__h; \ 93 __cp = (u_int8_t *)(P); \ 94 __hp[0] = __cp[0] ^ __cp[4]; \ 95 __hp[1] = __cp[1] ^ __cp[5]; \ 96 __hp[2] = __cp[2] ^ __cp[6]; \ 97 __hp[3] = __cp[3] ^ __cp[7]; \ 98 return (__h); \ 99 } 100 101 /* 102 * __lock_ohash -- 103 * 104 * PUBLIC: u_int32_t __lock_ohash __P((const DBT *)); 105 */ 106 u_int32_t 107 __lock_ohash(dbt) 108 const DBT *dbt; 109 { 110 if (dbt->size == sizeof(DB_LOCK_ILOCK)) 111 FAST_HASH(dbt->data); 112 113 return (__ham_func5(dbt->data, dbt->size)); 114 } 115 116 /* 117 * __lock_lhash -- 118 * 119 * PUBLIC: u_int32_t __lock_lhash __P((DB_LOCKOBJ *)); 120 */ 121 u_int32_t 122 __lock_lhash(lock_obj) 123 DB_LOCKOBJ *lock_obj; 124 { 125 u_int32_t tmp; 126 void *obj_data; 127 128 obj_data = SH_DBT_PTR(&lock_obj->lockobj); 129 if (lock_obj->type == DB_LOCK_LOCKER) { 130 memcpy(&tmp, obj_data, sizeof(u_int32_t)); 131 return (tmp); 132 } 133 134 if (lock_obj->lockobj.size == sizeof(DB_LOCK_ILOCK)) 135 FAST_HASH(obj_data); 136 137 return (__ham_func5(obj_data, lock_obj->lockobj.size)); 138 } 139 140 /* 141 * __lock_locker_hash -- 142 * Hash function for entering lockers into the hash table. Since these 143 * are simply 32-bit unsigned integers, just return the locker value. 144 * 145 * PUBLIC: u_int32_t __lock_locker_hash __P((u_int32_t)); 146 */ 147 u_int32_t 148 __lock_locker_hash(locker) 149 u_int32_t locker; 150 { 151 return (locker); 152 } 153