00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #include <string.h>
00016 #include <stdlib.h>
00017 #endif
00018
00019 #include "db_int.h"
00020 #include "dbinc/db_shash.h"
00021 #include "dbinc/lock.h"
00022 #include "dbinc/log.h"
00023
00024 static int __lock_sort_cmp __P((const void *, const void *));
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #define MAX_PGNOS 0xffff
00055
00056
00057
00058
00059
00060
00061 #define RET_SIZE(size, count) ((size) + \
00062 sizeof(u_int32_t) + (count) * 2 * sizeof(u_int16_t))
00063
00064 #define PUT_COUNT(dp, count) do { u_int32_t *ip = (u_int32_t *)dp;\
00065 *ip = count; \
00066 dp = (u_int8_t *)dp + \
00067 sizeof(u_int32_t); \
00068 } while (0)
00069 #define PUT_PCOUNT(dp, count) do { u_int16_t *ip = (u_int16_t *)dp;\
00070 *ip = count; \
00071 dp = (u_int8_t *)dp + \
00072 sizeof(u_int16_t); \
00073 } while (0)
00074 #define PUT_SIZE(dp, size) do { u_int16_t *ip = (u_int16_t *)dp;\
00075 *ip = size; \
00076 dp = (u_int8_t *)dp + \
00077 sizeof(u_int16_t); \
00078 } while (0)
00079 #define PUT_PGNO(dp, pgno) do { db_pgno_t *ip = (db_pgno_t *)dp;\
00080 *ip = pgno; \
00081 dp = (u_int8_t *)dp + \
00082 sizeof(db_pgno_t); \
00083 } while (0)
00084 #define COPY_OBJ(dp, obj) do { \
00085 memcpy(dp, \
00086 (obj)->data, (obj)->size); \
00087 dp = (u_int8_t *)dp + \
00088 DB_ALIGN((obj)->size, \
00089 sizeof(u_int32_t)); \
00090 } while (0)
00091 #define GET_COUNT(dp, count) do { \
00092 (count) = *(u_int32_t *)dp; \
00093 dp = (u_int8_t *)dp + \
00094 sizeof(u_int32_t); \
00095 } while (0)
00096 #define GET_PCOUNT(dp, count) do { \
00097 (count) = *(u_int16_t *)dp; \
00098 dp = (u_int8_t *)dp + \
00099 sizeof(u_int16_t); \
00100 } while (0)
00101 #define GET_SIZE(dp, size) do { \
00102 (size) = *(u_int16_t *)dp; \
00103 dp = (u_int8_t *)dp + \
00104 sizeof(u_int16_t); \
00105 } while (0)
00106 #define GET_PGNO(dp, pgno) do { \
00107 (pgno) = *(db_pgno_t *)dp; \
00108 dp = (u_int8_t *)dp + \
00109 sizeof(db_pgno_t); \
00110 } while (0)
00111
00112
00113
00114
00115
00116
00117 int
00118 __lock_fix_list(dbenv, list_dbt, nlocks)
00119 DB_ENV *dbenv;
00120 DBT *list_dbt;
00121 u_int32_t nlocks;
00122 {
00123 DBT *obj;
00124 DB_LOCK_ILOCK *lock, *plock;
00125 u_int32_t i, j, nfid, npgno, size;
00126 u_int8_t *data, *dp;
00127 int ret;
00128
00129 if ((size = list_dbt->size) == 0)
00130 return (0);
00131
00132 obj = (DBT *)list_dbt->data;
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 switch (nlocks) {
00143 case 1:
00144 size = RET_SIZE(obj->size, 1);
00145 if ((ret = __os_malloc(dbenv, size, &data)) != 0)
00146 return (ret);
00147
00148 dp = data;
00149 PUT_COUNT(dp, 1);
00150 PUT_PCOUNT(dp, 0);
00151 PUT_SIZE(dp, obj->size);
00152 COPY_OBJ(dp, obj);
00153 break;
00154 default:
00155
00156 qsort(list_dbt->data, nlocks, sizeof(DBT), __lock_sort_cmp);
00157
00158 case 2:
00159 nfid = npgno = 0;
00160 i = 0;
00161 if (obj->size != sizeof(DB_LOCK_ILOCK))
00162 goto not_ilock;
00163
00164 nfid = 1;
00165 plock = (DB_LOCK_ILOCK *)obj->data;
00166
00167
00168 j = 0;
00169 obj[0].ulen = 0;
00170 for (i = 1; i < nlocks; i++) {
00171 if (obj[i].size != sizeof(DB_LOCK_ILOCK))
00172 break;
00173 lock = (DB_LOCK_ILOCK *)obj[i].data;
00174 if (obj[j].ulen < MAX_PGNOS &&
00175 lock->type == plock->type &&
00176 memcmp(lock->fileid,
00177 plock->fileid, DB_FILE_ID_LEN) == 0) {
00178 obj[j].ulen++;
00179 npgno++;
00180 } else {
00181 nfid++;
00182 plock = lock;
00183 j = i;
00184 obj[j].ulen = 0;
00185 }
00186 }
00187
00188 not_ilock: size = nfid * sizeof(DB_LOCK_ILOCK);
00189 size += npgno * sizeof(db_pgno_t);
00190
00191 nfid += nlocks - i;
00192 for (; i < nlocks; i++) {
00193 size += obj[i].size;
00194 obj[i].ulen = 0;
00195 }
00196
00197 size = RET_SIZE(size, nfid);
00198 if ((ret = __os_malloc(dbenv, size, &data)) != 0)
00199 return (ret);
00200
00201 dp = data;
00202 PUT_COUNT(dp, nfid);
00203
00204 for (i = 0; i < nlocks; i = j) {
00205 PUT_PCOUNT(dp, obj[i].ulen);
00206 PUT_SIZE(dp, obj[i].size);
00207 COPY_OBJ(dp, &obj[i]);
00208 lock = (DB_LOCK_ILOCK *)obj[i].data;
00209 for (j = i + 1; j <= i + obj[i].ulen; j++) {
00210 lock = (DB_LOCK_ILOCK *)obj[j].data;
00211 PUT_PGNO(dp, lock->pgno);
00212 }
00213 }
00214 }
00215
00216 __os_free(dbenv, list_dbt->data);
00217
00218 list_dbt->data = data;
00219 list_dbt->size = size;
00220
00221 return (0);
00222 }
00223
00224
00225
00226
00227
00228 int
00229 __lock_get_list(dbenv, locker, flags, lock_mode, list)
00230 DB_ENV *dbenv;
00231 u_int32_t locker, flags;
00232 db_lockmode_t lock_mode;
00233 DBT *list;
00234 {
00235 DBT obj_dbt;
00236 DB_LOCK ret_lock;
00237 DB_LOCK_ILOCK *lock;
00238 DB_LOCKTAB *lt;
00239 db_pgno_t save_pgno;
00240 u_int16_t npgno, size;
00241 u_int32_t i, nlocks;
00242 int ret;
00243 void *data, *dp;
00244
00245 if (list->size == 0)
00246 return (0);
00247 ret = 0;
00248 data = NULL;
00249
00250 lt = dbenv->lk_handle;
00251 dp = list->data;
00252
00253
00254
00255
00256
00257
00258 if ((uintptr_t)dp != DB_ALIGN((uintptr_t)dp, sizeof(u_int32_t))) {
00259 if ((ret = __os_malloc(dbenv, list->size, &data)) != 0)
00260 return (ret);
00261 memcpy(data, list->data, list->size);
00262 dp = data;
00263 }
00264
00265 GET_COUNT(dp, nlocks);
00266 LOCK_SYSTEM_LOCK(dbenv);
00267
00268 for (i = 0; i < nlocks; i++) {
00269 GET_PCOUNT(dp, npgno);
00270 GET_SIZE(dp, size);
00271 lock = (DB_LOCK_ILOCK *) dp;
00272 save_pgno = lock->pgno;
00273 obj_dbt.data = dp;
00274 obj_dbt.size = size;
00275 dp = ((u_int8_t *)dp) + DB_ALIGN(size, sizeof(u_int32_t));
00276 do {
00277 if ((ret = __lock_get_internal(lt, locker,
00278 flags, &obj_dbt, lock_mode, 0, &ret_lock)) != 0) {
00279 lock->pgno = save_pgno;
00280 goto err;
00281 }
00282 if (npgno != 0)
00283 GET_PGNO(dp, lock->pgno);
00284 } while (npgno-- != 0);
00285 lock->pgno = save_pgno;
00286 }
00287
00288 err: LOCK_SYSTEM_UNLOCK(dbenv);
00289 if (data != NULL)
00290 __os_free(dbenv, data);
00291 return (ret);
00292 }
00293
00294 #define UINT32_CMP(A, B) ((A) == (B) ? 0 : ((A) > (B) ? 1 : -1))
00295 static int
00296 __lock_sort_cmp(a, b)
00297 const void *a, *b;
00298 {
00299 const DBT *d1, *d2;
00300 DB_LOCK_ILOCK *l1, *l2;
00301
00302 d1 = a;
00303 d2 = b;
00304
00305
00306 if (d1->size != sizeof(DB_LOCK_ILOCK)) {
00307 if (d2->size != sizeof(DB_LOCK_ILOCK))
00308 return (UINT32_CMP(d1->size, d2->size));
00309 else
00310 return (1);
00311 } else if (d2->size != sizeof(DB_LOCK_ILOCK))
00312 return (-1);
00313
00314 l1 = d1->data;
00315 l2 = d2->data;
00316 if (l1->type != l2->type)
00317 return (UINT32_CMP(l1->type, l2->type));
00318 return (memcmp(l1->fileid, l2->fileid, DB_FILE_ID_LEN));
00319 }
00320
00321
00322
00323
00324 void
00325 __lock_list_print(dbenv, list)
00326 DB_ENV *dbenv;
00327 DBT *list;
00328 {
00329 DB_LOCK_ILOCK *lock;
00330 db_pgno_t pgno;
00331 u_int16_t npgno, size;
00332 u_int32_t i, nlocks;
00333 u_int8_t *fidp;
00334 char *namep;
00335 void *dp;
00336
00337 if (list->size == 0)
00338 return;
00339 dp = list->data;
00340
00341 GET_COUNT(dp, nlocks);
00342
00343 for (i = 0; i < nlocks; i++) {
00344 GET_PCOUNT(dp, npgno);
00345 GET_SIZE(dp, size);
00346 lock = (DB_LOCK_ILOCK *) dp;
00347 fidp = lock->fileid;
00348 if (__dbreg_get_name(dbenv, fidp, &namep) != 0)
00349 namep = NULL;
00350 printf("\t");
00351 if (namep == NULL)
00352 printf("(%lx %lx %lx %lx %lx)",
00353 (u_long)fidp[0], (u_long)fidp[1], (u_long)fidp[2],
00354 (u_long)fidp[3], (u_long)fidp[4]);
00355 else
00356 printf("%-25s", namep);
00357 dp = ((u_int8_t *)dp) + DB_ALIGN(size, sizeof(u_int32_t));
00358 pgno = lock->pgno;
00359 do {
00360 printf(" %d", pgno);
00361 if (npgno != 0)
00362 GET_PGNO(dp, pgno);
00363 } while (npgno-- != 0);
00364 printf("\n");
00365 }
00366 }