|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 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 1.1 (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: File: GenericMRUCache.c ! 24: ! 25: Contains: Contains cache accessor routines based on MRU / LRU ordering. ! 26: ! 27: Version: HFS+ 1.0 ! 28: ! 29: Copyright: � 1997-1998 by Apple Computer, Inc., all rights reserved. ! 30: ! 31: File Ownership: ! 32: ! 33: DRI: Deric Horn ! 34: ! 35: Other Contact: Don Brady ! 36: ! 37: Technology: HFS+ ! 38: ! 39: Writers: ! 40: ! 41: (DSH) Deric Horn ! 42: ! 43: Change History (most recent first): ! 44: ! 45: <CS2> 1/29/98 DSH Add TrashMRUCache for TrashAllFSCaches API support. ! 46: <CS1> 7/25/97 DSH first checked in ! 47: */ ! 48: ! 49: #include "../../hfs_macos_defs.h" ! 50: #include "../headers/FileMgrInternal.h" ! 51: ! 52: enum { ! 53: // error codes ! 54: errNotInCache = -123, ! 55: errInvalidKey = -124 ! 56: }; ! 57: ! 58: ! 59: struct CacheBlock { ! 60: struct CacheBlock *nextMRU; // next node in MRU order ! 61: struct CacheBlock *nextLRU; // next node in LRU order ! 62: UInt32 flags; // status flags ! 63: UInt32 key; // comparrison Key ! 64: char buffer[1]; // user defineable data ! 65: }; ! 66: typedef struct CacheBlock CacheBlock; ! 67: ! 68: struct CacheGlobals { ! 69: UInt32 cacheBlockSize; // Size of CacheBlock structure including the buffer ! 70: UInt32 cacheBufferSize; // Size of cache buffer ! 71: UInt32 numCacheBlocks; // Number of blocks in cache ! 72: CacheBlock *mru; ! 73: CacheBlock *lru; ! 74: }; ! 75: typedef struct CacheGlobals CacheGlobals; ! 76: ! 77: ! 78: // ! 79: // Internal routines ! 80: // ! 81: static void InsertAsMRU ( CacheGlobals *cacheGlobals, CacheBlock *cacheBlock ); ! 82: static void InsertAsLRU ( CacheGlobals *cacheGlobals, CacheBlock *cacheBlock ); ! 83: ! 84: ! 85: // ! 86: // Diagram of Cache structures ! 87: // ! 88: // _______ ________ ________ ________ ! 89: // |data | | buff | | buff | | buff | ! 90: // | mru |-----> | nMRU |-----> | nMRU |--> ��� --->| nMRU |-->� ! 91: // | lru |-\ �<-| nLRU | <-----| nLRU |<-- ��� <---| nLRU | ! 92: // ------- \ -------- -------- -------- ! 93: // \ | ! 94: // \-----------------------------------------/ ! 95: // CacheGlobals CacheBlock's ! 96: ! 97: ! 98: ! 99: ! 100: //������������������������������������������������������������������������������� ! 101: // Routine: InitMRUCache ! 102: // ! 103: // Function: Allocates cache, and initializes all the cache structures. ! 104: // ! 105: //������������������������������������������������������������������������������� ! 106: OSErr InitMRUCache( UInt32 bufferSize, UInt32 numCacheBlocks, Ptr *cachePtr ) ! 107: { ! 108: OSErr err; ! 109: short i, lastBuffer; ! 110: CacheBlock *cacheBlock; ! 111: CacheGlobals *cacheGlobals; ! 112: UInt32 cacheBlockSize = offsetof( CacheBlock, buffer ) + bufferSize; ! 113: ! 114: cacheGlobals = (CacheGlobals *) NewPtrSysClear( sizeof( CacheGlobals ) + ( numCacheBlocks * cacheBlockSize ) ); ! 115: err = MemError(); ! 116: ! 117: if ( err == noErr ) ! 118: { ! 119: cacheGlobals->cacheBlockSize = cacheBlockSize; ! 120: cacheGlobals->cacheBufferSize = bufferSize; ! 121: cacheGlobals->numCacheBlocks = numCacheBlocks; ! 122: ! 123: lastBuffer = numCacheBlocks - 1; // last buffer number, since they start at 0 ! 124: ! 125: // Initialize the LRU order for the cache ! 126: cacheGlobals->lru = (CacheBlock *)((Ptr)cacheGlobals + sizeof( CacheGlobals ) + (lastBuffer * cacheBlockSize)); ! 127: cacheGlobals->lru->nextMRU = nil; ! 128: ! 129: // Initialize the MRU order for the cache ! 130: cacheGlobals->mru = (CacheBlock *)( (Ptr)cacheGlobals + sizeof( CacheGlobals ) ); // points to 1st cache block ! 131: cacheGlobals->mru->nextLRU = nil; ! 132: ! 133: // Traverse nodes, setting initial mru, lru, and default values ! 134: for ( i=0, cacheBlock=cacheGlobals->mru; i<lastBuffer ; i++ ) ! 135: { ! 136: cacheBlock->key = kInvalidMRUCacheKey; // initialize key to illegal while we're at it ! 137: cacheBlock->flags = 0; ! 138: cacheBlock->nextMRU = (CacheBlock *) ( (Ptr)cacheBlock + cacheBlockSize ); ! 139: cacheBlock = cacheBlock->nextMRU; ! 140: } ! 141: // And the last Block ! 142: cacheGlobals->lru->key = kInvalidMRUCacheKey; ! 143: cacheBlock->flags = 0; ! 144: ! 145: for ( i=0, cacheBlock=cacheGlobals->lru; i<lastBuffer ; i++ ) ! 146: { ! 147: cacheBlock->nextLRU = (CacheBlock *) ( (Ptr)cacheBlock - cacheBlockSize ); ! 148: cacheBlock = cacheBlock->nextLRU; ! 149: } ! 150: ! 151: *cachePtr = (Ptr) cacheGlobals; // return cacheGlobals to user ! 152: } ! 153: else ! 154: { ! 155: *cachePtr = nil; ! 156: } ! 157: ! 158: return( err ); ! 159: } ! 160: ! 161: ! 162: //������������������������������������������������������������������������������� ! 163: // Routine: DisposeMRUCache ! 164: // ! 165: // Function: Dispose of all memory allocated by the cache ! 166: // ! 167: //������������������������������������������������������������������������������� ! 168: OSErr DisposeMRUCache( Ptr cachePtr ) ! 169: { ! 170: OSErr err; ! 171: ! 172: DisposePtr( cachePtr ); ! 173: err = MemError(); ! 174: ! 175: return( err ); ! 176: } ! 177: ! 178: ! 179: //������������������������������������������������������������������������������� ! 180: // Routine: TrashMRUCache ! 181: // ! 182: // Function: Invalidates all entries in the MRU cache pointed to by cachePtr. ! 183: // ! 184: //������������������������������������������������������������������������������� ! 185: void TrashMRUCache( Ptr cachePtr ) ! 186: { ! 187: CacheGlobals *cacheGlobals = (CacheGlobals *) cachePtr; ! 188: CacheBlock *cacheBlock; ! 189: ! 190: for ( cacheBlock = cacheGlobals->mru ; cacheBlock != nil ; cacheBlock = cacheBlock->nextMRU ) ! 191: { ! 192: cacheBlock->flags = 0; // Clear the flags ! 193: cacheBlock->key = kInvalidMRUCacheKey; // Make it an illegal value ! 194: } ! 195: } ! 196: ! 197: ! 198: //������������������������������������������������������������������������������� ! 199: // Routine: GetMRUCacheBlock ! 200: // ! 201: // Function: Return buffer associated with the passed in key. ! 202: // Search the cache in MRU order ! 203: // � We can insert the found cache block at the head of mru automatically ! 204: // ! 205: //������������������������������������������������������������������������������� ! 206: OSErr GetMRUCacheBlock( UInt32 key, Ptr cachePtr, Ptr *buffer ) ! 207: { ! 208: CacheBlock *cacheBlock; ! 209: CacheGlobals *cacheGlobals = (CacheGlobals *) cachePtr; ! 210: ! 211: // if ( key == kInvalidMRUCacheKey ) // removed for performance ! 212: // return( errInvalidKey ); ! 213: ! 214: for ( cacheBlock = cacheGlobals->mru ; (cacheBlock != nil) && (cacheBlock->key != kInvalidMRUCacheKey) ; cacheBlock = cacheBlock->nextMRU ) ! 215: { ! 216: if ( cacheBlock->key == key ) ! 217: { ! 218: InsertAsMRU( cacheGlobals, cacheBlock ); ! 219: *buffer = (Ptr) cacheBlock->buffer; ! 220: return( noErr ); ! 221: } ! 222: } ! 223: ! 224: return( errNotInCache ); ! 225: } ! 226: ! 227: ! 228: ! 229: //������������������������������������������������������������������������������� ! 230: // Routine: InvalidateMRUCacheBlock ! 231: // ! 232: // Function: Place the cache block at the head of the lru queue and mark it invalid ! 233: // ! 234: //������������������������������������������������������������������������������� ! 235: void InvalidateMRUCacheBlock( Ptr cachePtr, Ptr buffer ) ! 236: { ! 237: CacheGlobals *cacheGlobals = (CacheGlobals *) cachePtr; ! 238: CacheBlock *cacheBlock; ! 239: ! 240: cacheBlock = (CacheBlock *) (buffer - offsetof( CacheBlock, buffer )); ! 241: cacheBlock->flags = 0; // Clear the flags ! 242: cacheBlock->key = kInvalidMRUCacheKey; // Make it an illegal value ! 243: InsertAsLRU( cacheGlobals, cacheBlock ); ! 244: } ! 245: ! 246: ! 247: //������������������������������������������������������������������������������� ! 248: // Routine: InsertMRUCacheBlock ! 249: // ! 250: // Function: Place the CacheBlock associated with the passed in key at the ! 251: // head of the mru queue and replace the buffer with the passed in buffer ! 252: // ! 253: //������������������������������������������������������������������������������� ! 254: void InsertMRUCacheBlock( Ptr cachePtr, UInt32 key, Ptr buffer ) ! 255: { ! 256: CacheBlock *cacheBlock = NULL; ! 257: Ptr cacheBuffer; ! 258: OSErr err; ! 259: CacheGlobals *cacheGlobals = (CacheGlobals *) cachePtr; ! 260: UInt32 cacheBufferSize; ! 261: ! 262: err = GetMRUCacheBlock( key, cachePtr, &cacheBuffer ); ! 263: if ( err == errNotInCache ) ! 264: cacheBlock = cacheGlobals->lru; ! 265: else if ( err == noErr ) ! 266: cacheBlock = (CacheBlock *) (cacheBuffer - offsetof( CacheBlock, buffer )); ! 267: ! 268: cacheBufferSize = cacheGlobals->cacheBufferSize; ! 269: if ( cacheBufferSize == sizeof(UInt32) ) ! 270: *(UInt32*)cacheBlock->buffer = *(UInt32*)buffer; ! 271: else ! 272: BlockMoveData( buffer, cacheBlock->buffer, cacheBufferSize ); ! 273: InsertAsMRU( cacheGlobals, cacheBlock ); ! 274: ! 275: cacheBlock->flags = 0; ! 276: cacheBlock->key = key; ! 277: } ! 278: ! 279: ! 280: ! 281: ! 282: //������������������������������������������������������������������������������� ! 283: // Routine: InsertMRUCacheBlock ! 284: // ! 285: // Function: Moves cache block to head of mru order in double linked list of cached blocks ! 286: // ! 287: //������������������������������������������������������������������������������� ! 288: static void InsertAsMRU ( CacheGlobals *cacheGlobals, CacheBlock *cacheBlock ) ! 289: { ! 290: CacheBlock *swapBlock; ! 291: ! 292: if ( cacheGlobals->mru != cacheBlock ) // if it's not already the mru cacheBlock ! 293: { ! 294: swapBlock = cacheGlobals->mru; // put it in the front of the double queue ! 295: cacheGlobals->mru = cacheBlock; ! 296: cacheBlock->nextLRU->nextMRU = cacheBlock->nextMRU; ! 297: if ( cacheBlock->nextMRU != nil ) ! 298: cacheBlock->nextMRU->nextLRU = cacheBlock->nextLRU; ! 299: else ! 300: cacheGlobals->lru= cacheBlock->nextLRU; ! 301: cacheBlock->nextMRU = swapBlock; ! 302: cacheBlock->nextLRU = nil; ! 303: swapBlock->nextLRU = cacheBlock; ! 304: } ! 305: } ! 306: ! 307: ! 308: //������������������������������������������������������������������������������� ! 309: // Routine: InsertMRUCacheBlock ! 310: // ! 311: // Function: Moves cache block to head of lru order in double linked list of cached blocks ! 312: // ! 313: //������������������������������������������������������������������������������� ! 314: static void InsertAsLRU ( CacheGlobals *cacheGlobals, CacheBlock *cacheBlock ) ! 315: { ! 316: CacheBlock *swapBlock; ! 317: ! 318: if ( cacheGlobals->lru != cacheBlock ) ! 319: { ! 320: swapBlock = cacheGlobals->lru; ! 321: cacheGlobals->lru = cacheBlock; ! 322: cacheBlock->nextMRU->nextLRU = cacheBlock->nextLRU; ! 323: if ( cacheBlock->nextLRU != nil ) ! 324: cacheBlock->nextLRU->nextMRU = cacheBlock->nextMRU; ! 325: else ! 326: cacheGlobals->mru= cacheBlock->nextMRU; ! 327: cacheBlock->nextLRU = swapBlock; ! 328: cacheBlock->nextMRU = nil; ! 329: swapBlock->nextMRU = cacheBlock; ! 330: } ! 331: } ! 332: ! 333:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.