Skip to content

Commit

Permalink
MXFileStore: Be more robust on commit interruption: Introduce the com…
Browse files Browse the repository at this point in the history
  • Loading branch information
manuroe committed Aug 12, 2016
1 parent 6b429e5 commit b454673
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 31 deletions.
12 changes: 10 additions & 2 deletions MatrixSDK/Data/Store/MXFileStore/MXFileStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,25 @@
+ MXFileStore
+ Matrix user id (one folder per account)
+ rooms
+ roomId1
+ {roomId1}
L messages: The room messages
L state: The room state events
L accountData: The account data for this room
L receipts: The read receipts for this room
+ roomId2
+ {roomId2}
L messages
L state
L accountData
L receipts
+ ...
+ roomsBackup: This folder contains backup of room files that are modified
during the commit process. It is flushed when the commit completes.
This allows to rollback to previous data if the commit process was
interrupted.
+ {syncToken} : the token that corresponds to the backup data
+ {roomIdA}
+ {roomIdB}
+ ...
L MXFileStore : Information about the stored data
*/
@interface MXFileStore : MXMemoryStore
Expand Down
68 changes: 39 additions & 29 deletions MatrixSDK/Data/Store/MXFileStore/MXFileStore.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
NSString *const kMXFileStoreSavingMarker = @"savingMarker";

NSString *const kMXFileStoreRoomsFolder = @"rooms";
NSString *const kMXFileStoreRoomsBackupFolder = @"roomsBackup";
NSString *const kMXFileStoreRoomMessagesFile = @"messages";
NSString *const kMXFileStoreRoomStateFile = @"state";
NSString *const kMXFileStoreRoomAccountDataFile = @"accountData";
Expand Down Expand Up @@ -57,6 +58,9 @@ @interface MXFileStore ()
// The path of the rooms folder
NSString *storeRoomsPath;

// The path of the rooms backup folder
NSString *storeRoomsBackupPath;

// Flag to indicate metaData needs to be store
BOOL metaDataHasChanged;

