New file |
| | |
| | | // |
| | | // YYKVStorage.h |
| | | // YYCache <https://github.com/ibireme/YYCache> |
| | | // |
| | | // Created by ibireme on 15/4/22. |
| | | // Copyright (c) 2015 ibireme. |
| | | // |
| | | // This source code is licensed under the MIT-style license found in the |
| | | // LICENSE file in the root directory of this source tree. |
| | | // |
| | | |
| | | #import <Foundation/Foundation.h> |
| | | |
| | | NS_ASSUME_NONNULL_BEGIN |
| | | |
| | | /** |
| | | YYKVStorageItem is used by `YYKVStorage` to store key-value pair and meta data. |
| | | Typically, you should not use this class directly. |
| | | */ |
| | | @interface YYKVStorageItem : NSObject |
| | | @property (nonatomic, strong) NSString *key; ///< key |
| | | @property (nonatomic, strong) NSData *value; ///< value |
| | | @property (nullable, nonatomic, strong) NSString *filename; ///< filename (nil if inline) |
| | | @property (nonatomic) int size; ///< value's size in bytes |
| | | @property (nonatomic) int modTime; ///< modification unix timestamp |
| | | @property (nonatomic) int accessTime; ///< last access unix timestamp |
| | | @property (nullable, nonatomic, strong) NSData *extendedData; ///< extended data (nil if no extended data) |
| | | @end |
| | | |
| | | /** |
| | | Storage type, indicated where the `YYKVStorageItem.value` stored. |
| | | |
| | | @discussion Typically, write data to sqlite is faster than extern file, but |
| | | reading performance is dependent on data size. In my test (on iPhone 6 64G), |
| | | read data from extern file is faster than from sqlite when the data is larger |
| | | than 20KB. |
| | | |
| | | * If you want to store large number of small datas (such as contacts cache), |
| | | use YYKVStorageTypeSQLite to get better performance. |
| | | * If you want to store large files (such as image cache), |
| | | use YYKVStorageTypeFile to get better performance. |
| | | * You can use YYKVStorageTypeMixed and choice your storage type for each item. |
| | | |
| | | See <http://www.sqlite.org/intern-v-extern-blob.html> for more information. |
| | | */ |
| | | 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, |
| | | }; |
| | | |
| | | |
| | | |
| | | /** |
| | | YYKVStorage is a key-value storage based on sqlite and file system. |
| | | Typically, you should not use this class directly. |
| | | |
| | | @discussion The designated initializer for YYKVStorage is `initWithPath:type:`. |
| | | After initialized, a directory is created based on the `path` to hold key-value data. |
| | | Once initialized you should not read or write this directory without the instance. |
| | | |
| | | You may compile the latest version of sqlite and ignore the libsqlite3.dylib in |
| | | iOS system to get 2x~4x speed up. |
| | | |
| | | @warning The instance of this class is *NOT* thread safe, you need to make sure |
| | | that there's only one thread to access the instance at the same time. If you really |
| | | need to process large amounts of data in multi-thread, you should split the data |
| | | to multiple KVStorage instance (sharding). |
| | | */ |
| | | @interface YYKVStorage : NSObject |
| | | |
| | | #pragma mark - Attribute |
| | | ///============================================================================= |
| | | /// @name Attribute |
| | | ///============================================================================= |
| | | |
| | | @property (nonatomic, readonly) NSString *path; ///< The path of this storage. |
| | | @property (nonatomic, readonly) YYKVStorageType type; ///< The type of this storage. |
| | | @property (nonatomic) BOOL errorLogsEnabled; ///< Set `YES` to enable error logs for debug. |
| | | |
| | | #pragma mark - Initializer |
| | | ///============================================================================= |
| | | /// @name Initializer |
| | | ///============================================================================= |
| | | - (instancetype)init UNAVAILABLE_ATTRIBUTE; |
| | | + (instancetype)new UNAVAILABLE_ATTRIBUTE; |
| | | |
| | | /** |
| | | The designated initializer. |
| | | |
| | | @param path Full path of a directory in which the storage will write data. If |
| | | the directory is not exists, it will try to create one, otherwise it will |
| | | read the data in this directory. |
| | | @param type The storage type. After first initialized you should not change the |
| | | type of the specified path. |
| | | @return A new storage object, or nil if an error occurs. |
| | | @warning Multiple instances with the same path will make the storage unstable. |
| | | */ |
| | | - (nullable instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type NS_DESIGNATED_INITIALIZER; |
| | | |
| | | |
| | | #pragma mark - Save Items |
| | | ///============================================================================= |
| | | /// @name Save Items |
| | | ///============================================================================= |
| | | |
| | | /** |
| | | Save an item or update the item with 'key' if it already exists. |
| | | |
| | | @discussion This method will save the item.key, item.value, item.filename and |
| | | item.extendedData to disk or sqlite, other properties will be ignored. item.key |
| | | and item.value should not be empty (nil or zero length). |
| | | |
| | | If the `type` is YYKVStorageTypeFile, then the item.filename should not be empty. |
| | | If the `type` is YYKVStorageTypeSQLite, then the item.filename will be ignored. |
| | | It the `type` is YYKVStorageTypeMixed, then the item.value will be saved to file |
| | | system if the item.filename is not empty, otherwise it will be saved to sqlite. |
| | | |
| | | @param item An item. |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)saveItem:(YYKVStorageItem *)item; |
| | | |
| | | /** |
| | | Save an item or update the item with 'key' if it already exists. |
| | | |
| | | @discussion This method will save the key-value pair to sqlite. If the `type` is |
| | | YYKVStorageTypeFile, then this method will failed. |
| | | |
| | | @param key The key, should not be empty (nil or zero length). |
| | | @param value The key, should not be empty (nil or zero length). |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)saveItemWithKey:(NSString *)key value:(NSData *)value; |
| | | |
| | | /** |
| | | Save an item or update the item with 'key' if it already exists. |
| | | |
| | | @discussion |
| | | If the `type` is YYKVStorageTypeFile, then the `filename` should not be empty. |
| | | If the `type` is YYKVStorageTypeSQLite, then the `filename` will be ignored. |
| | | It the `type` is YYKVStorageTypeMixed, then the `value` will be saved to file |
| | | system if the `filename` is not empty, otherwise it will be saved to sqlite. |
| | | |
| | | @param key The key, should not be empty (nil or zero length). |
| | | @param value The key, should not be empty (nil or zero length). |
| | | @param filename The filename. |
| | | @param extendedData The extended data for this item (pass nil to ignore it). |
| | | |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)saveItemWithKey:(NSString *)key |
| | | value:(NSData *)value |
| | | filename:(nullable NSString *)filename |
| | | extendedData:(nullable NSData *)extendedData; |
| | | |
| | | #pragma mark - Remove Items |
| | | ///============================================================================= |
| | | /// @name Remove Items |
| | | ///============================================================================= |
| | | |
| | | /** |
| | | Remove an item with 'key'. |
| | | |
| | | @param key The item's key. |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)removeItemForKey:(NSString *)key; |
| | | |
| | | /** |
| | | Remove items with an array of keys. |
| | | |
| | | @param keys An array of specified keys. |
| | | |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)removeItemForKeys:(NSArray<NSString *> *)keys; |
| | | |
| | | /** |
| | | Remove all items which `value` is larger than a specified size. |
| | | |
| | | @param size The maximum size in bytes. |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)removeItemsLargerThanSize:(int)size; |
| | | |
| | | /** |
| | | Remove all items which last access time is earlier than a specified timestamp. |
| | | |
| | | @param time The specified unix timestamp. |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)removeItemsEarlierThanTime:(int)time; |
| | | |
| | | /** |
| | | Remove items to make the total size not larger than a specified size. |
| | | The least recently used (LRU) items will be removed first. |
| | | |
| | | @param maxSize The specified size in bytes. |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)removeItemsToFitSize:(int)maxSize; |
| | | |
| | | /** |
| | | Remove items to make the total count not larger than a specified count. |
| | | The least recently used (LRU) items will be removed first. |
| | | |
| | | @param maxCount The specified item count. |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)removeItemsToFitCount:(int)maxCount; |
| | | |
| | | /** |
| | | Remove all items in background queue. |
| | | |
| | | @discussion This method will remove the files and sqlite database to a trash |
| | | folder, and then clear the folder in background queue. So this method is much |
| | | faster than `removeAllItemsWithProgressBlock:endBlock:`. |
| | | |
| | | @return Whether succeed. |
| | | */ |
| | | - (BOOL)removeAllItems; |
| | | |
| | | /** |
| | | Remove all items. |
| | | |
| | | @warning You should not send message to this instance in these blocks. |
| | | @param progress This block will be invoked during removing, pass nil to ignore. |
| | | @param end This block will be invoked at the end, pass nil to ignore. |
| | | */ |
| | | - (void)removeAllItemsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress |
| | | endBlock:(nullable void(^)(BOOL error))end; |
| | | |
| | | |
| | | #pragma mark - Get Items |
| | | ///============================================================================= |
| | | /// @name Get Items |
| | | ///============================================================================= |
| | | |
| | | /** |
| | | Get item with a specified key. |
| | | |
| | | @param key A specified key. |
| | | @return Item for the key, or nil if not exists / error occurs. |
| | | */ |
| | | - (nullable YYKVStorageItem *)getItemForKey:(NSString *)key; |
| | | |
| | | /** |
| | | Get item information with a specified key. |
| | | The `value` in this item will be ignored. |
| | | |
| | | @param key A specified key. |
| | | @return Item information for the key, or nil if not exists / error occurs. |
| | | */ |
| | | - (nullable YYKVStorageItem *)getItemInfoForKey:(NSString *)key; |
| | | |
| | | /** |
| | | Get item value with a specified key. |
| | | |
| | | @param key A specified key. |
| | | @return Item's value, or nil if not exists / error occurs. |
| | | */ |
| | | - (nullable NSData *)getItemValueForKey:(NSString *)key; |
| | | |
| | | /** |
| | | Get items with an array of keys. |
| | | |
| | | @param keys An array of specified keys. |
| | | @return An array of `YYKVStorageItem`, or nil if not exists / error occurs. |
| | | */ |
| | | - (nullable NSArray<YYKVStorageItem *> *)getItemForKeys:(NSArray<NSString *> *)keys; |
| | | |
| | | /** |
| | | Get item infomartions with an array of keys. |
| | | The `value` in items will be ignored. |
| | | |
| | | @param keys An array of specified keys. |
| | | @return An array of `YYKVStorageItem`, or nil if not exists / error occurs. |
| | | */ |
| | | - (nullable NSArray<YYKVStorageItem *> *)getItemInfoForKeys:(NSArray<NSString *> *)keys; |
| | | |
| | | /** |
| | | Get items value with an array of keys. |
| | | |
| | | @param keys An array of specified keys. |
| | | @return A dictionary which key is 'key' and value is 'value', or nil if not |
| | | exists / error occurs. |
| | | */ |
| | | - (nullable NSDictionary<NSString *, NSData *> *)getItemValueForKeys:(NSArray<NSString *> *)keys; |
| | | |
| | | #pragma mark - Get Storage Status |
| | | ///============================================================================= |
| | | /// @name Get Storage Status |
| | | ///============================================================================= |
| | | |
| | | /** |
| | | Whether an item exists for a specified key. |
| | | |
| | | @param key A specified key. |
| | | |
| | | @return `YES` if there's an item exists for the key, `NO` if not exists or an error occurs. |
| | | */ |
| | | - (BOOL)itemExistsForKey:(NSString *)key; |
| | | |
| | | /** |
| | | Get total item count. |
| | | @return Total item count, -1 when an error occurs. |
| | | */ |
| | | - (int)getItemsCount; |
| | | |
| | | /** |
| | | Get item value's total size in bytes. |
| | | @return Total size in bytes, -1 when an error occurs. |
| | | */ |
| | | - (int)getItemsSize; |
| | | |
| | | @end |
| | | |
| | | NS_ASSUME_NONNULL_END |