Contents of /trunk/db/patches/patch.4.1.25.2
Parent Directory | Revision Log
Revision 144 -
(show annotations)
(download)
Tue May 8 20:06:05 2007 UTC (17 years, 4 months ago) by niro
File size: 18100 byte(s)
Tue May 8 20:06:05 2007 UTC (17 years, 4 months ago) by niro
File size: 18100 byte(s)
-import
1 | *** dbinc/mp.h.orig 2004-02-02 10:24:53.000000000 -0800 |
2 | --- dbinc/mp.h 2004-02-02 10:26:27.000000000 -0800 |
3 | *************** |
4 | *** 149,154 **** |
5 | --- 149,161 ---- |
6 | * region lock). |
7 | */ |
8 | DB_MPOOL_STAT stat; /* Per-cache mpool statistics. */ |
9 | + |
10 | + /* |
11 | + * We track page puts so that we can decide when allocation is never |
12 | + * going to succeed. We don't lock the field, all we care about is |
13 | + * if it changes. |
14 | + */ |
15 | + u_int32_t put_counter; /* Count of page put calls. */ |
16 | }; |
17 | |
18 | struct __db_mpool_hash { |
19 | *** mp/mp_fput.c.orig 2002-08-13 06:26:41.000000000 -0700 |
20 | --- mp/mp_fput.c 2004-02-02 10:22:35.000000000 -0800 |
21 | *************** |
22 | *** 19,24 **** |
23 | --- 19,26 ---- |
24 | #include "dbinc/db_shash.h" |
25 | #include "dbinc/mp.h" |
26 | |
27 | + static void __memp_reset_lru __P((DB_ENV *, REGINFO *)); |
28 | + |
29 | /* |
30 | * __memp_fput -- |
31 | * Mpool file put function. |
32 | *************** |
33 | *** 198,202 **** |
34 | --- 200,255 ---- |
35 | |
36 | MUTEX_UNLOCK(dbenv, &hp->hash_mutex); |
37 | |
38 | + /* |
39 | + * On every buffer put we update the buffer generation number and check |
40 | + * for wraparound. |
41 | + */ |
42 | + if (++c_mp->lru_count == UINT32_T_MAX) |
43 | + __memp_reset_lru(dbenv, dbmp->reginfo); |
44 | + |
45 | return (0); |
46 | } |
47 | + |
48 | + /* |
49 | + * __memp_reset_lru -- |
50 | + * Reset the cache LRU counter. |
51 | + */ |
52 | + static void |
53 | + __memp_reset_lru(dbenv, memreg) |
54 | + DB_ENV *dbenv; |
55 | + REGINFO *memreg; |
56 | + { |
57 | + BH *bhp; |
58 | + DB_MPOOL_HASH *hp; |
59 | + MPOOL *c_mp; |
60 | + int bucket; |
61 | + |
62 | + c_mp = memreg->primary; |
63 | + |
64 | + /* |
65 | + * Update the counter so all future allocations will start at the |
66 | + * bottom. |
67 | + */ |
68 | + c_mp->lru_count -= MPOOL_BASE_DECREMENT; |
69 | + |
70 | + /* Adjust the priority of every buffer in the system. */ |
71 | + for (hp = R_ADDR(memreg, c_mp->htab), |
72 | + bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) { |
73 | + /* |
74 | + * Skip empty buckets. |
75 | + * |
76 | + * We can check for empty buckets before locking as we |
77 | + * only care if the pointer is zero or non-zero. |
78 | + */ |
79 | + if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL) |
80 | + continue; |
81 | + |
82 | + MUTEX_LOCK(dbenv, &hp->hash_mutex); |
83 | + for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh); |
84 | + bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) |
85 | + if (bhp->priority != UINT32_T_MAX && |
86 | + bhp->priority > MPOOL_BASE_DECREMENT) |
87 | + bhp->priority -= MPOOL_BASE_DECREMENT; |
88 | + MUTEX_UNLOCK(dbenv, &hp->hash_mutex); |
89 | + } |
90 | + } |
91 | *** mp/mp_alloc.c.orig 2002-08-17 07:23:25.000000000 -0700 |
92 | --- mp/mp_alloc.c 2004-02-02 10:28:15.000000000 -0800 |
93 | *************** |
94 | *** 25,31 **** |
95 | } HS; |
96 | |
97 | static void __memp_bad_buffer __P((DB_MPOOL_HASH *)); |
98 | - static void __memp_reset_lru __P((DB_ENV *, REGINFO *, MPOOL *)); |
99 | |
100 | /* |
101 | * __memp_alloc -- |
102 | --- 25,30 ---- |
103 | *************** |
104 | *** 50,57 **** |
105 | MPOOL *c_mp; |
106 | MPOOLFILE *bh_mfp; |
107 | size_t freed_space; |
108 | ! u_int32_t buckets, buffers, high_priority, max_na, priority; |
109 | ! int aggressive, ret; |
110 | void *p; |
111 | |
112 | dbenv = dbmp->dbenv; |
113 | --- 49,57 ---- |
114 | MPOOL *c_mp; |
115 | MPOOLFILE *bh_mfp; |
116 | size_t freed_space; |
117 | ! u_int32_t buckets, buffers, high_priority, priority, put_counter; |
118 | ! u_int32_t total_buckets; |
119 | ! int aggressive, giveup, ret; |
120 | void *p; |
121 | |
122 | dbenv = dbmp->dbenv; |
123 | *************** |
124 | *** 59,76 **** |
125 | dbht = R_ADDR(memreg, c_mp->htab); |
126 | hp_end = &dbht[c_mp->htab_buckets]; |
127 | |
128 | ! buckets = buffers = 0; |
129 | ! aggressive = 0; |
130 | |
131 | c_mp->stat.st_alloc++; |
132 | |
133 | /* |
134 | - * Get aggressive if we've tried to flush the number of pages as are |
135 | - * in the system without finding space. |
136 | - */ |
137 | - max_na = 5 * c_mp->htab_buckets; |
138 | - |
139 | - /* |
140 | * If we're allocating a buffer, and the one we're discarding is the |
141 | * same size, we don't want to waste the time to re-integrate it into |
142 | * the shared memory free list. If the DB_MPOOLFILE argument isn't |
143 | --- 59,71 ---- |
144 | dbht = R_ADDR(memreg, c_mp->htab); |
145 | hp_end = &dbht[c_mp->htab_buckets]; |
146 | |
147 | ! buckets = buffers = put_counter = total_buckets = 0; |
148 | ! aggressive = giveup = 0; |
149 | ! hp_tmp = NULL; |
150 | |
151 | c_mp->stat.st_alloc++; |
152 | |
153 | /* |
154 | * If we're allocating a buffer, and the one we're discarding is the |
155 | * same size, we don't want to waste the time to re-integrate it into |
156 | * the shared memory free list. If the DB_MPOOLFILE argument isn't |
157 | *************** |
158 | *** 81,99 **** |
159 | len = (sizeof(BH) - sizeof(u_int8_t)) + mfp->stat.st_pagesize; |
160 | |
161 | R_LOCK(dbenv, memreg); |
162 | - |
163 | - /* |
164 | - * On every buffer allocation we update the buffer generation number |
165 | - * and check for wraparound. |
166 | - */ |
167 | - if (++c_mp->lru_count == UINT32_T_MAX) |
168 | - __memp_reset_lru(dbenv, memreg, c_mp); |
169 | - |
170 | /* |
171 | * Anything newer than 1/10th of the buffer pool is ignored during |
172 | * allocation (unless allocation starts failing). |
173 | */ |
174 | - DB_ASSERT(c_mp->lru_count > c_mp->stat.st_pages / 10); |
175 | high_priority = c_mp->lru_count - c_mp->stat.st_pages / 10; |
176 | |
177 | /* |
178 | --- 76,85 ---- |
179 | *************** |
180 | *** 120,129 **** |
181 | * We're not holding the region locked here, these statistics |
182 | * can't be trusted. |
183 | */ |
184 | ! if (buckets != 0) { |
185 | ! if (buckets > c_mp->stat.st_alloc_max_buckets) |
186 | ! c_mp->stat.st_alloc_max_buckets = buckets; |
187 | ! c_mp->stat.st_alloc_buckets += buckets; |
188 | } |
189 | if (buffers != 0) { |
190 | if (buffers > c_mp->stat.st_alloc_max_pages) |
191 | --- 106,116 ---- |
192 | * We're not holding the region locked here, these statistics |
193 | * can't be trusted. |
194 | */ |
195 | ! total_buckets += buckets; |
196 | ! if (total_buckets != 0) { |
197 | ! if (total_buckets > c_mp->stat.st_alloc_max_buckets) |
198 | ! c_mp->stat.st_alloc_max_buckets = total_buckets; |
199 | ! c_mp->stat.st_alloc_buckets += total_buckets; |
200 | } |
201 | if (buffers != 0) { |
202 | if (buffers > c_mp->stat.st_alloc_max_pages) |
203 | *************** |
204 | *** 131,136 **** |
205 | --- 118,129 ---- |
206 | c_mp->stat.st_alloc_pages += buffers; |
207 | } |
208 | return (0); |
209 | + } else if (giveup || c_mp->stat.st_pages == 0) { |
210 | + R_UNLOCK(dbenv, memreg); |
211 | + |
212 | + __db_err(dbenv, |
213 | + "unable to allocate space from the buffer cache"); |
214 | + return (ret); |
215 | } |
216 | |
217 | /* |
218 | *************** |
219 | *** 138,163 **** |
220 | * we need. Reset our free-space counter. |
221 | */ |
222 | freed_space = 0; |
223 | |
224 | /* |
225 | * Walk the hash buckets and find the next two with potentially useful |
226 | * buffers. Free the buffer with the lowest priority from the buckets' |
227 | * chains. |
228 | */ |
229 | ! for (hp_tmp = NULL;;) { |
230 | /* Check for wrap around. */ |
231 | hp = &dbht[c_mp->last_checked++]; |
232 | if (hp >= hp_end) { |
233 | c_mp->last_checked = 0; |
234 | ! |
235 | ! /* |
236 | ! * If we've gone through all of the hash buckets, try |
237 | ! * an allocation. If the cache is small, the old page |
238 | ! * size is small, and the new page size is large, we |
239 | ! * might have freed enough memory (but not 3 times the |
240 | ! * memory). |
241 | ! */ |
242 | ! goto alloc; |
243 | } |
244 | |
245 | /* |
246 | --- 131,154 ---- |
247 | * we need. Reset our free-space counter. |
248 | */ |
249 | freed_space = 0; |
250 | + total_buckets += buckets; |
251 | + buckets = 0; |
252 | |
253 | /* |
254 | * Walk the hash buckets and find the next two with potentially useful |
255 | * buffers. Free the buffer with the lowest priority from the buckets' |
256 | * chains. |
257 | */ |
258 | ! for (;;) { |
259 | ! /* All pages have been freed, make one last try */ |
260 | ! if (c_mp->stat.st_pages == 0) |
261 | ! goto alloc; |
262 | ! |
263 | /* Check for wrap around. */ |
264 | hp = &dbht[c_mp->last_checked++]; |
265 | if (hp >= hp_end) { |
266 | c_mp->last_checked = 0; |
267 | ! hp = &dbht[c_mp->last_checked++]; |
268 | } |
269 | |
270 | /* |
271 | *************** |
272 | *** 172,210 **** |
273 | /* |
274 | * The failure mode is when there are too many buffers we can't |
275 | * write or there's not enough memory in the system. We don't |
276 | ! * have a metric for deciding if allocation has no possible way |
277 | ! * to succeed, so we don't ever fail, we assume memory will be |
278 | ! * available if we wait long enough. |
279 | * |
280 | ! * Get aggressive if we've tried to flush 5 times the number of |
281 | ! * hash buckets as are in the system -- it's possible we have |
282 | ! * been repeatedly trying to flush the same buffers, although |
283 | ! * it's unlikely. Aggressive means: |
284 | * |
285 | * a: set a flag to attempt to flush high priority buffers as |
286 | * well as other buffers. |
287 | * b: sync the mpool to force out queue extent pages. While we |
288 | * might not have enough space for what we want and flushing |
289 | * is expensive, why not? |
290 | ! * c: sleep for a second -- hopefully someone else will run and |
291 | ! * free up some memory. Try to allocate memory too, in case |
292 | ! * the other thread returns its memory to the region. |
293 | ! * d: look at a buffer in every hash bucket rather than choose |
294 | * the more preferable of two. |
295 | * |
296 | * !!! |
297 | * This test ignores pathological cases like no buffers in the |
298 | * system -- that shouldn't be possible. |
299 | */ |
300 | ! if ((++buckets % max_na) == 0) { |
301 | ! aggressive = 1; |
302 | ! |
303 | R_UNLOCK(dbenv, memreg); |
304 | |
305 | ! (void)__memp_sync_int( |
306 | ! dbenv, NULL, 0, DB_SYNC_ALLOC, NULL); |
307 | ! |
308 | ! (void)__os_sleep(dbenv, 1, 0); |
309 | |
310 | R_LOCK(dbenv, memreg); |
311 | goto alloc; |
312 | --- 163,221 ---- |
313 | /* |
314 | * The failure mode is when there are too many buffers we can't |
315 | * write or there's not enough memory in the system. We don't |
316 | ! * have a way to know that allocation has no way to succeed. |
317 | ! * We fail if there were no pages returned to the cache after |
318 | ! * we've been trying for a relatively long time. |
319 | * |
320 | ! * Get aggressive if we've tried to flush the number of hash |
321 | ! * buckets as are in the system and have not found any more |
322 | ! * space. Aggressive means: |
323 | * |
324 | * a: set a flag to attempt to flush high priority buffers as |
325 | * well as other buffers. |
326 | * b: sync the mpool to force out queue extent pages. While we |
327 | * might not have enough space for what we want and flushing |
328 | * is expensive, why not? |
329 | ! * c: look at a buffer in every hash bucket rather than choose |
330 | * the more preferable of two. |
331 | + * d: start to think about giving up. |
332 | + * |
333 | + * If we get here twice, sleep for a second, hopefully someone |
334 | + * else will run and free up some memory. |
335 | + * |
336 | + * Always try to allocate memory too, in case some other thread |
337 | + * returns its memory to the region. |
338 | * |
339 | * !!! |
340 | * This test ignores pathological cases like no buffers in the |
341 | * system -- that shouldn't be possible. |
342 | */ |
343 | ! if ((++buckets % c_mp->htab_buckets) == 0) { |
344 | ! if (freed_space > 0) |
345 | ! goto alloc; |
346 | R_UNLOCK(dbenv, memreg); |
347 | |
348 | ! switch (++aggressive) { |
349 | ! case 1: |
350 | ! break; |
351 | ! case 2: |
352 | ! put_counter = c_mp->put_counter; |
353 | ! /* FALLTHROUGH */ |
354 | ! case 3: |
355 | ! case 4: |
356 | ! case 5: |
357 | ! case 6: |
358 | ! (void)__memp_sync_int( |
359 | ! dbenv, NULL, 0, DB_SYNC_ALLOC, NULL); |
360 | ! |
361 | ! (void)__os_sleep(dbenv, 1, 0); |
362 | ! break; |
363 | ! default: |
364 | ! aggressive = 1; |
365 | ! if (put_counter == c_mp->put_counter) |
366 | ! giveup = 1; |
367 | ! break; |
368 | ! } |
369 | |
370 | R_LOCK(dbenv, memreg); |
371 | goto alloc; |
372 | *************** |
373 | *** 277,283 **** |
374 | * thread may have acquired this buffer and incremented the ref |
375 | * count after we wrote it, in which case we can't have it. |
376 | * |
377 | ! * If there's a write error, avoid selecting this buffer again |
378 | * by making it the bucket's least-desirable buffer. |
379 | */ |
380 | if (ret != 0 || bhp->ref != 0) { |
381 | --- 288,295 ---- |
382 | * thread may have acquired this buffer and incremented the ref |
383 | * count after we wrote it, in which case we can't have it. |
384 | * |
385 | ! * If there's a write error and we're having problems finding |
386 | ! * something to allocate, avoid selecting this buffer again |
387 | * by making it the bucket's least-desirable buffer. |
388 | */ |
389 | if (ret != 0 || bhp->ref != 0) { |
390 | *************** |
391 | *** 301,306 **** |
392 | --- 313,320 ---- |
393 | |
394 | freed_space += __db_shsizeof(bhp); |
395 | __memp_bhfree(dbmp, hp, bhp, 1); |
396 | + if (aggressive > 1) |
397 | + aggressive = 1; |
398 | |
399 | /* |
400 | * Unlock this hash bucket and re-acquire the region lock. If |
401 | *************** |
402 | *** 362,415 **** |
403 | hp->hash_priority = SH_TAILQ_FIRST(&hp->hash_bucket, __bh)->priority; |
404 | } |
405 | |
406 | - /* |
407 | - * __memp_reset_lru -- |
408 | - * Reset the cache LRU counter. |
409 | - */ |
410 | - static void |
411 | - __memp_reset_lru(dbenv, memreg, c_mp) |
412 | - DB_ENV *dbenv; |
413 | - REGINFO *memreg; |
414 | - MPOOL *c_mp; |
415 | - { |
416 | - BH *bhp; |
417 | - DB_MPOOL_HASH *hp; |
418 | - int bucket; |
419 | - |
420 | - /* |
421 | - * Update the counter so all future allocations will start at the |
422 | - * bottom. |
423 | - */ |
424 | - c_mp->lru_count -= MPOOL_BASE_DECREMENT; |
425 | - |
426 | - /* Release the region lock. */ |
427 | - R_UNLOCK(dbenv, memreg); |
428 | - |
429 | - /* Adjust the priority of every buffer in the system. */ |
430 | - for (hp = R_ADDR(memreg, c_mp->htab), |
431 | - bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) { |
432 | - /* |
433 | - * Skip empty buckets. |
434 | - * |
435 | - * We can check for empty buckets before locking as we |
436 | - * only care if the pointer is zero or non-zero. |
437 | - */ |
438 | - if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL) |
439 | - continue; |
440 | - |
441 | - MUTEX_LOCK(dbenv, &hp->hash_mutex); |
442 | - for (bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh); |
443 | - bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) |
444 | - if (bhp->priority != UINT32_T_MAX && |
445 | - bhp->priority > MPOOL_BASE_DECREMENT) |
446 | - bhp->priority -= MPOOL_BASE_DECREMENT; |
447 | - MUTEX_UNLOCK(dbenv, &hp->hash_mutex); |
448 | - } |
449 | - |
450 | - /* Reacquire the region lock. */ |
451 | - R_LOCK(dbenv, memreg); |
452 | - } |
453 | - |
454 | #ifdef DIAGNOSTIC |
455 | /* |
456 | * __memp_check_order -- |
457 | --- 376,381 ---- |
458 | *** dbreg/dbreg_rec.c.orig 2002-08-17 07:22:52.000000000 -0700 |
459 | --- dbreg/dbreg_rec.c 2003-11-08 10:59:19.000000000 -0800 |
460 | *************** |
461 | *** 174,192 **** |
462 | * Typically, closes should match an open which means |
463 | * that if this is a close, there should be a valid |
464 | * entry in the dbentry table when we get here, |
465 | ! * however there is an exception. If this is an |
466 | * OPENFILES pass, then we may have started from |
467 | * a log file other than the first, and the |
468 | * corresponding open appears in an earlier file. |
469 | ! * We can ignore that case, but all others are errors. |
470 | */ |
471 | dbe = &dblp->dbentry[argp->fileid]; |
472 | if (dbe->dbp == NULL && !dbe->deleted) { |
473 | /* No valid entry here. */ |
474 | ! if ((argp->opcode != LOG_CLOSE && |
475 | ! argp->opcode != LOG_RCLOSE) || |
476 | ! (op != DB_TXN_OPENFILES && |
477 | ! op !=DB_TXN_POPENFILES)) { |
478 | __db_err(dbenv, |
479 | "Improper file close at %lu/%lu", |
480 | (u_long)lsnp->file, |
481 | --- 174,193 ---- |
482 | * Typically, closes should match an open which means |
483 | * that if this is a close, there should be a valid |
484 | * entry in the dbentry table when we get here, |
485 | ! * however there are exceptions. 1. If this is an |
486 | * OPENFILES pass, then we may have started from |
487 | * a log file other than the first, and the |
488 | * corresponding open appears in an earlier file. |
489 | ! * 2. If we are undoing an open on an abort or |
490 | ! * recovery, it's possible that we failed after |
491 | ! * the log record, but before we actually entered |
492 | ! * a handle here. |
493 | */ |
494 | dbe = &dblp->dbentry[argp->fileid]; |
495 | if (dbe->dbp == NULL && !dbe->deleted) { |
496 | /* No valid entry here. */ |
497 | ! if (DB_REDO(op) || |
498 | ! argp->opcode == LOG_CHECKPOINT) { |
499 | __db_err(dbenv, |
500 | "Improper file close at %lu/%lu", |
501 | (u_long)lsnp->file, |
502 | *** env/env_recover.c.orig.1 2002-08-22 14:52:51.000000000 -0700 |
503 | --- env/env_recover.c 2003-11-15 08:20:59.000000000 -0800 |
504 | *************** |
505 | *** 232,243 **** |
506 | * we'll still need to do a vtruncate based on information we haven't |
507 | * yet collected. |
508 | */ |
509 | ! if (ret == DB_NOTFOUND) { |
510 | ret = 0; |
511 | ! if (max_lsn == NULL) |
512 | ! goto done; |
513 | ! } |
514 | ! if (ret != 0) |
515 | goto err; |
516 | |
517 | hi_txn = txnid; |
518 | --- 232,240 ---- |
519 | * we'll still need to do a vtruncate based on information we haven't |
520 | * yet collected. |
521 | */ |
522 | ! if (ret == DB_NOTFOUND) |
523 | ret = 0; |
524 | ! else if (ret != 0) |
525 | goto err; |
526 | |
527 | hi_txn = txnid; |
528 | *************** |
529 | *** 331,337 **** |
530 | |
531 | /* Find a low txnid. */ |
532 | ret = 0; |
533 | ! do { |
534 | /* txnid is after rectype, which is a u_int32. */ |
535 | memcpy(&txnid, |
536 | (u_int8_t *)data.data + sizeof(u_int32_t), sizeof(txnid)); |
537 | --- 328,334 ---- |
538 | |
539 | /* Find a low txnid. */ |
540 | ret = 0; |
541 | ! if (hi_txn != 0) do { |
542 | /* txnid is after rectype, which is a u_int32. */ |
543 | memcpy(&txnid, |
544 | (u_int8_t *)data.data + sizeof(u_int32_t), sizeof(txnid)); |
545 | *************** |
546 | *** 344,354 **** |
547 | * There are no transactions and we're not recovering to an LSN (see |
548 | * above), so there is nothing to do. |
549 | */ |
550 | ! if (ret == DB_NOTFOUND) { |
551 | ret = 0; |
552 | - if (max_lsn == NULL) |
553 | - goto done; |
554 | - } |
555 | |
556 | /* Reset to the first lsn. */ |
557 | if (ret != 0 || (ret = logc->get(logc, &first_lsn, &data, DB_SET)) != 0) |
558 | --- 341,348 ---- |
559 | * There are no transactions and we're not recovering to an LSN (see |
560 | * above), so there is nothing to do. |
561 | */ |
562 | ! if (ret == DB_NOTFOUND) |
563 | ret = 0; |
564 | |
565 | /* Reset to the first lsn. */ |
566 | if (ret != 0 || (ret = logc->get(logc, &first_lsn, &data, DB_SET)) != 0) |
567 | *************** |
568 | *** 367,372 **** |
569 | --- 361,370 ---- |
570 | txninfo, &data, &first_lsn, &last_lsn, nfiles, 1)) != 0) |
571 | goto err; |
572 | |
573 | + /* If there were no transactions, then we can bail out early. */ |
574 | + if (hi_txn == 0 && max_lsn == NULL) |
575 | + goto done; |
576 | + |
577 | /* |
578 | * Pass #2. |
579 | * |
580 | *************** |
581 | *** 483,488 **** |
582 | --- 481,487 ---- |
583 | if ((ret = __dbreg_close_files(dbenv)) != 0) |
584 | goto err; |
585 | |
586 | + done: |
587 | if (max_lsn != NULL) { |
588 | region->last_ckp = ((DB_TXNHEAD *)txninfo)->ckplsn; |
589 | |
590 | *************** |
591 | *** 538,544 **** |
592 | __db_err(dbenv, "Recovery complete at %.24s", ctime(&now)); |
593 | __db_err(dbenv, "%s %lx %s [%lu][%lu]", |
594 | "Maximum transaction ID", |
595 | ! ((DB_TXNHEAD *)txninfo)->maxid, |
596 | "Recovery checkpoint", |
597 | (u_long)region->last_ckp.file, |
598 | (u_long)region->last_ckp.offset); |
599 | --- 537,544 ---- |
600 | __db_err(dbenv, "Recovery complete at %.24s", ctime(&now)); |
601 | __db_err(dbenv, "%s %lx %s [%lu][%lu]", |
602 | "Maximum transaction ID", |
603 | ! txninfo == NULL ? TXN_MINIMUM : |
604 | ! ((DB_TXNHEAD *)txninfo)->maxid, |
605 | "Recovery checkpoint", |
606 | (u_long)region->last_ckp.file, |
607 | (u_long)region->last_ckp.offset); |
608 | *************** |
609 | *** 550,556 **** |
610 | (u_long)lsn.file, (u_long)lsn.offset, pass); |
611 | } |
612 | |
613 | - done: |
614 | err: if (lockid != DB_LOCK_INVALIDID) { |
615 | if ((t_ret = __rep_unlockpages(dbenv, lockid)) != 0 && ret == 0) |
616 | ret = t_ret; |
617 | --- 550,555 ---- |