]>
git.saurik.com Git - apple/libc.git/blob - libdarwin/dirstat_collection.c
c91a2fe7762bbee5e68b711b88cad3925507f1d4
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * Copyright (c) 2017 Apple Inc. All rights reserved.
39 * @APPLE_LICENSE_HEADER_START@
41 * This file contains Original Code and/or Modifications of Original Code
42 * as defined in and that are subject to the Apple Public Source License
43 * Version 2.0 (the 'License'). You may not use this file except in
44 * compliance with the License. Please obtain a copy of the License at
45 * http://www.opensource.apple.com/apsl/ and read it before using this
48 * The Original Code and all software distributed under the License are
49 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
50 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
51 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
52 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
53 * Please see the License for the specific language governing rights and
54 * limitations under the License.
56 * @APPLE_LICENSE_HEADER_END@
60 * Taken from file_cmds:du.c
66 #include "dirstat_collection.h"
69 struct fileid_entry
*next
;
70 struct fileid_entry
*previous
;
76 struct dirstat_fileid_set_s
{
77 struct fileid_entry
**buckets
;
78 struct fileid_entry
*free_list
;
79 size_t number_buckets
;
80 unsigned long number_entries
;
84 static const size_t links_hash_initial_size
= 8192;
87 _dirstat_fileid_set_create(void)
89 dirstat_fileid_set_t ds
= calloc(1, sizeof(dirstat_fileid_set_s
));
90 ds
->number_buckets
= links_hash_initial_size
;
91 ds
->buckets
= calloc(ds
->number_buckets
, sizeof(ds
->buckets
[0]));
92 if (ds
->buckets
== NULL
) {
100 _dirstat_fileid_set_destroy(dirstat_fileid_set_t ds
)
102 struct fileid_entry
*le
;
103 for (size_t i
= 0; i
< ds
->number_buckets
; i
++) {
104 while (ds
->buckets
[i
] != NULL
) {
106 ds
->buckets
[i
] = le
->next
;
115 _dirstat_fileid_set_add(dirstat_fileid_set_t ds
, uint64_t fileid
)
117 struct fileid_entry
*le
, **new_buckets
;
121 /* If the hash table is getting too full, enlarge it. */
122 if (ds
->number_entries
> ds
->number_buckets
* 10 && !ds
->stop_allocating
) {
123 new_size
= ds
->number_buckets
* 2;
124 new_buckets
= calloc(new_size
, sizeof(struct fileid_entry
*));
126 /* Try releasing the free list to see if that helps. */
127 if (new_buckets
== NULL
&& ds
->free_list
!= NULL
) {
128 while (ds
->free_list
!= NULL
) {
130 ds
->free_list
= le
->next
;
133 new_buckets
= calloc(new_size
, sizeof(new_buckets
[0]));
136 if (new_buckets
== NULL
) {
137 ds
->stop_allocating
= 1;
139 for (i
= 0; i
< ds
->number_buckets
; i
++) {
140 while (ds
->buckets
[i
] != NULL
) {
141 /* Remove entry from old bucket. */
143 ds
->buckets
[i
] = le
->next
;
145 /* Add entry to new bucket. */
146 hash
= (int)(fileid
% new_size
);
148 if (new_buckets
[hash
] != NULL
)
149 new_buckets
[hash
]->previous
=
151 le
->next
= new_buckets
[hash
];
153 new_buckets
[hash
] = le
;
157 ds
->buckets
= new_buckets
;
158 ds
->number_buckets
= new_size
;
162 /* Try to locate this entry in the hash table. */
163 hash
= (int)(fileid
% ds
->number_buckets
);
164 for (le
= ds
->buckets
[hash
]; le
!= NULL
; le
= le
->next
) {
165 if (le
->fileid
== fileid
) {
168 * Save memory by releasing an entry when we've seen
171 if (--le
->links
<= 0) {
172 if (le
->previous
!= NULL
)
173 le
->previous
->next
= le
->next
;
174 if (le
->next
!= NULL
)
175 le
->next
->previous
= le
->previous
;
176 if (buckets
[hash
] == le
)
177 buckets
[hash
] = le
->next
;
179 /* Recycle this node through the free list */
180 if (stop_allocating
) {
183 le
->next
= free_list
;
192 if (ds
->stop_allocating
)
195 /* Add this entry to the links cache. */
196 if (ds
->free_list
!= NULL
) {
197 /* Pull a node from the free list if we can. */
199 ds
->free_list
= le
->next
;
201 /* Malloc one if we have to. */
202 le
= malloc(sizeof(struct fileid_entry
));
205 ds
->stop_allocating
= 1;
209 ds
->number_entries
++;
210 le
->next
= ds
->buckets
[hash
];
212 if (ds
->buckets
[hash
] != NULL
)
213 ds
->buckets
[hash
]->previous
= le
;
214 ds
->buckets
[hash
] = le
;