Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/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 "sl.h" //Azi:???
32//#include <fs.h>
33
34struct CacheEntry {
35 CICell ih;
36 long time;
37 long long offset;
38};
39typedef struct CacheEntry CacheEntry;
40
41#define kCacheSize (0x100000)
42#define kCacheMinBlockSize (0x200)
43#define kCacheMaxBlockSize (0x8000)
44#define kCacheMaxEntries (kCacheSize / kCacheMinBlockSize)
45
46static CICell gCacheIH;
47static long gCacheBlockSize;
48static long gCacheNumEntries;
49static long gCacheTime;
50
51#ifdef __i386__
52static CacheEntry *gCacheEntries;
53static char *gCacheBuffer;
54#else
55static CacheEntry gCacheEntries[kCacheMaxEntries];
56static char gCacheBuffer[kCacheSize];
57#endif
58
59#if CACHE_STATS
60unsigned long gCacheHits;
61unsigned long gCacheMisses;
62unsigned long gCacheEvicts;
63#endif
64
65void CacheReset()
66{
67 gCacheIH = NULL;
68}
69
70void CacheInit( CICell ih, long blockSize )
71{
72#ifdef __i386__
73 if ((ih == gCacheIH) && (blockSize == gCacheBlockSize))
74 return;
75#endif
76
77 if ((blockSize < kCacheMinBlockSize) ||
78 (blockSize > kCacheMaxBlockSize))
79 return;
80
81 gCacheBlockSize = blockSize;
82 gCacheNumEntries = kCacheSize / gCacheBlockSize;
83 gCacheTime = 0;
84
85#if CACHE_STATS
86 gCacheHits = 0;
87 gCacheMisses = 0;
88 gCacheEvicts = 0;
89#endif
90
91 gCacheIH = ih;
92
93#ifdef __i386__
94 if (!gCacheBuffer) gCacheBuffer = (char *) malloc(kCacheSize);
95 if (!gCacheEntries) gCacheEntries = (CacheEntry *) malloc(kCacheMaxEntries * sizeof(CacheEntry));
96 if ( !gCacheBuffer || !gCacheEntries )
97 {
98 gCacheIH = 0; // invalidate cache
99 return;
100 }
101#endif
102
103 bzero(gCacheEntries, kCacheMaxEntries * sizeof(CacheEntry));
104}
105
106long CacheRead( CICell ih, char * buffer, long long offset,
107 long length, long cache )
108{
109 long cnt, oldestEntry = 0, oldestTime, loadCache = 0;
110 CacheEntry *entry;
111
112 // See if the data can be cached.
113 if (cache && (gCacheIH == ih) && (length == gCacheBlockSize)) {
114 // Look for the data in the cache.
115 for (cnt = 0; cnt < gCacheNumEntries; cnt++) {
116 entry = &gCacheEntries[cnt];
117 if ((entry->ih == ih) && (entry->offset == offset)) {
118 entry->time = ++gCacheTime;
119 break;
120 }
121 }
122
123 // If the data was found copy it to the caller.
124 if (cnt != gCacheNumEntries) {
125 bcopy(gCacheBuffer + cnt * gCacheBlockSize, buffer, gCacheBlockSize);
126#if CACHE_STATS
127 gCacheHits++;
128#endif
129 return gCacheBlockSize;
130 }
131
132 // Could not find the data in the cache.
133 loadCache = 1;
134 }
135
136 // Read the data from the disk.
137 Seek(ih, offset);
138 Read(ih, (long)buffer, length);
139#if CACHE_STATS
140 if (cache) gCacheMisses++;
141#endif
142
143 // Put the data from the disk in the cache if needed.
144 if (loadCache) {
145 // Find a free entry.
146 oldestTime = gCacheTime;
147 for (cnt = 0; cnt < gCacheNumEntries; cnt++) {
148 entry = &gCacheEntries[cnt];
149
150 // Found a free entry.
151 if (entry->ih == 0) break;
152
153 if (entry->time < oldestTime) {
154 oldestTime = entry->time;
155 oldestEntry = cnt;
156 }
157 }
158
159 // If no free entry was found, use the oldest.
160 if (cnt == gCacheNumEntries) {
161 cnt = oldestEntry;
162#if CACHE_STATS
163 gCacheEvicts++;
164#endif
165 }
166
167 // Copy the data from disk to the new entry.
168 entry = &gCacheEntries[cnt];
169 entry->ih = ih;
170 entry->time = ++gCacheTime;
171 entry->offset = offset;
172 bcopy(buffer, gCacheBuffer + cnt * gCacheBlockSize, gCacheBlockSize);
173 }
174
175 return length;
176}
177

Archive Download this file

Revision: 840