YYCacheソースコード解析ノート(一)
6350 ワード
YYK VstorageItemファイル
ヘッダファイル
@interface YYKVStorageItem : NSObject
@property (nonatomic, strong) NSString *key; ///< key
@property (nonatomic, strong) NSData *value; ///< value
@property (nonatomic, strong) NSString *filename; ///< filename (nil if inline)
@property (nonatomic, assign) int size; ///< value's size in bytes
@property (nonatomic, assign) int modTime; ///<
@property (nonatomic, assign) int accessTime; ///<
@property (nonatomic, strong) NSData *extendedData; ///< extended data (nil if no extended data)
@end
YYYYYVstorageItemとは、記憶されているセルごとに、あるキー値のペアとしても理解できますが、この記憶セルの属性がより完備しているだけでなく、タイムスタンプやアクセスタイムスタンプを修正したり、補足したデータを修正したりすることもあります.この補足したデータには何の意味があるのでしょうか.私の理解では、この記憶セルを補足して説明します.
YYK Vstorageファイル
typedef NS_ENUM(NSUInteger, YYKVStorageType) {
/// The `value` is stored as a file in file system.
YYKVStorageTypeFile = 0,
/// The `value` is stored in sqlite with blob type.
YYKVStorageTypeSQLite = 1,
/// The `value` is stored in file system or sqlite based on your choice.
YYKVStorageTypeMixed = 2,
};
YYYYYVstorageTypeについて,著者らはYYYYVstorageType SQLite,YYYVstorageType Fileの2つのストレージ方式の効率の問題を分析し,連絡先キャッシュなどの比較的小さなデータを大量に格納したい場合はYYYYVstorageType SQLiteを使用してより良いパフォーマンスを得ると結論した.画像キャッシュなどの大きなファイルを保存したい場合は、YYYVstorageTypeファイルを使用してパフォーマンスを向上させます.YYYYVstorageTypeMixedを使用して、プロジェクトごとにストレージタイプを選択することもできます.
YYK VstorageとYYK VstorageItemの関係
YYYK VstorageはmanagerのようにYYK VstorageItemを管理しています.YYK Vstorageでは個々のYYK VstorageItemを操作できます.たとえば、保存、削除、取得などです.YYYYVstorageファイルと照らし合わせると、多くの関連操作関数が含まれています.
保存の猶予
- (BOOL)saveItemWithKey:(NSString *)key value:(NSData *)value filename:(NSString *)filename extendedData:(NSData *)extendedData {
if (key.length == 0 || value.length == 0) return NO;
if (_type == YYKVStorageTypeFile && filename.length == 0) {
return NO;
}
if (filename.length) {
if (![self _fileWriteWithName:filename data:value]) {
return NO;
}
if (![self _dbSaveWithKey:key value:value fileName:filename extendedData:extendedData]) {
[self _fileDeleteWithName:filename];
return NO;
}
return YES;
} else {
if (_type != YYKVStorageTypeSQLite) {
NSString *filename = [self _dbGetFilenameWithKey:key];
if (filename) {
[self _fileDeleteWithName:filename];
}
}
return [self _dbSaveWithKey:key value:value fileName:nil extendedData:extendedData];
}
}
キャッシュ・アイテムを保存する操作手順:1.まずkey,valueが空かどうかを判断する.Filenameが空でない場合は、まずNSDataをディスクファイルに書き込み、次にデータベースに1つのディスクキャッシュファイルを挿入したテーブルレコードfilenameが空の場合、keyクエリーテーブルにキャッシュ項目を記録したfilenameフィールドに基づいて、クエリーしたfilenameに対応するバッファファイルを削除し、keyに対応するキャッシュテーブルレコードのfilenameフィールドを更新し、nilにクリアする.
複数のキャッシュ・アイテムの削除
- (BOOL)removeItemForKeys:(NSArray *)keys {
if (keys.count == 0) return NO;
switch (_type) {
case YYKVStorageTypeSQLite: {
return [self _dbDeleteItemWithKeys:keys];
} break;
case YYKVStorageTypeFile:
case YYKVStorageTypeMixed: {
NSArray *filenames = [self _dbGetFilenameWithKeys:keys];
for (NSString *filename in filenames) {
[self _fileDeleteWithName:filename];
}
return [self _dbDeleteItemWithKeys:keys];
} break;
default: return NO;
}
}
複数のキャッシュ・アイテムを削除する手順は、1です.配列が空であるか否かを判断する.キャッシュ方式のどちらがsqliteストレージであるかを判断し、sqliteに対応するキャッシュ項目を削除ファイルストレージである場合は、まずすべてのファイル名を取得し、次にハイブリッドモードである場合は削除し、上記の手順を繰り返します.
すべて削除
- (BOOL)removeAllItems {
if (![self _dbClose]) return NO;
[self _reset];
if (![self _dbOpen]) return NO;
if (![self _dbInitialize]) return NO;
return YES;
}
すべてのディレクトリを削除する手順は、1です.まずデータベースを閉じ、2を閉じたことを確認します.データベースをフォーマットし、dbを削除します.sqlite,db.sqlite-shm,db.sqlite-walファイル(この3つのファイルの具体的な役割は後述)は、すべてのディスクファイルをトラッシュディレクトリの下に移動し、トラッシュディレクトリの下のファイルを削除する操作をサブスレッドキューの上で非同期に実行する.データベースの初期化
補足:砂箱の下のSQLiteデータベースには3つのファイルが含まれています:db.sqlite,db.sqlite-shm,db.sqlite-wal. db.sqliteはデータベース自体のデータを格納する:テーブル、テーブルレコード、index、sequence...db.sqlite-shmはShared-Memory Filesを格納し、データベースはWALモードをオンにしなければならない.複数のスレッド/プロセスが同じデータベースにアクセスする場合、各データベース接続をメモリデータ共有できるようにし、db-walファイルの作成に伴って作成し、削除して削除する.db.sqlite-wal Write-Ahead Log(WAL)Files WALのフルネームはWrite Ahead Loggingであり、多くのデータベースで原子トランザクションを実現するためのメカニズムである.同様に、データベースが原子間トランザクションを実行する場合、最初のデータベース接続を作成するときにdb-walファイルを作成し、最後のデータベース接続が閉じるときにdb-walファイルを削除するWALモードをオンにする必要がある.
アイテムのクエリー
- (YYKVStorageItem *)getItemForKey:(NSString *)key {
if (key.length == 0) return nil;
YYKVStorageItem *item = [self _dbGetItemWithKey:key excludeInlineData:NO];
if (item) {
[self _dbUpdateAccessTimeWithKey:key];
if (item.filename) {
item.value = [self _fileReadWithName:item.filename];
if (!item.value) {
[self _dbDeleteItemWithKey:key];
item = nil;
}
}
}
return item;
}
クエリーの手順は、1です.まずkeyが空かどうかを判断する.キーで対応するキャッシュアイテム3を検索する.検索に成功した場合は、アクセス時間を更新し、ファイル名でデータを読み込み、データが空の場合はkeyで対応するファイルを削除します.
複数のアイテムの問合せ
- (NSArray *)getItemForKeys:(NSArray *)keys {
if (keys.count == 0) return nil;
NSMutableArray *items = [self _dbGetItemWithKeys:keys excludeInlineData:NO];
if (_type != YYKVStorageTypeSQLite) {
for (NSInteger i = 0, max = items.count; i < max; i++) {
YYKVStorageItem *item = items[i];
if (item.filename) {
item.value = [self _fileReadWithName:item.filename];
if (!item.value) {
if (item.key) [self _dbDeleteItemWithKey:item.key];
[items removeObjectAtIndex:i];
i--;
max--;
}
}
}
}
if (items.count > 0) {
[self _dbUpdateAccessTimeWithKeys:keys];
}
return items.count ? items : nil;
}
複数のキャッシュ・アイテムをクエリーするには:1.検索するキャッシュ配列が空かどうかを判断する.データベースですべてのキャッシュ・アイテム3を取得します.各キャッシュ・アイテムを巡回し、値が存在することを確認し、存在しない削除4.最後に、すべてのキャッシュ・アイテムのアクセス時間を更新します.
微博アカウント:梅嘉慶(クリック注目)