Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazileon/i386/libsaio/cache.c

1/*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 2.0 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * cache.c - A simple cache for file systems meta-data.
24 *
25 * Copyright (c) 2000 Apple Computer, Inc.
26 *
27 * DRI: Josh de Cesare
28 */
29
30#include <sl.h>
31// #include <fs.h>
32
33struct CacheEntry {
34 CICell ih;
35 long time;
36 long long offset;
37};
38typedef struct CacheEntry CacheEntry;
39
40#define kCacheSize (0x100000)
41#define kCacheMinBlockSize (0x200)
42#define kCacheMaxBlockSize (0x8000)
43#define kCacheMaxEntries (kCacheSize / kCacheMinBlockSize)
44
45static CICell gCacheIH;
46static long gCacheBlockSize;
47static long gCacheNumEntries;
48static long gCacheTime;
49
50#ifdef __i386__
51static CacheEntry *gCacheEntries;
52static char *gCacheBuffer;
53#else
54static CacheEntry gCacheEntries[kCacheMaxEntries];
55static char gCacheBuffer[kCacheSize];
56#endif
57
58#if CACHE_STATS
59unsigned long gCacheHits;
60unsigned long gCacheMisses;
61unsigned long gCacheEvicts;
62#endif
63
64void CacheReset()
65{
66 gCacheIH = NULL;
67}
68
69void CacheInit( CICell ih, long blockSize )
70{
71#ifdef __i386__
72 if ((ih == gCacheIH) && (blockSize == gCacheBlockSize))
73 return;
74#endif
75
76 if ((blockSize < kCacheMinBlockSize) ||
77 (blockSize > kCacheMaxBlockSize))
78 return;
79
80 gCacheBlockSize = blockSize;
81 gCacheNumEntries = kCacheSize / gCacheBlockSize;
82 gCacheTime = 0;
83
84#if CACHE_STATS
85 gCacheHits = 0;
86 gCacheMisses = 0;
87 gCacheEvicts = 0;
88#endif
89
90 gCacheIH = ih;
91
92#ifdef __i386__
93 if (!gCacheBuffer) gCacheBuffer = (char *) malloc(kCacheSize);
94 if (!gCacheEntries) gCacheEntries = (CacheEntry *) malloc(kCacheMaxEntries * sizeof(CacheEntry));
95 if ( !gCacheBuffer || !gCacheEntries )
96 {
97 gCacheIH = 0; // invalidate cache
98 return;
99 }
100#endif
101
102 bzero(gCacheEntries, kCacheMaxEntries * sizeof(CacheEntry));
103}
104
105long CacheRead( CICell ih, char * buffer, long long offset,
106 long length, long cache )
107{
108 long cnt, oldestEntry = 0, oldestTime, loadCache = 0;
109 CacheEntry *entry;
110
111 // See if the data can be cached.
112 if (cache && (gCacheIH == ih) && (length == gCacheBlockSize)) {
113 // Look for the data in the cache.
114 for (cnt = 0; cnt < gCacheNumEntries; cnt++) {
115 entry = &gCacheEntries[cnt];
116 if ((entry->ih == ih) && (entry->offset == offset)) {
117 entry->time = ++gCacheTime;
118 break;
119 }
120 }
121
122 // If the data was found copy it to the caller.
123 if (cnt != gCacheNumEntries) {
124 bcopy(gCacheBuffer + cnt * gCacheBlockSize, buffer, gCacheBlockSize);
125#if CACHE_STATS
126 gCacheHits++;
127#endif
128 return gCacheBlockSize;
129 }
130
131 // Could not find the data in the cache.
132 loadCache = 1;
133 }
134
135 // Read the data from the disk.
136 Seek(ih, offset);
137 Read(ih, (long)buffer, length);
138#if CACHE_STATS
139 if (cache) gCacheMisses++;
140#endif
141
142 // Put the data from the disk in the cache if needed.
143 if (loadCache) {
144 // Find a free entry.
145 oldestTime = gCacheTime;
146 for (cnt = 0; cnt < gCacheNumEntries; cnt++) {
147 entry = &gCacheEntries[cnt];
148
149 // Found a free entry.
150 if (entry->ih == 0) break;
151
152 if (entry->time < oldestTime) {
153 oldestTime = entry->time;
154 oldestEntry = cnt;
155 }
156 }
157
158 // If no free entry was found, use the oldest.
159 if (cnt == gCacheNumEntries) {
160 cnt = oldestEntry;
161#if CACHE_STATS
162 gCacheEvicts++;
163#endif
164 }
165
166 // Copy the data from disk to the new entry.
167 entry = &gCacheEntries[cnt];
168 entry->ih = ih;
169 entry->time = ++gCacheTime;
170 entry->offset = offset;
171 bcopy(buffer, gCacheBuffer + cnt * gCacheBlockSize, gCacheBlockSize);
172 }
173
174 return length;
175}
176

Archive Download this file

Revision: 399