Re: Invalidating objects in change notification framework
Re: Invalidating objects in change notification framework
- Subject: Re: Invalidating objects in change notification framework
- From: Timo Hoepfner <email@hidden>
- Date: Fri, 15 Sep 2006 12:22:38 +0200
Hi,
I'm still fighting with the ChangeNotification stuff. Really need
some help here...
Somehow it appears impossible to me to go the "invalidate global IDs"
route because I'm getting IllegalStateExceptions during saveChanges
(see bottom of post). I made some reproduction code which reproduces
the problem quite reliably (also see bottom of post).
I tried tons of alternatives for the locking (ec.lockObjectectStore()
instead ec.rootObjectStore().lock(), getting down to the database
context and locking it as well, ...) but the problem remains. Also
tried EODatabase.forgetSnapshotForGlobalID with the same result.
Before I finally give up on the subject, could someone with a deeper
understanding of the locking stuff (Chuck?) take a look at it. I
think it should work this way. If I'm not missing something, I
currently see no way in getting any kind of change notification
framework work reliably with the "invalidate global IDs" approach.
And the "snapshot" approach is already known for causing deadlocks.
Locally I'm testing on Intel/Tiger/WO 5.3.1, but have seen the same
Exceptions on PPC/Panther Server/WO 5.2.3.
Any help would be greatly appreciated.
Timo
PS: As Apple is going out of the tools business for WO and wants to
concentrate more on the framework, I *really* hope they take a deep
look into EOF concurrency and cross-VM cache synchronization. I guess
that will remain a wish but would make life soooooo much easier...
PPS:
The meat of the code is:
a) in some thread read and write data concurrently (with correct
locking)
b) simulate incoming change notifications in another tread
EOEditingContext ec = new EOEditingContext();
try {
ec.lock();
ec.rootObjectStore().lock();
ec.rootObjectStore().invalidateAllObjects(); // just for testing,
real code would only invalidate certain GIDs
} finally {
ec.rootObjectStore().unlock();
ec.unlock();
ec.dispose();
}
Result is e.g.:
java.lang.IllegalStateException:
rowDiffsForAttributes:
snapshot in com.webobjects.eoaccess.EODatabaseOperation {
_dbSnapshot = {};
_entity = "TestEntity";
_newRow = {id = 45; testValue = "Thread-2/2200"; lastUpdate =
2006-09-13 15:12:40 Etc/GMT; };
_object = "{values = {lastUpdate = 2006-09-13 15:12:40 Etc/GMT;
testValue = "Thread-2/2200"; };
this = "<timo.testet.TestEntity 5b8e6c _EOIntegralKeyGlobalID
[TestEntity (java.lang.Integer)45]>"; }";
_globalID = _EOIntegralKeyGlobalID[TestEntity (java.lang.Integer)45];
_databaseOperator = "EODatabaseUpdateOperator";
}
does not contain value for attribute named id with snapshot key: id
A bit more of code and output is attached:
Attachment:
code.java
Description: Binary data
Thread-2 still running after 1000 iterations.
Thread-2 still running after 2000 iterations.
cleanup time
java.lang.IllegalStateException: rowDiffsForAttributes: snapshot in com.webobjects.eoaccess.EODatabaseOperation {_dbSnapshot = {}; _entity = "TestEntity"; _newRow = {id = 45; testValue = "Thread-2/2200"; lastUpdate = 2006-09-13 15:12:40 Etc/GMT; }; _object = "{values = {lastUpdate = 2006-09-13 15:12:40 Etc/GMT; testValue = "Thread-2/2200"; }; this = "<timo.testet.TestEntity 5b8e6c _EOIntegralKeyGlobalID[TestEntity (java.lang.Integer)45]>"; }"; _globalID = _EOIntegralKeyGlobalID[TestEntity (java.lang.Integer)45]; _databaseOperator = "EODatabaseUpdateOperator"; } does not contain value for attribute named id with snapshot key: id
at com.webobjects.eoaccess.EODatabaseOperation.rowDiffsForAttributes(EODatabaseOperation.java:338)
at com.webobjects.eoaccess.EODatabaseContext.createAdaptorOperationsForDatabaseOperationAttributes(EODatabaseContext.java:5373)
at com.webobjects.eoaccess.EODatabaseContext.createAdaptorOperationsForDatabaseOperation(EODatabaseContext.java:5548)
at com.webobjects.eoaccess.EODatabaseContext.performChanges(EODatabaseContext.java:6365)
at com.webobjects.eocontrol.EOObjectStoreCoordinator.saveChangesInEditingContext(EOObjectStoreCoordinator.java:415)
at com.webobjects.eocontrol.EOEditingContext.saveChanges(EOEditingContext.java:3226)
at Main$2.run(Main.java:66)
at java.lang.Thread.run(Thread.java:552)
cleanup time
java.lang.IllegalStateException: rowDiffsForAttributes: snapshot in com.webobjects.eoaccess.EODatabaseOperation {_dbSnapshot = {}; _entity = "TestEntity"; _newRow = {id = 34; testValue = "Thread-2/2677"; lastUpdate = 2006-09-13 15:12:41 Etc/GMT; }; _object = "{values = {lastUpdate = 2006-09-13 15:12:41 Etc/GMT; testValue = "Thread-2/2677"; }; this = "<timo.testet.TestEntity 80435f _EOIntegralKeyGlobalID[TestEntity (java.lang.Integer)34]>"; }"; _globalID = _EOIntegralKeyGlobalID[TestEntity (java.lang.Integer)34]; _databaseOperator = "EODatabaseUpdateOperator"; } does not contain value for attribute named id with snapshot key: id
at com.webobjects.eoaccess.EODatabaseOperation.rowDiffsForAttributes(EODatabaseOperation.java:338)
at com.webobjects.eoaccess.EODatabaseContext.createAdaptorOperationsForDatabaseOperationAttributes(EODatabaseContext.java:5373)
at com.webobjects.eoaccess.EODatabaseContext.createAdaptorOperationsForDatabaseOperation(EODatabaseContext.java:5548)
at com.webobjects.eoaccess.EODatabaseContext.performChanges(EODatabaseContext.java:6365)
at com.webobjects.eocontrol.EOObjectStoreCoordinator.saveChangesInEditingContext(EOObjectStoreCoordinator.java:415)
at com.webobjects.eocontrol.EOEditingContext.saveChanges(EOEditingContext.java:3226)
at Main$2.run(Main.java:66)
at java.lang.Thread.run(Thread.java:552)
Thread-2 still running after 3000 iterations.
Am 06.09.2006 um 13:59 schrieb Timo Hoepfner:
Hi,
I'm currently taking a look on Wonder's ERChangeNotificationJMS
framework, as it is causing deadlocks sometimes (often).
The framework currently sends around snapshots via JMS and replaces
them at the EODatabase level in the recieving instance:
EODatabase database;
EOGlobalID globalID;
NSDictionary snapshot;
...
database.forgetSnapshotForGlobalID(globalID);
database.recordSnapshotForGlobalID(snapshot, globalID);
I guess that this is taken from the father of all change
notification frameworks by D. Neumann, as almost the same lines can
be found in the WHChangeNotification framework.
Several people reported, that everything works a lot better, if no
snapshots but just globalIDs are used.
Now I can see several ways to invalidate the data once the GIDs are
received and I'm wondering, what's the best way to do so:
1. database.forgetSnapshotForGlobalID(globalID);
or
2. database.recordSnapshotForGlobalID(null, globalID);
or
3. ec.invalidateObjectsWithGlobalIDs(globalIDs);
or
4. ec.rootObjectStore().invalidateObjectsWithGlobalIDs(globalIDs);
Or a combination of the above ones? Or a completely different
approach?
Am I right, that 1+2 would work across different EOF stacks within
one instance but 3+4 would only work for one?
Any hints would be very welcome.
Timo
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40onlinehome.de
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden