diff -cpr pgsql-orig/src/backend/postmaster/bgwriter.c pgsql/src/backend/postmaster/bgwriter.c *** pgsql-orig/src/backend/postmaster/bgwriter.c 2006-01-10 22:03:59.000000000 +0900 --- pgsql/src/backend/postmaster/bgwriter.c 2006-01-10 22:19:50.000000000 +0900 *************** static void bg_quickdie(SIGNAL_ARGS); *** 150,155 **** --- 150,159 ---- static void BgSigHupHandler(SIGNAL_ARGS); static void ReqCheckpointHandler(SIGNAL_ARGS); static void ReqShutdownHandler(SIGNAL_ARGS); + static int EliminateDupRequests(BgWriterRequest *requests, int num); + static int BgWriterRequestCompare(const void *v1, const void *v2); + static size_t unique(void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *)); /* *************** RequestCheckpoint(bool waitforit, bool w *** 628,639 **** * * If we are unable to pass over the request (at present, this can happen * if the shared memory queue is full), we return false. That forces ! * the backend to do its own fsync. We hope that will be even more seldom. * * Note: we presently make no attempt to eliminate duplicate requests ! * in the requests[] queue. The bgwriter will have to eliminate dups ! * internally anyway, so we may as well avoid holding the lock longer ! * than we have to here. */ bool ForwardFsyncRequest(RelFileNode rnode, BlockNumber segno) --- 632,644 ---- * * If we are unable to pass over the request (at present, this can happen * if the shared memory queue is full), we return false. That forces ! * the backend to do its own fsync. We hope that will be even more seldom, ! * but in such cases, we will eliminate duplicate requests. * * Note: we presently make no attempt to eliminate duplicate requests ! * in the requests[] queue as long as it is not full. The bgwriter will ! * have to eliminate dups internally anyway, so we may as well avoid ! * holding the lock longer than we have to here. */ bool ForwardFsyncRequest(RelFileNode rnode, BlockNumber segno) *************** ForwardFsyncRequest(RelFileNode rnode, B *** 645,656 **** Assert(BgWriterShmem != NULL); LWLockAcquire(BgWriterCommLock, LW_EXCLUSIVE); ! if (BgWriterShmem->bgwriter_pid == 0 || ! BgWriterShmem->num_requests >= BgWriterShmem->max_requests) { LWLockRelease(BgWriterCommLock); return false; } request = &BgWriterShmem->requests[BgWriterShmem->num_requests++]; request->rnode = rnode; request->segno = segno; --- 650,670 ---- Assert(BgWriterShmem != NULL); LWLockAcquire(BgWriterCommLock, LW_EXCLUSIVE); ! if (BgWriterShmem->bgwriter_pid == 0) { LWLockRelease(BgWriterCommLock); return false; } + if (BgWriterShmem->num_requests >= BgWriterShmem->max_requests) + { + BgWriterShmem->num_requests = EliminateDupRequests( + BgWriterShmem->requests, BgWriterShmem->num_requests); + if (BgWriterShmem->num_requests >= BgWriterShmem->max_requests) + { + LWLockRelease(BgWriterCommLock); + return false; + } + } request = &BgWriterShmem->requests[BgWriterShmem->num_requests++]; request->rnode = rnode; request->segno = segno; *************** AbsorbFsyncRequests(void) *** 710,712 **** --- 724,778 ---- END_CRIT_SECTION(); } + + static int + BgWriterRequestCompare(const void *v1, const void *v2) + { + const BgWriterRequest *lhs = (const BgWriterRequest *)v1; + const BgWriterRequest *rhs = (const BgWriterRequest *)v2; + + if (lhs->rnode.spcNode < rhs->rnode.spcNode) return -1; + if (lhs->rnode.spcNode > rhs->rnode.spcNode) return 1; + if (lhs->rnode.dbNode < rhs->rnode.dbNode) return -1; + if (lhs->rnode.dbNode > rhs->rnode.dbNode) return 1; + if (lhs->rnode.relNode < rhs->rnode.relNode) return -1; + if (lhs->rnode.relNode > rhs->rnode.relNode) return 1; + if (lhs->segno < rhs->segno) return -1; + if (lhs->segno > rhs->segno) return 1; + return 0; + } + + static size_t + unique(void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *)) + { + char *start = (char *) base; + char *stop = (char *) base + (size * (nmemb - 1)); + char *dst = start; + char *p = start; + + while (p <= stop) + { + size_t elements; + char *q = p; + + while (q < stop && compar(q, q + size) != 0) + q = q + size; + + elements = ((q - p) / size) + 1; + memmove(dst, p, size * elements); + dst = dst + size * elements; + + p = q + size; + while (p <= stop && compar(q, p) == 0) + p = p + size; + } + return (dst - start) / size; + } + + static int + EliminateDupRequests(BgWriterRequest *requests, int num) + { + qsort(requests, num, sizeof(BgWriterRequest), BgWriterRequestCompare); + return unique(requests, num, sizeof(BgWriterRequest), BgWriterRequestCompare); + }