Re: Core Data conflict detection
Re: Core Data conflict detection
- Subject: Re: Core Data conflict detection
- From: Paulo Andrade <email@hidden>
- Date: Sun, 25 Jul 2010 17:54:09 +0100
- Resent-cc: cocoa-dev Mailinglist <email@hidden>
- Resent-date: Mon, 26 Jul 2010 10:53:50 +0100
- Resent-from: Paulo Andrade <email@hidden>
- Resent-message-id: <email@hidden>
- Resent-to: Miguel Arroz <email@hidden>
Hello,
I did a small test to verify that indeed an error occurred.
Here is the relevant part of the code:
// Create our two peer editing contexts
NSManagedObjectContext *moc1 = newManagedObjectContext();
NSManagedObjectContext *moc2 = newManagedObjectContext();
// Instantiate managed object on moc1
NSManagedObject *moc1Sequence = [moc1 objectWithID:objID];
NSNumber *moc1Value = [moc1Sequence valueForKey:COUNTER_ATTRIBUTE];
NSLog(@"Moc1 read sequence with value %@", moc1Value);
// Instantiate managed object on moc1
NSManagedObject *moc2Sequence = [moc2 objectWithID:objID];
NSNumber *moc2Value = [moc2Sequence valueForKey:COUNTER_ATTRIBUTE];
NSLog(@"Moc2 read sequence with value %@", moc2Value);
// Moc1 makes changes
[moc1Sequence setValue:[NSNumber numberWithInt:[moc1Value intValue] + 1]
forKey:COUNTER_ATTRIBUTE];
NSLog(@"Moc1 incremented sequence to value %@", [moc1Sequence valueForKey:COUNTER_ATTRIBUTE]);
// Moc2 makes changes
[moc2Sequence setValue:[NSNumber numberWithInt:[moc2Value intValue] + 1]
forKey:COUNTER_ATTRIBUTE];
NSLog(@"Moc2 incremented sequence to value %@", [moc2Sequence valueForKey:COUNTER_ATTRIBUTE]);
// Moc1 save
if (![moc1 save:&error]) {
NSLog(@"Error while saving Moc1\n%@",
([error localizedDescription] != nil) ? [error localizedDescription] : @"Unknown Error");
exit(1);
} else {
NSLog(@"Moc1 saved");
}
// Moc2 save
if (![moc2 save:&error]) {
NSLog(@"Error while saving Moc2\n%@",
([error localizedDescription] != nil) ? [error localizedDescription] : @"Unknown Error");
exit(1);
} else {
NSLog(@"Moc2 saved");
}
Running this for either the SQL store or the XML store outputs:
2010-07-25 17:42:35.643 CoreData Test[1103:a0f] Moc1 read sequence with value 0
2010-07-25 17:42:35.646 CoreData Test[1103:a0f] Moc2 read sequence with value 0
2010-07-25 17:42:35.647 CoreData Test[1103:a0f] Moc1 incremented sequence to value 1
2010-07-25 17:42:35.648 CoreData Test[1103:a0f] Moc2 incremented sequence to value 1
2010-07-25 17:42:35.653 CoreData Test[1103:a0f] Moc1 saved
2010-07-25 17:42:35.657 CoreData Test[1103:a0f] Error while saving Moc2
Could not merge changes.
Which is what was expected (and confirms that this indeed does not work like EOF). Than when I was reading what was in the error's user info I found this in the documentation for NSManagedObjectContext:
Each conflict record in the @"conflictList" array in the userInfo dictionary for an error from theNSErrorMergePolicy is a dictionary containing some of the keys described in the following table. Of the cachedRow, databaseRow, and snapshot keys, only two will be present depending on whether the conflict is between the managed object context and the persistent store coordinator (snapshot and cachedRow) or between the persistent store coordinator and the persistent store (cachedRow and databaseRow).
So it seems the snapshots are held at the managed object context level, and a cachedRow is held at the persistent store level. These two allow for conflict detection on every persistent store type (being it SQL or not). I'm guessing the databaseRow key will only ever be filled for the SQL store.
Printing the value of the conflictList on the example above:
conflictList: (
{
cachedRow = {
counter = 1;
};
newVersion = 2;
object = "<NSManagedObject: 0x200027760> (entity: Sequence; id: 0x2000228c0 <x-coredata://7F582366-0A93-49E1-8A9B-E00F032D6B0F/Sequence/p103> ; data: {\n counter = 1;\n})";
oldVersion = 1;
snapshot = {
counter = 0;
};
}
)
Feels like I'm guessing closer at understanding the Core Data stack :). I don't like it when it feels like magic.
Regards,
Paulo Andrade
On Jul 21, 2010, at 4:41 PM, Miguel Arroz wrote:
> Hi!
>
> On 2010/07/19, at 14:04, Paulo Andrade wrote:
>
>> You have two threads (T1 and T2) each with their own managed object context (moc1 and moc2) which use the same persistent store coordinator.
>>
>> 1 - T1 reads ObjectX
>> <the snapshot for ObjectX is created>
>> 2 - T2 reads ObjectX
>> 3 - T1 makes some changes to ObjectX
>> 4 - T2 makes some other changes to ObjectX and saves
>> < at this point the snapshot should be updated >
>> 5 - T1 tries to save
>>
>>
>> I'm expecting a conflict after point 5. But what does Core Data use to know this? If the snapshot is updated with the new value at step 4, the snapshot values are equal to what is on the persistent store.
>
> That is an interesting question. I've always been "curious" about this issue in Core Data's big brother, EOF. In the situation you describe, EOF would *not* report a conflict (wrongly, in my opinion, although this has been a theme for debate in the WebObjects lists) because the snapshot would already be updated. It ends up being easier to detect conflicts between different application instances than between threads of the same instance.
>
> Now, if Core Data also doesn't report any conflict, it means it works just like EOF. However, if it DOES report a conflict, I'm also very interested in knowing how CoreData implements this mechanism.
>
> Regards,
>
> Miguel Arroz
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden