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__trickle_8c-source.html,v 1.1 2008年06月08日 10:20:54 sebdiaz Exp $"; 00011 #endif /* not lint */ 00012 00013 #ifndef NO_SYSTEM_INCLUDES 00014 #include <sys/types.h> 00015 00016 #include <errno.h> 00017 #include <stdlib.h> 00018 #endif 00019 00020 #ifdef HAVE_RPC 00021 #include "db_server.h" 00022 #endif 00023 00024 #include "db_int.h" 00025 #include "db_shash.h" 00026 #include "mp.h" 00027 00028 #ifdef HAVE_RPC 00029 #include "gen_client_ext.h" 00030 #include "rpc_client_ext.h" 00031 #endif 00032 00033 static int __memp_trick __P((DB_ENV *, int, int, int *)); 00034 00035 /* 00036 * CDB_memp_trickle -- 00037 * Keep a specified percentage of the buffers clean. 00038 */ 00039 int 00040 CDB_memp_trickle(dbenv, pct, nwrotep) 00041 DB_ENV *dbenv; 00042 int pct, *nwrotep; 00043 { 00044 DB_MPOOL *dbmp; 00045 MPOOL *mp; 00046 u_int32_t i; 00047 int ret; 00048 00049 #ifdef HAVE_RPC 00050 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT)) 00051 return (__dbcl_memp_trickle(dbenv, pct, nwrotep)); 00052 #endif 00053 00054 PANIC_CHECK(dbenv); 00055 ENV_REQUIRES_CONFIG(dbenv, dbenv->mp_handle, DB_INIT_MPOOL); 00056 00057 dbmp = dbenv->mp_handle; 00058 mp = dbmp->reginfo[0].primary; 00059 00060 if (nwrotep != NULL) 00061 *nwrotep = 0; 00062 00063 if (pct < 1 || pct > 100) 00064 return (EINVAL); 00065 00066 R_LOCK(dbenv, dbmp->reginfo); 00067 00068 /* Loop through the caches... */ 00069 for (ret = 0, i = 0; i < mp->nreg; ++i) 00070 if ((ret = __memp_trick(dbenv, i, pct, nwrotep)) != 0) 00071 break; 00072 00073 R_UNLOCK(dbenv, dbmp->reginfo); 00074 return (ret); 00075 } 00076 00077 /* 00078 * __memp_trick -- 00079 * Trickle a single cache. 00080 */ 00081 static int 00082 __memp_trick(dbenv, ncache, pct, nwrotep) 00083 DB_ENV *dbenv; 00084 int ncache, pct, *nwrotep; 00085 { 00086 BH *bhp; 00087 DB_MPOOL *dbmp; 00088 MPOOL *c_mp; 00089 MPOOLFILE *mfp; 00090 db_pgno_t pgno; 00091 u_long total; 00092 int ret, wrote; 00093 00094 dbmp = dbenv->mp_handle; 00095 c_mp = dbmp->reginfo[ncache].primary; 00096 00097 /* 00098 * If there are sufficient clean buffers, or no buffers or no dirty 00099 * buffers, we're done. 00100 * 00101 * XXX 00102 * Using st_page_clean and st_page_dirty is our only choice at the 00103 * moment, but it's not as correct as we might like in the presence 00104 * of pools with more than one buffer size, as a free 512-byte buffer 00105 * isn't the same as a free 8K buffer. 00106 */ 00107 loop: total = c_mp->stat.st_page_clean + c_mp->stat.st_page_dirty; 00108 if (total == 0 || c_mp->stat.st_page_dirty == 0 || 00109 (c_mp->stat.st_page_clean * 100) / total >= (u_long)pct) 00110 return (0); 00111 00112 /* Loop until we write a buffer. */ 00113 for (bhp = SH_TAILQ_FIRST(&c_mp->bhq, __bh); 00114 bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, q, __bh)) { 00115 if (bhp->ref != 0 || 00116 !F_ISSET(bhp, BH_DIRTY) || F_ISSET(bhp, BH_LOCKED)) 00117 continue; 00118 00119 mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset); 00120 00121 /* 00122 * We can't write to temporary files -- see the comment in 00123 * mp_bh.c:CDB___memp_bhwrite(). 00124 */ 00125 if (F_ISSET(mfp, MP_TEMP)) 00126 continue; 00127 00128 pgno = bhp->pgno; 00129 if ((ret = CDB___memp_bhwrite(dbmp, mfp, bhp, NULL, &wrote)) != 0) 00130 return (ret); 00131 00132 /* 00133 * Any process syncing the shared memory buffer pool had better 00134 * be able to write to any underlying file. Be understanding, 00135 * but firm, on this point. 00136 */ 00137 if (!wrote) { 00138 CDB___db_err(dbenv, "%s: unable to flush page: %lu", 00139 CDB___memp_fns(dbmp, mfp), (u_long)pgno); 00140 return (EPERM); 00141 } 00142 00143 ++c_mp->stat.st_page_trickle; 00144 if (nwrotep != NULL) 00145 ++*nwrotep; 00146 goto loop; 00147 } 00148 00149 return (0); 00150 }