]> git.ipfire.org Git - thirdparty/squid.git/blob - src/mem.cc
2.1 branch merge
[thirdparty/squid.git] / src / mem.cc
1
2 /*
3 * $Id: mem.cc,v 1.35 1998/11/12 06:28:14 wessels Exp $
4 *
5 * DEBUG: section 13 High Level Memory Pool Management
6 * AUTHOR: Harvest Derived
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36 #include "squid.h"
37
38 /* module globals */
39
40 static MemPool *MemPools[MEM_MAX];
41
42 /* string pools */
43 #define mem_str_pool_count 3
44 static const struct {
45 const char *name;
46 size_t obj_size;
47 } StrPoolsAttrs[mem_str_pool_count] = {
48
49 {
50 "Short Strings", 36,
51 }, /* to fit rfc1123 and similar */
52 {
53 "Medium Strings", 128,
54 }, /* to fit most urls */
55 {
56 "Long Strings", 512
57 } /* other */
58 };
59 static struct {
60 MemPool *pool;
61 } StrPools[mem_str_pool_count];
62 static MemMeter StrCountMeter;
63 static MemMeter StrVolumeMeter;
64
65
66 /* local routines */
67
68 /*
69 * we have a limit on _total_ amount of idle memory so we ignore
70 * max_pages for now
71 */
72 static void
73 memDataInit(mem_type type, const char *name, size_t size, int max_pages_notused)
74 {
75 assert(name && size);
76 MemPools[type] = memPoolCreate(name, size);
77 }
78
79 static void
80 memStringStats(StoreEntry * sentry)
81 {
82 const char *pfmt = "%-20s\t %d\t %d\n";
83 int i;
84 int pooled_count = 0;
85 size_t pooled_volume = 0;
86 /* heading */
87 storeAppendPrintf(sentry,
88 "String Pool\t Impact\t\t\n"
89 " \t (%%strings)\t (%%volume)\n");
90 /* table body */
91 for (i = 0; i < mem_str_pool_count; i++) {
92 const MemPool *pool = StrPools[i].pool;
93 const int plevel = pool->meter.inuse.level;
94 storeAppendPrintf(sentry, pfmt,
95 pool->label,
96 xpercentInt(plevel, StrCountMeter.level),
97 xpercentInt(plevel * pool->obj_size, StrVolumeMeter.level));
98 pooled_count += plevel;
99 pooled_volume += plevel * pool->obj_size;
100 }
101 /* malloc strings */
102 storeAppendPrintf(sentry, pfmt,
103 "Other Strings",
104 xpercentInt(StrCountMeter.level - pooled_count, StrCountMeter.level),
105 xpercentInt(StrVolumeMeter.level - pooled_volume, StrVolumeMeter.level));
106 }
107
108 static void
109 memStats(StoreEntry * sentry)
110 {
111 storeBuffer(sentry);
112 memReport(sentry);
113 memStringStats(sentry);
114 storeBufferFlush(sentry);
115 }
116
117
118 /*
119 * public routines
120 */
121
122
123 /* find appropriate pool and use it (pools always init buffer with 0s) */
124 void *
125 memAllocate(mem_type type)
126 {
127 return memPoolAlloc(MemPools[type]);
128 }
129
130 /* find appropriate pool and use it */
131 void
132 memFree(mem_type type, void *p)
133 {
134 memPoolFree(MemPools[type], p);
135 }
136
137 /* allocate a variable size buffer using best-fit pool */
138 void *
139 memAllocBuf(size_t net_size, size_t * gross_size)
140 {
141 int i;
142 MemPool *pool = NULL;
143 assert(gross_size);
144 for (i = 0; i < mem_str_pool_count; i++) {
145 if (net_size <= StrPoolsAttrs[i].obj_size) {
146 pool = StrPools[i].pool;
147 break;
148 }
149 }
150 *gross_size = pool ? pool->obj_size : net_size;
151 assert(*gross_size >= net_size);
152 memMeterInc(StrCountMeter);
153 memMeterAdd(StrVolumeMeter, *gross_size);
154 return pool ? memPoolAlloc(pool) : xcalloc(1, net_size);
155 }
156
157 /* free buffer allocated with memAllocBuf() */
158 void
159 memFreeBuf(size_t size, void *buf)
160 {
161 int i;
162 MemPool *pool = NULL;
163 assert(size && buf);
164 for (i = 0; i < mem_str_pool_count; i++) {
165 if (size <= StrPoolsAttrs[i].obj_size) {
166 assert(size == StrPoolsAttrs[i].obj_size);
167 pool = StrPools[i].pool;
168 break;
169 }
170 }
171 memMeterDec(StrCountMeter);
172 memMeterDel(StrVolumeMeter, size);
173 pool ? memPoolFree(pool, buf) : xfree(buf);
174 }
175
176 void
177 memInit(void)
178 {
179 int i;
180 mem_type t;
181 memInitModule();
182 /* set all pointers to null */
183 memset(MemPools, '\0', sizeof(MemPools));
184 /*
185 * it does not hurt much to have a lot of pools since sizeof(MemPool) is
186 * small; someday we will figure out what to do with all the entries here
187 * that are never used or used only once; perhaps we should simply use
188 * malloc() for those? @?@
189 */
190 memDataInit(MEM_2K_BUF, "2K Buffer", 2048, 10);
191 memDataInit(MEM_4K_BUF, "4K Buffer", 4096, 10);
192 memDataInit(MEM_8K_BUF, "8K Buffer", 8192, 10);
193 memDataInit(MEM_CLIENT_SOCK_BUF, "Client Socket Buffer", CLIENT_SOCK_SZ, 0);
194 memDataInit(MEM_ACCESSLOGENTRY, "AccessLogEntry",
195 sizeof(AccessLogEntry), 10);
196 memDataInit(MEM_ACL, "acl", sizeof(acl), 0);
197 memDataInit(MEM_ACLCHECK_T, "aclCheck_t", sizeof(aclCheck_t), 0);
198 memDataInit(MEM_ACL_ACCESS, "acl_access", sizeof(acl_access), 0);
199 memDataInit(MEM_ACL_DENY_INFO_LIST, "acl_deny_info_list",
200 sizeof(acl_deny_info_list), 0);
201 memDataInit(MEM_ACL_IP_DATA, "acl_ip_data", sizeof(acl_ip_data), 0);
202 memDataInit(MEM_ACL_LIST, "acl_list", sizeof(acl_list), 0);
203 memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0);
204 memDataInit(MEM_ACL_TIME_DATA, "acl_time_data", sizeof(acl_time_data), 0);
205 memDataInit(MEM_ACL_PROXY_AUTH_USER, "acl_proxy_auth_user",
206 sizeof(acl_proxy_auth_user), 0);
207 memDataInit(MEM_AIO_RESULT_T, "aio_result_t", sizeof(aio_result_t), 0);
208 memDataInit(MEM_CACHEMGR_PASSWD, "cachemgr_passwd",
209 sizeof(cachemgr_passwd), 0);
210 #if USE_CACHE_DIGESTS
211 memDataInit(MEM_CACHE_DIGEST, "CacheDigest", sizeof(CacheDigest), 0);
212 #endif
213 memDataInit(MEM_CLIENTHTTPREQUEST, "clientHttpRequest",
214 sizeof(clientHttpRequest), 0);
215 memDataInit(MEM_CLOSE_HANDLER, "close_handler", sizeof(close_handler), 0);
216 memDataInit(MEM_COMMWRITESTATEDATA, "CommWriteStateData",
217 sizeof(CommWriteStateData), 0);
218 memDataInit(MEM_CONNSTATEDATA, "ConnStateData", sizeof(ConnStateData), 0);
219 memDataInit(MEM_DISK_BUF, "Disk I/O Buffer", DISK_PAGE_SIZE, 200);
220 memDataInit(MEM_DLINK_LIST, "dlink_list", sizeof(dlink_list), 10);
221 memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10);
222 memDataInit(MEM_DNSSERVER_T, "dnsserver_t", sizeof(dnsserver_t), 0);
223 memDataInit(MEM_DNSSTATDATA, "dnsStatData", sizeof(dnsStatData), 0);
224 memDataInit(MEM_DOMAIN_PING, "domain_ping", sizeof(domain_ping), 0);
225 memDataInit(MEM_DOMAIN_TYPE, "domain_type", sizeof(domain_type), 0);
226 memDataInit(MEM_DREAD_CTRL, "dread_ctrl", sizeof(dread_ctrl), 0);
227 memDataInit(MEM_DWRITE_Q, "dwrite_q", sizeof(dwrite_q), 0);
228 memDataInit(MEM_ERRORSTATE, "ErrorState", sizeof(ErrorState), 0);
229 memDataInit(MEM_FILEMAP, "fileMap", sizeof(fileMap), 0);
230 memDataInit(MEM_FQDNCACHE_ENTRY, "fqdncache_entry",
231 sizeof(fqdncache_entry), 0);
232 memDataInit(MEM_FQDNCACHE_PENDING, "fqdn_pending",
233 sizeof(fqdn_pending), 0);
234 memDataInit(MEM_FWD_STATE, "FwdState", sizeof(FwdState), 0);
235 memDataInit(MEM_FWD_SERVER, "FwdServer", sizeof(FwdServer), 0);
236 memDataInit(MEM_HASH_LINK, "hash_link", sizeof(hash_link), 0);
237 memDataInit(MEM_HASH_TABLE, "hash_table", sizeof(hash_table), 0);
238 memDataInit(MEM_HIERARCHYLOGENTRY, "HierarchyLogEntry",
239 sizeof(HierarchyLogEntry), 0);
240 memDataInit(MEM_HTTP_STATE_DATA, "HttpStateData", sizeof(HttpStateData), 0);
241 memDataInit(MEM_HTTP_REPLY, "HttpReply", sizeof(HttpReply), 0);
242 memDataInit(MEM_HTTP_HDR_ENTRY, "HttpHeaderEntry", sizeof(HttpHeaderEntry), 0);
243 memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0);
244 memDataInit(MEM_HTTP_HDR_RANGE_SPEC, "HttpHdrRangeSpec", sizeof(HttpHdrRangeSpec), 0);
245 memDataInit(MEM_HTTP_HDR_RANGE, "HttpHdrRange", sizeof(HttpHdrRange), 0);
246 memDataInit(MEM_HTTP_HDR_CONTENT_RANGE, "HttpHdrContRange", sizeof(HttpHdrContRange), 0);
247 memDataInit(MEM_ICPUDPDATA, "icpUdpData", sizeof(icpUdpData), 0);
248 memDataInit(MEM_ICP_COMMON_T, "icp_common_t", sizeof(icp_common_t), 0);
249 memDataInit(MEM_ICP_PING_DATA, "ping_data", sizeof(ping_data), 0);
250 memDataInit(MEM_INTLIST, "intlist", sizeof(intlist), 0);
251 memDataInit(MEM_IOSTATS, "iostats", sizeof(iostats), 0);
252 memDataInit(MEM_IPCACHE_PENDING, "ip_pending", sizeof(ip_pending), 0);
253 memDataInit(MEM_IPCACHE_ENTRY, "ipcache_entry", sizeof(ipcache_entry), 0);
254 memDataInit(MEM_MEMOBJECT, "MemObject", sizeof(MemObject),
255 Squid_MaxFD >> 3);
256 memDataInit(MEM_MEM_NODE, "mem_node", sizeof(mem_node), 0);
257 memDataInit(MEM_NETDBENTRY, "netdbEntry", sizeof(netdbEntry), 0);
258 memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0);
259 memDataInit(MEM_NET_DB_PEER, "net_db_peer", sizeof(net_db_peer), 0);
260 #if USE_CACHE_DIGESTS
261 memDataInit(MEM_DIGEST_FETCH_STATE, "DigestFetchState", sizeof(DigestFetchState), 0);
262 #endif
263 memDataInit(MEM_PEER, "peer", sizeof(peer), 0);
264 memDataInit(MEM_PINGERECHODATA, "pingerEchoData",
265 sizeof(pingerEchoData), 0);
266 memDataInit(MEM_PINGERREPLYDATA, "pingerReplyData",
267 sizeof(pingerReplyData), 0);
268 memDataInit(MEM_PS_STATE, "ps_state", sizeof(ps_state), 0);
269 memDataInit(MEM_REFRESH_T, "refresh_t", sizeof(refresh_t), 0);
270 memDataInit(MEM_RELIST, "relist", sizeof(relist), 0);
271 memDataInit(MEM_REQUEST_T, "request_t", sizeof(request_t),
272 Squid_MaxFD >> 3);
273 memDataInit(MEM_SQUIDCONFIG, "SquidConfig", sizeof(SquidConfig), 0);
274 memDataInit(MEM_SQUIDCONFIG2, "SquidConfig2", sizeof(SquidConfig2), 0);
275 memDataInit(MEM_STATCOUNTERS, "StatCounters", sizeof(StatCounters), 0);
276 memDataInit(MEM_STMEM_BUF, "Store Mem Buffer", SM_PAGE_SIZE,
277 Config.Mem.maxSize / SM_PAGE_SIZE);
278 memDataInit(MEM_STOREENTRY, "StoreEntry", sizeof(StoreEntry), 0);
279 memDataInit(MEM_STORE_CLIENT, "store_client", sizeof(store_client), 0);
280 memDataInit(MEM_SWAPDIR, "SwapDir", sizeof(SwapDir), 0);
281 memDataInit(MEM_USHORTLIST, "ushort_list", sizeof(ushortlist), 0);
282 memDataInit(MEM_WORDLIST, "wordlist", sizeof(wordlist), 0);
283 memDataInit(MEM_CLIENT_INFO, "ClientInfo", sizeof(ClientInfo), 0);
284 memDataInit(MEM_MD5_DIGEST, "MD5 digest", MD5_DIGEST_CHARS, 0);
285 memDataInit(MEM_HELPER, "helper", sizeof(helper), 0);
286 memDataInit(MEM_HELPER_REQUEST, "helper_request",
287 sizeof(helper_request), 0);
288 memDataInit(MEM_HELPER_SERVER, "helper_server",
289 sizeof(helper_server), 0);
290 /* test that all entries are initialized */
291 for (t = MEM_NONE, t++; t < MEM_MAX; t++) {
292 if (MEM_DONTFREE == t)
293 continue;
294 /*
295 * If you hit this assertion, then you forgot to add a
296 * memDataInit() line for type 't' above.
297 */
298 assert(MemPools[t]);
299 }
300 /* init string pools */
301 for (i = 0; i < mem_str_pool_count; i++) {
302 StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size);
303 }
304 cachemgrRegister("mem",
305 "Memory Utilization",
306 memStats, 0, 1);
307 }
308
309 void
310 memClean()
311 {
312 memCleanModule();
313 }
314
315 int
316 memInUse(mem_type type)
317 {
318 return memPoolInUseCount(MemPools[type]);
319 }
320
321 /* ick */
322
323 void
324 memFree2K(void *p)
325 {
326 memFree(MEM_2K_BUF, p);
327 }
328
329 void
330 memFree4K(void *p)
331 {
332 memFree(MEM_4K_BUF, p);
333 }
334
335 void
336 memFree8K(void *p)
337 {
338 memFree(MEM_8K_BUF, p);
339 }
340
341 void
342 memFreeDISK(void *p)
343 {
344 memFree(MEM_DISK_BUF, p);
345 }