diff --git a/MQTTClient/MQTTClient/MQTTCoreDataPersistence.m b/MQTTClient/MQTTClient/MQTTCoreDataPersistence.m index 4206e954..cfc7d7f3 100755 --- a/MQTTClient/MQTTClient/MQTTCoreDataPersistence.m +++ b/MQTTClient/MQTTClient/MQTTCoreDataPersistence.m @@ -53,111 +53,187 @@ - (MQTTCoreDataFlow *)initWithContext:(NSManagedObjectContext *)c andObject:(id< - (NSString *)clientId { __block NSString *_clientId; - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { _clientId = object.clientId; - }]; + } else { + [context performBlockAndWait:^{ + _clientId = object.clientId; + }]; + } return _clientId; } - (void)setClientId:(NSString *)clientId { - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { object.clientId = clientId; - }]; + } else { + + [context performBlockAndWait:^{ + object.clientId = clientId; + }]; + } } - (NSNumber *)incomingFlag { __block NSNumber *_incomingFlag; - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { _incomingFlag = object.incomingFlag; - }]; + } else { + [context performBlockAndWait:^{ + _incomingFlag = object.incomingFlag; + }]; + } return _incomingFlag; } - (void)setIncomingFlag:(NSNumber *)incomingFlag { - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { object.incomingFlag = incomingFlag; - }]; + } else { + + [context performBlockAndWait:^{ + object.incomingFlag = incomingFlag; + }]; + } } - (NSNumber *)retainedFlag { __block NSNumber *_retainedFlag; - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { _retainedFlag = object.retainedFlag; - }]; + } else { + [context performBlockAndWait:^{ + _retainedFlag = object.retainedFlag; + }]; + } return _retainedFlag; } - (void)setRetainedFlag:(NSNumber *)retainedFlag { - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { object.retainedFlag = retainedFlag; - }]; + } else { + + [context performBlockAndWait:^{ + object.retainedFlag = retainedFlag; + }]; + } } - (NSNumber *)commandType { __block NSNumber *_commandType; - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { _commandType = object.commandType; - }]; + } else { + [context performBlockAndWait:^{ + _commandType = object.commandType; + }]; + } return _commandType; } - (void)setCommandType:(NSNumber *)commandType { - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { object.commandType = commandType; - }]; + } else { + + [context performBlockAndWait:^{ + object.commandType = commandType; + }]; + } } - (NSNumber *)qosLevel { __block NSNumber *_qosLevel; - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { _qosLevel = object.qosLevel; - }]; + } else { + [context performBlockAndWait:^{ + _qosLevel = object.qosLevel; + }]; + } return _qosLevel; } - (void)setQosLevel:(NSNumber *)qosLevel { - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { object.qosLevel = qosLevel; - }]; + } else { + [context performBlockAndWait:^{ + object.qosLevel = qosLevel; + }]; + } } - (NSNumber *)messageId { __block NSNumber *_messageId; - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { _messageId = object.messageId; - }]; + } else { + [context performBlockAndWait:^{ + _messageId = object.messageId; + }]; + } return _messageId; } - (void)setMessageId:(NSNumber *)messageId { - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { object.messageId = messageId; - }]; + } else { + [context performBlockAndWait:^{ + object.messageId = messageId; + }]; + } } - (NSString *)topic { __block NSString *_topic; - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { _topic = object.topic; - }]; + } else { + [context performBlockAndWait:^{ + _topic = object.topic; + }]; + } return _topic; } - (void)setTopic:(NSString *)topic { - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { object.topic = topic; - }]; + } else { + [context performBlockAndWait:^{ + object.topic = topic; + }]; + } } - (NSData *)data { __block NSData *_data; - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { _data = object.data; - }]; + } else { + [context performBlockAndWait:^{ + _data = object.data; + }]; + } return _data; } - (void)setData:(NSData *)data { - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { object.data = data; - }]; + } else { + [context performBlockAndWait:^{ + object.data = data; + }]; + } } - (NSDate *)deadline { __block NSDate *_deadline; - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { _deadline = object.deadline; - }]; + } else { + [context performBlockAndWait:^{ + _deadline = object.deadline; + }]; + } return _deadline; } - (void)setDeadline:(NSDate *)deadline { - [context performBlockAndWait:^{ + if ([NSThread isMainThread]) { object.deadline = deadline; - }]; + } else { + [context performBlockAndWait:^{ + object.deadline = deadline; + }]; + } } @end @@ -205,7 +281,7 @@ - (MQTTCoreDataFlow *)storeMessageForClientId:(NSString *)clientId (fileSize <= self.maxSize)) { MQTTCoreDataFlow *flow = [self createFlowforClientId:clientId incomingFlag:incomingFlag - messageId:msgId]; + messageId:msgId]; flow.topic = topic; flow.data = data; flow.retainedFlag = [NSNumber numberWithBool:retainFlag]; @@ -219,22 +295,35 @@ - (MQTTCoreDataFlow *)storeMessageForClientId:(NSString *)clientId } - (void)deleteFlow:(MQTTCoreDataFlow *)flow { - [self.managedObjectContext performBlockAndWait:^{ + if ([NSThread isMainThread]) { [self.managedObjectContext deleteObject:(NSManagedObject *)flow.object]; - [self sync]; - }]; + } else { + [self.managedObjectContext performBlockAndWait:^{ + [self.managedObjectContext deleteObject:(NSManagedObject *)flow.object]; + }]; + } + [self sync]; } - (void)deleteAllFlowsForClientId:(NSString *)clientId { - [self.managedObjectContext performBlockAndWait:^{ + if ([NSThread isMainThread]) { for (MQTTCoreDataFlow *flow in [self allFlowsforClientId:clientId incomingFlag:TRUE]) { [self.managedObjectContext deleteObject:(NSManagedObject *)flow.object]; } for (MQTTCoreDataFlow *flow in [self allFlowsforClientId:clientId incomingFlag:FALSE]) { [self.managedObjectContext deleteObject:(NSManagedObject *)flow.object]; } - [self sync]; - }]; + } else { + [self.managedObjectContext performBlockAndWait:^{ + for (MQTTCoreDataFlow *flow in [self allFlowsforClientId:clientId incomingFlag:TRUE]) { + [self.managedObjectContext deleteObject:(NSManagedObject *)flow.object]; + } + for (MQTTCoreDataFlow *flow in [self allFlowsforClientId:clientId incomingFlag:FALSE]) { + [self.managedObjectContext deleteObject:(NSManagedObject *)flow.object]; + } + }]; + } + [self sync]; } - (void)sync { @@ -290,8 +379,7 @@ - (NSArray *)allFlowsforClientId:(NSString *)clientId incomingFlag:(BOOL)incomingFlag { NSMutableArray *flows = [NSMutableArray array]; __block NSArray *rows; - [self.managedObjectContext performBlockAndWait:^{ - + if ([NSThread isMainThread]) { NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"MQTTFlow"]; fetchRequest.predicate = [NSPredicate predicateWithFormat: @"clientId = %@ and incomingFlag = %@", @@ -304,7 +392,23 @@ - (NSArray *)allFlowsforClientId:(NSString *)clientId if (!rows) { DDLogError(@"[MQTTPersistence] allFlowsforClientId %@", error); } - }]; + } else { + [self.managedObjectContext performBlockAndWait:^{ + + NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"MQTTFlow"]; + fetchRequest.predicate = [NSPredicate predicateWithFormat: + @"clientId = %@ and incomingFlag = %@", + clientId, + @(incomingFlag) + ]; + fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"deadline" ascending:YES]]; + NSError *error = nil; + rows = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; + if (!rows) { + DDLogError(@"[MQTTPersistence] allFlowsforClientId %@", error); + } + }]; + } for (idrow in rows) { [flows addObject:[[MQTTCoreDataFlow alloc] initWithContext:self.managedObjectContext andObject:row]]; } @@ -315,30 +419,47 @@ - (MQTTCoreDataFlow *)flowforClientId:(NSString *)clientId incomingFlag:(BOOL)incomingFlag messageId:(UInt16)messageId { __block MQTTCoreDataFlow *flow = nil; - + DDLogVerbose(@"flowforClientId requestingPerform"); - [self.managedObjectContext performBlockAndWait:^{ - DDLogVerbose(@"flowforClientId performing"); + if ([NSThread isMainThread]) { + flow = [self internalFlowForClientId:clientId + incomingFlag:incomingFlag + messageId:messageId]; + } else { + [self.managedObjectContext performBlockAndWait:^{ + flow = [self internalFlowForClientId:clientId + incomingFlag:incomingFlag + messageId:messageId]; + }]; + } + DDLogVerbose(@"flowforClientId performed"); + return flow; +} - NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"MQTTFlow"]; - fetchRequest.predicate = [NSPredicate predicateWithFormat: - @"clientId = %@ and incomingFlag = %@ and messageId = %@", - clientId, - @(incomingFlag), - @(messageId) - ]; - NSArray *rows; - NSError *error = nil; - rows = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; - if (!rows) { - DDLogError(@"[MQTTPersistence] flowForClientId %@", error); - } else { - if ([rows count]) { - flow = [[MQTTCoreDataFlow alloc] initWithContext:self.managedObjectContext andObject:[rows lastObject]]; - } +- (MQTTCoreDataFlow *)internalFlowForClientId:(NSString *)clientId + incomingFlag:(BOOL)incomingFlag + messageId:(UInt16)messageId { + MQTTCoreDataFlow *flow = nil; + + DDLogVerbose(@"flowforClientId performing"); + + NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"MQTTFlow"]; + fetchRequest.predicate = [NSPredicate predicateWithFormat: + @"clientId = %@ and incomingFlag = %@ and messageId = %@", + clientId, + @(incomingFlag), + @(messageId) + ]; + NSArray *rows; + NSError *error = nil; + rows = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error]; + if (!rows) { + DDLogError(@"[MQTTPersistence] flowForClientId %@", error); + } else { + if ([rows count]) { + flow = [[MQTTCoreDataFlow alloc] initWithContext:self.managedObjectContext andObject:[rows lastObject]]; } - }]; - DDLogVerbose(@"flowforClientId performed"); + } return flow; } @@ -350,17 +471,26 @@ - (MQTTCoreDataFlow *)createFlowforClientId:(NSString *)clientId messageId:messageId]; if (!flow) { __block id row; - [self.managedObjectContext performBlockAndWait:^{ + if ([NSThread isMainThread]) { row = [NSEntityDescription insertNewObjectForEntityForName:@"MQTTFlow" inManagedObjectContext:self.managedObjectContext]; - + row.clientId = clientId; row.incomingFlag = @(incomingFlag); row.messageId = @(messageId); - }]; + } else { + [self.managedObjectContext performBlockAndWait:^{ + row = [NSEntityDescription insertNewObjectForEntityForName:@"MQTTFlow" + inManagedObjectContext:self.managedObjectContext]; + + row.clientId = clientId; + row.incomingFlag = @(incomingFlag); + row.messageId = @(messageId); + }]; + } flow = [[MQTTCoreDataFlow alloc] initWithContext:self.managedObjectContext andObject:row]; } - + return flow; } @@ -372,7 +502,7 @@ - (NSManagedObjectContext *)managedObjectContext if (managedObjectContext != nil) { return managedObjectContext; } - + @synchronized (lock) { if (parentManagedObjectContext == nil) { NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; @@ -381,11 +511,11 @@ - (NSManagedObjectContext *)managedObjectContext [parentManagedObjectContext setPersistentStoreCoordinator:coordinator]; } } - + managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [managedObjectContext setParentContext:parentManagedObjectContext]; [[NSThread currentThread].threadDictionary setObject:managedObjectContext forKey:@"MQTTClient"]; - + return managedObjectContext; } } @@ -396,76 +526,76 @@ - (NSManagedObjectModel *)managedObjectModel if (managedObjectModel != nil) { return managedObjectModel; } - + managedObjectModel = [[NSManagedObjectModel alloc] init]; NSMutableArray *entities = [[NSMutableArray alloc] init]; NSMutableArray *properties = [[NSMutableArray alloc] init]; - + NSAttributeDescription *attributeDescription; - + attributeDescription = [[NSAttributeDescription alloc] init]; attributeDescription.name = @"clientId"; attributeDescription.attributeType = NSStringAttributeType; attributeDescription.attributeValueClassName = @"NSString"; [properties addObject:attributeDescription]; - + attributeDescription = [[NSAttributeDescription alloc] init]; attributeDescription.name = @"incomingFlag"; attributeDescription.attributeType = NSBooleanAttributeType; attributeDescription.attributeValueClassName = @"NSNumber"; [properties addObject:attributeDescription]; - + attributeDescription = [[NSAttributeDescription alloc] init]; attributeDescription.name = @"retainedFlag"; attributeDescription.attributeType = NSBooleanAttributeType; attributeDescription.attributeValueClassName = @"NSNumber"; [properties addObject:attributeDescription]; - + attributeDescription = [[NSAttributeDescription alloc] init]; attributeDescription.name = @"commandType"; attributeDescription.attributeType = NSInteger16AttributeType; attributeDescription.attributeValueClassName = @"NSNumber"; [properties addObject:attributeDescription]; - + attributeDescription = [[NSAttributeDescription alloc] init]; attributeDescription.name = @"qosLevel"; attributeDescription.attributeType = NSInteger16AttributeType; attributeDescription.attributeValueClassName = @"NSNumber"; [properties addObject:attributeDescription]; - + attributeDescription = [[NSAttributeDescription alloc] init]; attributeDescription.name = @"messageId"; attributeDescription.attributeType = NSInteger32AttributeType; attributeDescription.attributeValueClassName = @"NSNumber"; [properties addObject:attributeDescription]; - + attributeDescription = [[NSAttributeDescription alloc] init]; attributeDescription.name = @"topic"; attributeDescription.attributeType = NSStringAttributeType; attributeDescription.attributeValueClassName = @"NSString"; [properties addObject:attributeDescription]; - + attributeDescription = [[NSAttributeDescription alloc] init]; attributeDescription.name = @"data"; attributeDescription.attributeType = NSBinaryDataAttributeType; attributeDescription.attributeValueClassName = @"NSData"; [properties addObject:attributeDescription]; - + attributeDescription = [[NSAttributeDescription alloc] init]; attributeDescription.name = @"deadline"; attributeDescription.attributeType = NSDateAttributeType; attributeDescription.attributeValueClassName = @"NSDate"; [properties addObject:attributeDescription]; - + NSEntityDescription *entityDescription = [[NSEntityDescription alloc] init]; entityDescription.name = @"MQTTFlow"; entityDescription.managedObjectClassName = @"MQTTFlow"; entityDescription.abstract = FALSE; entityDescription.properties = properties; - + [entities addObject:entityDescription]; [managedObjectModel setEntities:entities]; - + return managedObjectModel; } } @@ -476,12 +606,12 @@ - (NSPersistentStoreCoordinator *)persistentStoreCoordinator if (persistentStoreCoordinator != nil) { return persistentStoreCoordinator; } - + NSURL *persistentStoreURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MQTTClient"]; DDLogInfo(@"[MQTTPersistence] Persistent store: %@", persistentStoreURL.path); - - + + NSError *error = nil; persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; @@ -490,7 +620,7 @@ - (NSPersistentStoreCoordinator *)persistentStoreCoordinator NSSQLiteAnalyzeOption: @YES, NSSQLiteManualVacuumOption: @YES }; - + if (![persistentStoreCoordinator addPersistentStoreWithType:self.persistent ? NSSQLiteStoreType : NSInMemoryStoreType configuration:nil URL:self.persistent ? persistentStoreURL : nil @@ -499,7 +629,7 @@ - (NSPersistentStoreCoordinator *)persistentStoreCoordinator DDLogError(@"[MQTTPersistence] managedObjectContext save: %@", error); persistentStoreCoordinator = nil; } - + return persistentStoreCoordinator; } } @@ -516,7 +646,7 @@ - (void)sizes { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *persistentStorePath = [documentsDirectory stringByAppendingPathComponent:@"MQTTClient"]; - + NSError *error = nil; NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:persistentStorePath error:&error];