db

mp_alloc.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  * Sleepycat Software. All rights reserved.
00006  */
00007 #include "config.h"
00008 
00009 #ifndef lint
00010 static const char revid[] = "$Id: mp__alloc_8c-source.html,v 1.1 2008年06月08日 10:20:39 sebdiaz Exp $";
00011 #endif /* not lint */
00012 
00013 #ifndef NO_SYSTEM_INCLUDES
00014 #include <sys/types.h>
00015 #endif
00016 
00017 #include "db_int.h"
00018 #include "db_shash.h"
00019 #include "mp.h"
00020 
00021 /*
00022  * CDB___memp_alloc --
00023  * Allocate some space from a cache region.
00024  *
00025  * PUBLIC: int CDB___memp_alloc __P((DB_MPOOL *,
00026  * PUBLIC: REGINFO *, MPOOLFILE *, size_t, roff_t *, void *));
00027  */
00028 int
00029 CDB___memp_alloc(dbmp, memreg, mfp, len, offsetp, retp)
00030 DB_MPOOL *dbmp;
00031 REGINFO *memreg;
00032 MPOOLFILE *mfp;
00033 size_t len;
00034 roff_t *offsetp;
00035 void *retp;
00036 {
00037 BH *bhp, *nbhp;
00038 MPOOL *c_mp;
00039 MPOOLFILE *bh_mfp;
00040 size_t total;
00041 int nomore, restart, ret, wrote;
00042 void *p;
00043 
00044 c_mp = memreg->primary;
00045 
00046 /*
00047  * If we're allocating a buffer, and the one we're discarding is the
00048  * same size, we don't want to waste the time to re-integrate it into
00049  * the shared memory free list. If the DB_MPOOLFILE argument isn't
00050  * NULL, we'll compare the underlying page sizes of the two buffers
00051  * before free-ing and re-allocating buffers.
00052  */
00053 if (mfp != NULL)
00054 len = (sizeof(BH) - sizeof(u_int8_t)) + mfp->stat.st_pagesize;
00055 
00056 nomore = 0;
00057 alloc: if ((ret = CDB___db_shalloc(memreg->addr, len, MUTEX_ALIGN, &p)) == 0) {
00058 if (offsetp != NULL)
00059 *offsetp = R_OFFSET(memreg, p);
00060 *(void **)retp = p;
00061 return (0);
00062 }
00063 if (nomore) {
00064 CDB___db_err(dbmp->dbenv,
00065 "Unable to allocate %lu bytes from mpool shared region: %s\n",
00066 (u_long)len, CDB_db_strerror(ret));
00067 return (ret);
00068 }
00069 
00070 retry: /* Find a buffer we can flush; pure LRU. */
00071 restart = total = 0;
00072 for (bhp =
00073 SH_TAILQ_FIRST(&c_mp->bhq, __bh); bhp != NULL; bhp = nbhp) {
00074 nbhp = SH_TAILQ_NEXT(bhp, q, __bh);
00075 
00076 /* Ignore pinned or locked (I/O in progress) buffers. */
00077 if (bhp->ref != 0 || F_ISSET(bhp, BH_LOCKED))
00078 continue;
00079 
00080 /* Find the associated MPOOLFILE. */
00081 bh_mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset);
00082 
00083 /* Write the page if it's dirty. */
00084 if (F_ISSET(bhp, BH_DIRTY)) {
00085 ++bhp->ref;
00086 if ((ret = CDB___memp_bhwrite(dbmp,
00087 bh_mfp, bhp, &restart, &wrote)) != 0)
00088 return (ret);
00089 --bhp->ref;
00090 
00091 /*
00092  * Another process may have acquired this buffer and
00093  * incremented the ref count after we wrote it.
00094  */
00095 if (bhp->ref != 0)
00096 goto retry;
00097 
00098 /*
00099  * If we wrote the page, continue and free the buffer.
00100  * We don't have to rewalk the list to acquire the
00101  * buffer because it was never available for any other
00102  * process to modify it.
00103  *
00104  * If we didn't write the page, but we discarded and
00105  * reacquired the region lock, restart the list walk.
00106  *
00107  * If we neither wrote the buffer nor discarded the
00108  * region lock, continue down the buffer list.
00109  */
00110 if (wrote)
00111 ++c_mp->stat.st_rw_evict;
00112 else {
00113 if (restart)
00114 goto retry;
00115 continue;
00116 }
00117 } else
00118 ++c_mp->stat.st_ro_evict;
00119 
00120 /*
00121  * Check to see if the buffer is the size we're looking for.
00122  * If it is, simply reuse it.
00123  */
00124 if (mfp != NULL &&
00125 mfp->stat.st_pagesize == bh_mfp->stat.st_pagesize) {
00126 CDB___memp_bhfree(dbmp, bhp, 0);
00127 
00128 if (offsetp != NULL)
00129 *offsetp = R_OFFSET(memreg, bhp);
00130 *(void **)retp = bhp;
00131 return (0);
00132 }
00133 
00134 /* Note how much space we've freed, and free the buffer. */
00135 total += CDB___db_shsizeof(bhp);
00136 CDB___memp_bhfree(dbmp, bhp, 1);
00137 
00138 /*
00139  * Retry as soon as we've freed up sufficient space. If we
00140  * have to coalesce of memory to satisfy the request, don't
00141  * try until it's likely (possible?) that we'll succeed.
00142  */
00143 if (total >= 3 * len)
00144 goto alloc;
00145 
00146 /* Restart the walk if we discarded the region lock. */
00147 if (restart)
00148 goto retry;
00149 }
00150 nomore = 1;
00151 goto alloc;
00152 }

Generated on Sun Jun 8 10:56:38 2008 for GNUmifluz by doxygen 1.5.5

AltStyle によって変換されたページ (->オリジナル) /