diff --git a/src/MTXClient.m b/src/MTXClient.m index 08907d5..256021d 100644 --- a/src/MTXClient.m +++ b/src/MTXClient.m @@ -219,6 +219,20 @@ validateHomeserver(OFURL *homeserver) return; } + OFString *nextBatch = response[@"next_batch"]; + if (![nextBatch isKindOfClass: OFString.class]) { + block([OFInvalidServerReplyException exception]); + return; + } + + @try { + [_storage setNextBatch: nextBatch + forDeviceID: _deviceID]; + } @catch (id e) { + block(e); + return; + } + block(nil); }]; diff --git a/src/MTXSQLite3Storage.m b/src/MTXSQLite3Storage.m index 46bfb6b..fd508d8 100644 --- a/src/MTXSQLite3Storage.m +++ b/src/MTXSQLite3Storage.m @@ -27,6 +27,7 @@ @implementation MTXSQLite3Storage { SL3Connection *_conn; + SL3PreparedStatement *_nextBatchSetStatement, *_nextBatchGetStatement; } + (instancetype)storageWithPath: (OFString *)path @@ -39,7 +40,23 @@ self = [super init]; @try { + void *pool = objc_autoreleasePoolPush(); + _conn = [[SL3Connection alloc] initWithPath: path]; + + [self createTables]; + + _nextBatchSetStatement = [[_conn prepareStatement: + @"INSERT OR REPLACE INTO next_batch (\n" + @" device_id, next_batch\n" + @") VALUES (\n" + @" $device_id, $next_batch\n" + @")"] retain]; + _nextBatchGetStatement = [[_conn prepareStatement: + @"SELECT next_batch FROM next_batch\n" + @"WHERE device_id=$device_id"] retain]; + + objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; @@ -50,8 +67,53 @@ - (void)dealloc { + [_nextBatchSetStatement release]; + [_nextBatchGetStatement release]; [_conn release]; [super dealloc]; } + +- (void)createTables +{ + [_conn executeStatement: @"CREATE TABLE IF NOT EXISTS next_batch (\n" + @" device_id TEXT PRIMARY KEY,\n" + @" next_batch TEXT\n" + @")"]; +} + +- (void)setNextBatch: (OFString *)nextBatch + forDeviceID: (OFString *)deviceID +{ + void *pool = objc_autoreleasePoolPush(); + + [_nextBatchSetStatement reset]; + [_nextBatchSetStatement bindWithDictionary: @{ + @"$device_id": deviceID, + @"$next_batch": nextBatch + }]; + [_nextBatchSetStatement step]; + + objc_autoreleasePoolPop(pool); +} + +- (OFString *)nextBatchForDeviceID: (OFString *)deviceID +{ + void *pool = objc_autoreleasePoolPush(); + + [_nextBatchGetStatement reset]; + [_nextBatchGetStatement bindWithDictionary: @{ + @"$device_id": deviceID + }]; + + if (![_nextBatchGetStatement step]) + return nil; + + OFString *nextBatch = + [[_nextBatchGetStatement rowDictionary][@"next_batch"] retain]; + + objc_autoreleasePoolPop(pool); + + return [nextBatch autorelease]; +} @end diff --git a/src/MTXStorage.h b/src/MTXStorage.h index 17a99c3..f2d2a5c 100644 --- a/src/MTXStorage.h +++ b/src/MTXStorage.h @@ -28,6 +28,23 @@ OF_ASSUME_NONNULL_BEGIN * @brief A protocol for a storage to be used by @ref MTXClient. */ @protocol MTXStorage +/** + * @brief Stores the next batch for the specified device. + * + * @param nextBatch The next batch for the device + * @param deviceID The device for which to store the next batch + */ +- (void)setNextBatch: (OFString *)nextBatch + forDeviceID: (OFString *)deviceID; + +/** + * @brief Returns the next batch for the specified device. + * + * @param deviceID The device ID for which to return the next batch + * @return The next batch for the specified device, or `nil` if none is + * available. + */ +- (nullable OFString *)nextBatchForDeviceID: (OFString *)deviceID; @end OF_ASSUME_NONNULL_END