]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/stmem.cc
2 * $Id: stmem.cc,v 1.14 1996/07/20 03:16:56 wessels Exp $
4 * DEBUG: section 19 Memory Primitives
5 * AUTHOR: Harvest Derived
7 * SQUID Internet Object Cache http://www.nlanr.net/Squid/
8 * --------------------------------------------------------
10 * Squid is the result of efforts by numerous individuals from the
11 * Internet community. Development is led by Duane Wessels of the
12 * National Laboratory for Applied Network Research and funded by
13 * the National Science Foundation.
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 * Copyright (c) 1994, 1995. All rights reserved.
34 * The Harvest software was developed by the Internet Research Task
35 * Force Research Group on Resource Discovery (IRTF-RD):
37 * Mic Bowman of Transarc Corporation.
38 * Peter Danzig of the University of Southern California.
39 * Darren R. Hardy of the University of Colorado at Boulder.
40 * Udi Manber of the University of Arizona.
41 * Michael F. Schwartz of the University of Colorado at Boulder.
42 * Duane Wessels of the University of Colorado at Boulder.
44 * This copyright notice applies to software in the Harvest
45 * ``src/'' directory only. Users should consult the individual
46 * copyright notices in the ``components/'' subdirectories for
47 * copyright information about other software bundled with the
48 * Harvest source code distribution.
52 * The Harvest software may be used and re-distributed without
53 * charge, provided that the software origin and research team are
54 * cited in any use of the system. Most commonly this is
55 * accomplished by including a link to the Harvest Home Page
56 * (http://harvest.cs.colorado.edu/) from the query page of any
57 * Broker you deploy, as well as in the query result pages. These
58 * links are generated automatically by the standard Broker
59 * software distribution.
61 * The Harvest software is provided ``as is'', without express or
62 * implied warranty, and with no support nor obligation to assist
63 * in its use, correction, modification or enhancement. We assume
64 * no liability with respect to the infringement of copyrights,
65 * trade secrets, or any patents, and are not responsible for
66 * consequential damages. Proper use of the Harvest software is
67 * entirely the responsibility of the user.
71 * Users may make derivative works from the Harvest software, subject
72 * to the following constraints:
74 * - You must include the above copyright notice and these
75 * accompanying paragraphs in all forms of derivative works,
76 * and any documentation and other materials related to such
77 * distribution and use acknowledge that the software was
78 * developed at the above institutions.
80 * - You must notify IRTF-RD regarding your distribution of
81 * the derivative work.
83 * - You must clearly notify users that your are distributing
84 * a modified version and not the original Harvest software.
86 * - Any derivative product is also subject to these copyright
87 * and use restrictions.
89 * Note that the Harvest software is NOT in the public domain. We
90 * retain copyright, as specified above.
92 * HISTORY OF FREE SOFTWARE STATUS
94 * Originally we required sites to license the software in cases
95 * where they were going to build commercial products/services
96 * around Harvest. In June 1995 we changed this policy. We now
97 * allow people to use the core Harvest software (the code found in
98 * the Harvest ``src/'' directory) for free. We made this change
99 * in the interest of encouraging the widest possible deployment of
100 * the technology. The Harvest software is really a reference
101 * implementation of a set of protocols and formats, some of which
102 * we intend to standardize. We encourage commercial
103 * re-implementations of code complying to this set of standards.
108 stmem_stats sm_stats
;
109 stmem_stats disk_stats
;
110 stmem_stats request_pool
;
111 stmem_stats mem_obj_pool
;
113 #define min(x,y) ((x)<(y)? (x) : (y))
116 #define USE_MEMALIGN 0
119 static void *get_free_thing
_PARAMS((stmem_stats
* thing
));
120 static void put_free_thing
_PARAMS((stmem_stats
* thing
, void *p
));
126 mem_node lastp
, p
= mem
->head
;
129 while (p
&& (p
!= mem
->tail
)) {
133 put_free_4k_page(lastp
->data
);
139 put_free_4k_page(p
->data
);
143 memset(mem
, '\0', sizeof(mem_ptr
)); /* nuke in case ref'ed again */
147 void memFreeData(mem
)
150 mem_node lastp
, p
= mem
->head
;
152 while (p
!= mem
->tail
) {
155 put_free_4k_page(lastp
->data
);
160 put_free_4k_page(p
->data
);
164 mem
->head
= mem
->tail
= NULL
; /* detach in case ref'd */
165 mem
->origin_offset
= 0;
168 int memFreeDataUpto(mem
, target_offset
)
172 int current_offset
= mem
->origin_offset
;
173 mem_node lastp
, p
= mem
->head
;
175 while (p
&& ((current_offset
+ p
->len
) <= target_offset
)) {
176 if (p
== mem
->tail
) {
177 /* keep the last one to avoid change to other part of code */
178 mem
->head
= mem
->tail
;
179 mem
->origin_offset
= current_offset
;
180 return current_offset
;
184 current_offset
+= lastp
->len
;
185 put_free_4k_page(lastp
->data
);
191 mem
->origin_offset
= current_offset
;
192 if (current_offset
< target_offset
) {
193 /* there are still some data left. */
194 return current_offset
;
196 if (current_offset
!= target_offset
) {
197 debug(19, 1, "memFreeDataBehind: This shouldn't happen. Some odd condition.\n");
198 debug(19, 1, " Current offset: %d Target offset: %d p: %p\n",
199 current_offset
, target_offset
, p
);
201 return current_offset
;
206 /* Append incoming data. */
207 int memAppend(mem
, data
, len
)
216 debug(19, 6, "memAppend: len %d\n", len
);
218 /* Does the last block still contain empty space?
219 * If so, fill out the block before dropping into the
222 if (mem
->head
&& mem
->tail
&& (mem
->tail
->len
< SM_PAGE_SIZE
)) {
223 avail_len
= SM_PAGE_SIZE
- (mem
->tail
->len
);
224 len_to_copy
= min(avail_len
, len
);
225 xmemcpy((mem
->tail
->data
+ mem
->tail
->len
), data
, len_to_copy
);
226 /* Adjust the ptr and len according to what was deposited in the page */
229 mem
->tail
->len
+= len_to_copy
;
232 len_to_copy
= min(len
, SM_PAGE_SIZE
);
233 p
= xcalloc(1, sizeof(Mem_Node
));
235 p
->len
= len_to_copy
;
236 p
->data
= get_free_4k_page();
237 xmemcpy(p
->data
, data
, len_to_copy
);
240 /* The chain is empty */
241 mem
->head
= mem
->tail
= p
;
243 /* Append it to existing chain */
254 int memGrep(mem
, string
, nbytes
)
259 mem_node p
= mem
->head
;
261 int i
= 0, blk_idx
= 0, state
, goal
;
263 debug(19, 6, "memGrep: looking for %s in less than %d bytes.\n",
269 if (mem
->origin_offset
!= 0) {
270 debug(19, 1, "memGrep: Some lower chunk of data has been erased. Can't do memGrep!\n");
276 goal
= strlen(string
);
279 if (tolower(*mem_i
++) == tolower(*str_i
++))
289 /* Return offset of byte beyond the matching string */
293 if (blk_idx
>= p
->len
) {
306 int memCopy(mem
, offset
, buf
, size
)
312 mem_node p
= mem
->head
;
313 int t_off
= mem
->origin_offset
;
314 int bytes_to_go
= size
;
315 char *ptr_to_buf
= NULL
;
316 int bytes_from_this_packet
= 0;
317 int bytes_into_this_packet
= 0;
319 debug(19, 6, "memCopy: offset %d: size %d\n", offset
, size
);
322 fatal_dump("memCopy: NULL mem_node");
327 /* Seek our way into store */
328 while ((t_off
+ p
->len
) < offset
) {
333 debug(19, 1, "memCopy: Offset: %d is off limit of current object of %d\n", t_off
, offset
);
338 /* Start copying begining with this block until
341 bytes_into_this_packet
= offset
- t_off
;
342 bytes_from_this_packet
= min(bytes_to_go
,
343 p
->len
- bytes_into_this_packet
);
345 xmemcpy(buf
, p
->data
+ bytes_into_this_packet
, bytes_from_this_packet
);
346 bytes_to_go
-= bytes_from_this_packet
;
347 ptr_to_buf
= buf
+ bytes_from_this_packet
;
350 while (p
&& bytes_to_go
> 0) {
351 if (bytes_to_go
> p
->len
) {
352 xmemcpy(ptr_to_buf
, p
->data
, p
->len
);
353 ptr_to_buf
+= p
->len
;
354 bytes_to_go
-= p
->len
;
356 xmemcpy(ptr_to_buf
, p
->data
, bytes_to_go
);
357 bytes_to_go
-= bytes_to_go
;
366 /* Do whatever is necessary to begin storage of new object */
369 mem_ptr
new = xcalloc(1, sizeof(Mem_Hdr
));
370 new->tail
= new->head
= NULL
;
371 new->mem_free
= memFree
;
372 new->mem_free_data
= memFreeData
;
373 new->mem_free_data_upto
= memFreeDataUpto
;
374 new->mem_append
= memAppend
;
375 new->mem_copy
= memCopy
;
377 new->mem_grep
= memGrep
;
382 static void *get_free_thing(thing
)
386 if (!empty_stack(&thing
->free_page_stack
)) {
387 p
= pop(&thing
->free_page_stack
);
389 fatal_dump("get_free_thing: NULL pointer?");
391 p
= xmalloc(thing
->page_size
);
392 thing
->total_pages_allocated
++;
394 thing
->n_pages_in_use
++;
395 memset(p
, '\0', thing
->page_size
);
399 void *get_free_request_t()
401 return get_free_thing(&request_pool
);
404 void *get_free_mem_obj()
406 return get_free_thing(&mem_obj_pool
);
409 char *get_free_4k_page()
411 return get_free_thing(&sm_stats
);
414 char *get_free_8k_page()
416 return get_free_thing(&disk_stats
);
419 static void put_free_thing(thing
, p
)
423 thing
->n_pages_in_use
--;
424 if (thing
->total_pages_allocated
> thing
->max_pages
) {
426 thing
->total_pages_allocated
--;
427 } else if (full_stack(&thing
->free_page_stack
)) {
429 thing
->total_pages_allocated
--;
431 push(&thing
->free_page_stack
, p
);
435 void put_free_request_t(req
)
438 put_free_thing(&request_pool
, req
);
441 void put_free_mem_obj(mem
)
444 put_free_thing(&mem_obj_pool
, mem
);
447 void put_free_4k_page(page
)
450 put_free_thing(&sm_stats
, page
);
453 void put_free_8k_page(page
)
456 put_free_thing(&disk_stats
, page
);
461 sm_stats
.page_size
= SM_PAGE_SIZE
;
462 sm_stats
.total_pages_allocated
= 0;
463 sm_stats
.n_pages_free
= 0;
464 sm_stats
.n_pages_in_use
= 0;
465 sm_stats
.max_pages
= (getCacheMemMax() / SM_PAGE_SIZE
) >> 1;
467 disk_stats
.page_size
= DISK_PAGE_SIZE
;
468 disk_stats
.total_pages_allocated
= 0;
469 disk_stats
.n_pages_free
= 0;
470 disk_stats
.n_pages_in_use
= 0;
471 disk_stats
.max_pages
= 200;
473 request_pool
.page_size
= sizeof(request_t
);
474 request_pool
.total_pages_allocated
= 0;
475 request_pool
.n_pages_free
= 0;
476 request_pool
.n_pages_in_use
= 0;
477 request_pool
.max_pages
= FD_SETSIZE
>> 3;
479 mem_obj_pool
.page_size
= sizeof(MemObject
);
480 mem_obj_pool
.total_pages_allocated
= 0;
481 mem_obj_pool
.n_pages_free
= 0;
482 mem_obj_pool
.n_pages_in_use
= 0;
483 mem_obj_pool
.max_pages
= FD_SETSIZE
>> 3;
486 sm_stats
.max_pages
= 0;
487 disk_stats
.max_pages
= 0;
488 request_pool
.max_pages
= 0;
489 mem_obj_pool
.max_pages
= 0;
492 init_stack(&sm_stats
.free_page_stack
, sm_stats
.max_pages
);
493 init_stack(&disk_stats
.free_page_stack
, disk_stats
.max_pages
);
494 init_stack(&request_pool
.free_page_stack
, request_pool
.max_pages
);
495 init_stack(&mem_obj_pool
.free_page_stack
, mem_obj_pool
.max_pages
);