]> git.pld-linux.org Git - packages/db4.1.git/blob - patch.4.1.25.2
- added 4.1.25.[23] patches
[packages/db4.1.git] / patch.4.1.25.2
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 ----
This page took 0.07591 seconds and 3 git commands to generate.