YYKVStorage.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. //
  2. // YYKVStorage.h
  3. // YYKit <https://github.com/ibireme/YYKit>
  4. //
  5. // Created by ibireme on 15/4/22.
  6. // Copyright (c) 2015 ibireme.
  7. //
  8. // This source code is licensed under the MIT-style license found in the
  9. // LICENSE file in the root directory of this source tree.
  10. //
  11. #import <Foundation/Foundation.h>
  12. NS_ASSUME_NONNULL_BEGIN
  13. /**
  14. YYKVStorageItem is used by `YYKVStorage` to store key-value pair and meta data.
  15. Typically, you should not use this class directly.
  16. */
  17. @interface YYKVStorageItem : NSObject
  18. @property (nonatomic, strong) NSString *key; ///< key
  19. @property (nonatomic, strong) NSData *value; ///< value
  20. @property (nullable, nonatomic, strong) NSString *filename; ///< filename (nil if inline)
  21. @property (nonatomic) int size; ///< value's size in bytes
  22. @property (nonatomic) int modTime; ///< modification unix timestamp
  23. @property (nonatomic) int accessTime; ///< last access unix timestamp
  24. @property (nullable, nonatomic, strong) NSData *extendedData; ///< extended data (nil if no extended data)
  25. @end
  26. /**
  27. Storage type, indicated where the `YYKVStorageItem.value` stored.
  28. @discussion Typically, write data to sqlite is faster than extern file, but
  29. reading performance is dependent on data size. In my test (on iPhone 6 64G),
  30. read data from extern file is faster than from sqlite when the data is larger
  31. than 20KB.
  32. * If you want to store large number of small datas (such as contacts cache),
  33. use YYKVStorageTypeSQLite to get better performance.
  34. * If you want to store large files (such as image cache),
  35. use YYKVStorageTypeFile to get better performance.
  36. * You can use YYKVStorageTypeMixed and choice your storage type for each item.
  37. See <http://www.sqlite.org/intern-v-extern-blob.html> for more information.
  38. */
  39. typedef NS_ENUM(NSUInteger, YYKVStorageType) {
  40. /// The `value` is stored as a file in file system.
  41. YYKVStorageTypeFile = 0,
  42. /// The `value` is stored in sqlite with blob type.
  43. YYKVStorageTypeSQLite = 1,
  44. /// The `value` is stored in file system or sqlite based on your choice.
  45. YYKVStorageTypeMixed = 2,
  46. };
  47. /**
  48. YYKVStorage is a key-value storage based on sqlite and file system.
  49. Typically, you should not use this class directly.
  50. @discussion The designated initializer for YYKVStorage is `initWithPath:type:`.
  51. After initialized, a directory is created based on the `path` to hold key-value data.
  52. Once initialized you should not read or write this directory without the instance.
  53. You may compile the latest version of sqlite and ignore the libsqlite3.dylib in
  54. iOS system to get 2x~4x speed up.
  55. @warning The instance of this class is *NOT* thread safe, you need to make sure
  56. that there's only one thread to access the instance at the same time. If you really
  57. need to process large amounts of data in multi-thread, you should split the data
  58. to multiple KVStorage instance (sharding).
  59. */
  60. @interface YYKVStorage : NSObject
  61. #pragma mark - Attribute
  62. ///=============================================================================
  63. /// @name Attribute
  64. ///=============================================================================
  65. @property (nonatomic, readonly) NSString *path; ///< The path of this storage.
  66. @property (nonatomic, readonly) YYKVStorageType type; ///< The type of this storage.
  67. @property (nonatomic) BOOL errorLogsEnabled; ///< Set `YES` to enable error logs for debug.
  68. #pragma mark - Initializer
  69. ///=============================================================================
  70. /// @name Initializer
  71. ///=============================================================================
  72. - (instancetype)init UNAVAILABLE_ATTRIBUTE;
  73. + (instancetype)new UNAVAILABLE_ATTRIBUTE;
  74. /**
  75. The designated initializer.
  76. @param path Full path of a directory in which the storage will write data. If
  77. the directory is not exists, it will try to create one, otherwise it will
  78. read the data in this directory.
  79. @param type The storage type. After first initialized you should not change the
  80. type of the specified path.
  81. @return A new storage object, or nil if an error occurs.
  82. @warning Multiple instances with the same path will make the storage unstable.
  83. */
  84. - (nullable instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type NS_DESIGNATED_INITIALIZER;
  85. #pragma mark - Save Items
  86. ///=============================================================================
  87. /// @name Save Items
  88. ///=============================================================================
  89. /**
  90. Save an item or update the item with 'key' if it already exists.
  91. @discussion This method will save the item.key, item.value, item.filename and
  92. item.extendedData to disk or sqlite, other properties will be ignored. item.key
  93. and item.value should not be empty (nil or zero length).
  94. If the `type` is YYKVStorageTypeFile, then the item.filename should not be empty.
  95. If the `type` is YYKVStorageTypeSQLite, then the item.filename will be ignored.
  96. It the `type` is YYKVStorageTypeMixed, then the item.value will be saved to file
  97. system if the item.filename is not empty, otherwise it will be saved to sqlite.
  98. @param item An item.
  99. @return Whether succeed.
  100. */
  101. - (BOOL)saveItem:(YYKVStorageItem *)item;
  102. /**
  103. Save an item or update the item with 'key' if it already exists.
  104. @discussion This method will save the key-value pair to sqlite. If the `type` is
  105. YYKVStorageTypeFile, then this method will failed.
  106. @param key The key, should not be empty (nil or zero length).
  107. @param value The key, should not be empty (nil or zero length).
  108. @return Whether succeed.
  109. */
  110. - (BOOL)saveItemWithKey:(NSString *)key value:(NSData *)value;
  111. /**
  112. Save an item or update the item with 'key' if it already exists.
  113. @discussion
  114. If the `type` is YYKVStorageTypeFile, then the `filename` should not be empty.
  115. If the `type` is YYKVStorageTypeSQLite, then the `filename` will be ignored.
  116. It the `type` is YYKVStorageTypeMixed, then the `value` will be saved to file
  117. system if the `filename` is not empty, otherwise it will be saved to sqlite.
  118. @param key The key, should not be empty (nil or zero length).
  119. @param value The key, should not be empty (nil or zero length).
  120. @param filename The filename.
  121. @param extendedData The extended data for this item (pass nil to ignore it).
  122. @return Whether succeed.
  123. */
  124. - (BOOL)saveItemWithKey:(NSString *)key
  125. value:(NSData *)value
  126. filename:(nullable NSString *)filename
  127. extendedData:(nullable NSData *)extendedData;
  128. #pragma mark - Remove Items
  129. ///=============================================================================
  130. /// @name Remove Items
  131. ///=============================================================================
  132. /**
  133. Remove an item with 'key'.
  134. @param key The item's key.
  135. @return Whether succeed.
  136. */
  137. - (BOOL)removeItemForKey:(NSString *)key;
  138. /**
  139. Remove items with an array of keys.
  140. @param keys An array of specified keys.
  141. @return Whether succeed.
  142. */
  143. - (BOOL)removeItemForKeys:(NSArray<NSString *> *)keys;
  144. /**
  145. Remove all items which `value` is larger than a specified size.
  146. @param size The maximum size in bytes.
  147. @return Whether succeed.
  148. */
  149. - (BOOL)removeItemsLargerThanSize:(int)size;
  150. /**
  151. Remove all items which last access time is earlier than a specified timestamp.
  152. @param time The specified unix timestamp.
  153. @return Whether succeed.
  154. */
  155. - (BOOL)removeItemsEarlierThanTime:(int)time;
  156. /**
  157. Remove items to make the total size not larger than a specified size.
  158. The least recently used (LRU) items will be removed first.
  159. @param maxSize The specified size in bytes.
  160. @return Whether succeed.
  161. */
  162. - (BOOL)removeItemsToFitSize:(int)maxSize;
  163. /**
  164. Remove items to make the total count not larger than a specified count.
  165. The least recently used (LRU) items will be removed first.
  166. @param maxCount The specified item count.
  167. @return Whether succeed.
  168. */
  169. - (BOOL)removeItemsToFitCount:(int)maxCount;
  170. /**
  171. Remove all items in background queue.
  172. @discussion This method will remove the files and sqlite database to a trash
  173. folder, and then clear the folder in background queue. So this method is much
  174. faster than `removeAllItemsWithProgressBlock:endBlock:`.
  175. @return Whether succeed.
  176. */
  177. - (BOOL)removeAllItems;
  178. /**
  179. Remove all items.
  180. @warning You should not send message to this instance in these blocks.
  181. @param progress This block will be invoked during removing, pass nil to ignore.
  182. @param end This block will be invoked at the end, pass nil to ignore.
  183. */
  184. - (void)removeAllItemsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress
  185. endBlock:(nullable void(^)(BOOL error))end;
  186. #pragma mark - Get Items
  187. ///=============================================================================
  188. /// @name Get Items
  189. ///=============================================================================
  190. /**
  191. Get item with a specified key.
  192. @param key A specified key.
  193. @return Item for the key, or nil if not exists / error occurs.
  194. */
  195. - (nullable YYKVStorageItem *)getItemForKey:(NSString *)key;
  196. /**
  197. Get item information with a specified key.
  198. The `value` in this item will be ignored.
  199. @param key A specified key.
  200. @return Item information for the key, or nil if not exists / error occurs.
  201. */
  202. - (nullable YYKVStorageItem *)getItemInfoForKey:(NSString *)key;
  203. /**
  204. Get item value with a specified key.
  205. @param key A specified key.
  206. @return Item's value, or nil if not exists / error occurs.
  207. */
  208. - (nullable NSData *)getItemValueForKey:(NSString *)key;
  209. /**
  210. Get items with an array of keys.
  211. @param keys An array of specified keys.
  212. @return An array of `YYKVStorageItem`, or nil if not exists / error occurs.
  213. */
  214. - (nullable NSArray<YYKVStorageItem *> *)getItemForKeys:(NSArray<NSString *> *)keys;
  215. /**
  216. Get item infomartions with an array of keys.
  217. The `value` in items will be ignored.
  218. @param keys An array of specified keys.
  219. @return An array of `YYKVStorageItem`, or nil if not exists / error occurs.
  220. */
  221. - (nullable NSArray<YYKVStorageItem *> *)getItemInfoForKeys:(NSArray<NSString *> *)keys;
  222. /**
  223. Get items value with an array of keys.
  224. @param keys An array of specified keys.
  225. @return A dictionary which key is 'key' and value is 'value', or nil if not
  226. exists / error occurs.
  227. */
  228. - (nullable NSDictionary<NSString *, NSData *> *)getItemValueForKeys:(NSArray<NSString *> *)keys;
  229. #pragma mark - Get Storage Status
  230. ///=============================================================================
  231. /// @name Get Storage Status
  232. ///=============================================================================
  233. /**
  234. Whether an item exists for a specified key.
  235. @param key A specified key.
  236. @return `YES` if there's an item exists for the key, `NO` if not exists or an error occurs.
  237. */
  238. - (BOOL)itemExistsForKey:(NSString *)key;
  239. /**
  240. Get total item count.
  241. @return Total item count, -1 when an error occurs.
  242. */
  243. - (int)getItemsCount;
  244. /**
  245. Get item value's total size in bytes.
  246. @return Total size in bytes, -1 when an error occurs.
  247. */
  248. - (int)getItemsSize;
  249. @end
  250. NS_ASSUME_NONNULL_END