Expand Down Expand Up @@ -107,6 +111,7 @@ - (void)openWithCredentials:(MXCredentials*)someCredentials onComplete:(void (^)
storePath = [[cachePath stringByAppendingPathComponent:kMXFileStoreFolder] stringByAppendingPathComponent:credentials.userId];
savingMarkerFile = [storePath stringByAppendingPathComponent:kMXFileStoreSavingMarker];
storeRoomsPath = [storePath stringByAppendingPathComponent:kMXFileStoreRoomsFolder];
storeRoomsBackupPath = [storePath stringByAppendingPathComponent:kMXFileStoreRoomsBackupFolder];

/*
Mount data corresponding to the account credentials.
Expand Down Expand Up @@ -233,10 +238,10 @@ - (void)deleteAllMessagesInRoom:(NSString *)roomId
NSError *error;

// Remove room messages and read receipts from file system. Keep room state
[[NSFileManager defaultManager] removeItemAtPath:[self messagesFileForRoom:roomId] error:&error];
[[NSFileManager defaultManager] removeItemAtPath:[self messagesFileForRoom:roomId forBackup:NO] error:&error];

// Remove Read receipts
[[NSFileManager defaultManager] removeItemAtPath:[self readReceiptsFileForRoom:roomId] error:&error];
[[NSFileManager defaultManager] removeItemAtPath:[self readReceiptsFileForRoom:roomId forBackup:NO] error:&error];

if (NSNotFound == [roomsToCommitForMessages indexOfObject:roomId])
{
Expand All @@ -248,10 +253,8 @@ - (void)deleteRoom:(NSString *)roomId
{
[super deleteRoom:roomId];

NSError *error;

// Remove the room folder from file system
[[NSFileManager defaultManager] removeItemAtPath:[self folderForRoom:roomId] error:&error];
[[NSFileManager defaultManager] removeItemAtPath:[self folderForRoom:roomId forBackup:NO] error:nil];
}

- (void)deleteAllData
Expand Down Expand Up @@ -356,7 +359,7 @@ - (NSArray*)stateOfRoom:(NSString *)roomId

if (!stateEvents)
{
stateEvents =[NSKeyedUnarchiver unarchiveObjectWithFile:[self stateFileForRoom:roomId]];
stateEvents =[NSKeyedUnarchiver unarchiveObjectWithFile:[self stateFileForRoom:roomId forBackup:NO]];

if (NO == [NSThread isMainThread])
{
Expand Down Expand Up @@ -386,7 +389,7 @@ - (MXRoomAccountData *)accountDataOfRoom:(NSString *)roomId

if (!roomUserdData)
{
roomUserdData =[NSKeyedUnarchiver unarchiveObjectWithFile:[self accountDataFileForRoom:roomId]];
roomUserdData =[NSKeyedUnarchiver unarchiveObjectWithFile:[self accountDataFileForRoom:roomId forBackup:NO]];

if (NO == [NSThread isMainThread])
{
Expand Down Expand Up @@ -497,38 +500,45 @@ - (MXMemoryRoomStore*)getOrCreateRoomStore:(NSString*)roomId


#pragma mark - Private methods
- (NSString*)folderForRoom:(NSString*)roomId
- (NSString*)folderForRoom:(NSString*)roomId forBackup:(BOOL)backup
{
return [storeRoomsPath stringByAppendingPathComponent:roomId];
if (!backup)
{
return [storeRoomsPath stringByAppendingPathComponent:roomId];
}
else
{
return [[storeRoomsBackupPath stringByAppendingPathComponent:self.eventStreamToken] stringByAppendingPathComponent:roomId];
}
}

- (void)checkFolderExistenceForRoom:(NSString*)roomId
- (void)checkFolderExistenceForRoom:(NSString*)roomId forBackup:(BOOL)backup
{
NSString *roomFolder = [self folderForRoom:roomId];
NSString *roomFolder = [self folderForRoom:roomId forBackup:backup];
if (![NSFileManager.defaultManager fileExistsAtPath:roomFolder])
{
[[NSFileManager defaultManager] createDirectoryAtPath:roomFolder withIntermediateDirectories:YES attributes:nil error:nil];
}
}

- (NSString*)messagesFileForRoom:(NSString*)roomId
- (NSString*)messagesFileForRoom:(NSString*)roomId forBackup:(BOOL)backup
{
return [[storeRoomsPath stringByAppendingPathComponent:roomId] stringByAppendingPathComponent:kMXFileStoreRoomMessagesFile];
return [[self folderForRoom:roomId forBackup:backup] stringByAppendingPathComponent:kMXFileStoreRoomMessagesFile];
}

- (NSString*)stateFileForRoom:(NSString*)roomId
- (NSString*)stateFileForRoom:(NSString*)roomId forBackup:(BOOL)backup
{
return [[storeRoomsPath stringByAppendingPathComponent:roomId] stringByAppendingPathComponent:kMXFileStoreRoomStateFile];
return [[self folderForRoom:roomId forBackup:backup] stringByAppendingPathComponent:kMXFileStoreRoomStateFile];
}

- (NSString*)accountDataFileForRoom:(NSString*)roomId
- (NSString*)accountDataFileForRoom:(NSString*)roomId forBackup:(BOOL)backup
{
return [[storeRoomsPath stringByAppendingPathComponent:roomId] stringByAppendingPathComponent:kMXFileStoreRoomAccountDataFile];
return [[self folderForRoom:roomId forBackup:backup] stringByAppendingPathComponent:kMXFileStoreRoomAccountDataFile];
}

- (NSString*)readReceiptsFileForRoom:(NSString*)roomId
- (NSString*)readReceiptsFileForRoom:(NSString*)roomId forBackup:(BOOL)backup
{
return [[storeRoomsPath stringByAppendingPathComponent:roomId] stringByAppendingPathComponent:kMXFileStoreRoomReadReceiptsFile];
return [[self folderForRoom:roomId forBackup:backup] stringByAppendingPathComponent:kMXFileStoreRoomReadReceiptsFile];
}


Expand Down Expand Up @@ -558,7 +568,7 @@ - (void)loadRoomsMessages

for (NSString *roomId in roomIDArray) {

NSString *roomFile = [self messagesFileForRoom:roomId];
NSString *roomFile = [self messagesFileForRoom:roomId forBackup:NO];

MXFileRoomStore *roomStore;
@try
Expand Down Expand Up @@ -605,8 +615,8 @@ - (void)saveRoomsMessages
MXFileRoomStore *roomStore = roomStores[roomId];
if (roomStore)
{
[self checkFolderExistenceForRoom:roomId];
[NSKeyedArchiver archiveRootObject:roomStore toFile:[self messagesFileForRoom:roomId]];
[self checkFolderExistenceForRoom:roomId forBackup:NO];
[NSKeyedArchiver archiveRootObject:roomStore toFile:[self messagesFileForRoom:roomId forBackup:NO]];
}
}

Expand Down Expand Up @@ -648,8 +658,8 @@ - (void)saveRoomsState
{
NSArray *stateEvents = roomsToCommit[roomId];

[self checkFolderExistenceForRoom:roomId];
[NSKeyedArchiver archiveRootObject:stateEvents toFile:[self stateFileForRoom:roomId]];
[self checkFolderExistenceForRoom:roomId forBackup:NO];
[NSKeyedArchiver archiveRootObject:stateEvents toFile:[self stateFileForRoom:roomId forBackup:NO]];
}
});
}
Expand Down Expand Up @@ -688,8 +698,8 @@ - (void)saveRoomsAccountData
{
MXRoomAccountData *roomAccountData = roomsToCommit[roomId];

[self checkFolderExistenceForRoom:roomId];
[NSKeyedArchiver archiveRootObject:roomAccountData toFile:[self accountDataFileForRoom:roomId]];
[self checkFolderExistenceForRoom:roomId forBackup:NO];
[NSKeyedArchiver archiveRootObject:roomAccountData toFile:[self accountDataFileForRoom:roomId forBackup:NO]];
}
});
}
Expand Down Expand Up @@ -821,7 +831,7 @@ - (void)loadReceipts
{
for (NSString *roomId in roomIDArray)
{
NSString *roomFile = [self readReceiptsFileForRoom:roomId];
NSString *roomFile = [self readReceiptsFileForRoom:roomId forBackup:NO];

NSMutableDictionary *receiptsDict = NULL;
@try
Expand Down Expand Up @@ -868,8 +878,8 @@ - (void)saveReceipts
{
@synchronized (receiptsByUserId)
{
[self checkFolderExistenceForRoom:roomId];
BOOL success = [NSKeyedArchiver archiveRootObject:receiptsByUserId toFile:[self readReceiptsFileForRoom:roomId]];
[self checkFolderExistenceForRoom:roomId forBackup:NO];
BOOL success = [NSKeyedArchiver archiveRootObject:receiptsByUserId toFile:[self readReceiptsFileForRoom:roomId forBackup:NO]];
if (!success)
{
NSLog(@"[MXFileStore] Error: Failed to store read receipts for room %@", roomId);
Expand Down

0 comments on commit b454673

Please sign in to comment.