Hi,

On 2014-11-25, 6:21 AM, "OC" wrote:

Hello there,

I've got a WO app, running with FrontBase, pretty standard setup.

The one slightly non-standard thing is that for some specific EOs, I generate 
fixed PKs through

ec.insertObjectWithGlobalID(myeo,EOKeyGlobalID.globalIDWithEntityName(entityName,new
 Object[]{primaryKey}))

and later I fetch them with those fixed PKs.

Till my app run single-instance, all worked well. As soon as I went 
multi-instance, I'm starting getting locking problems FrontBase-level. That 
sort of makes sense -- after all it's well possible that different instances 
access the DB at the same moment -- but for sweet world, I can't find a good 
solution.

There are no simple solutions.  You need to be aware of where this can happen 
in your app and code for it.


(i) My first attempt was to set pessimistic locking FrontBase-level -- the idea 
was that the other instance simply would be forced by the DB server to wait a 
moment whilst the first one does its work. This failed due to

- the fact that FrontBase locks SELECTS in pessimistic mode, too, which 
probably made all the instances run pretty slow (I am not entirely sure it's 
the culprit, but I checked that FrontBase indeed does lock SELECTS in 
pessimistic mode, and I _do_ know my app run much slower in this setup, so it 
seems a good guess).

Yes, it will make it slower.


- anyway, I kept getting deadlocks: I did implement 
databaseContextWillOrderAdaptorOperations delegate method to order operations 
by entity to prevent table-based deadlocks, *BUT* I am using 
er.jgroups.ERJGroupsSynchronizer to sync changes betw. instances, and it does 
not seem it can be told to order operations the same way, and thus I got 
deadlocks, when Synchronizer saved tables in order B, A ... and my own code 
from another instance at the same moment updated in order A, B, ...

Create your constraints as DEFERRABLE INITIALLY DEFERRED.  You will need to 
drop and re-create the ones that you have.


(ii) so I've switched to optimistic locking FrontBase-level 
("jdbc:FrontBase://... .../isolation=read_committed/locking=optimistic"). That, 
though, brought other problems I have problems to cope with:

(a) concurrent deletions

It might happen two instances try to delete an EO at the same moment. If this 
happens, I am getting an exception that object cannot be found (not 
surprisingly :)). At the moment, the best solution I have found so far is

===
static void _saveTolerantlyChangesInEC(EOEditingContext ec) { // essentially 
same logic as Wonder's saveTolerantly
  try { // solve the concurrent deletion problem
    ec.saveChanges()
  } catch (EOGeneralAdaptorException exception) {
    NSDictionary eui=exception.userInfo()
    EOAdaptorOperation adaptorOp=eui[EOAdaptorChannel.FailedAdaptorOperationKey]
    EODatabaseOperation 
databaseOp=eui[EODatabaseContext.FailedDatabaseOperationKey]
    NSDictionary snapshot = databaseOp.dbSnapshot()
    if (adaptorOp.adaptorOperator()==EODatabaseOperation.AdaptorDeleteOperator) 
{
      EOEnterpriseObject delobj=ec.deletedObjects().find { 
it.primaryKeyNumericValue == snapshot['uid'] } // 'uid' is PK
      if (delobj) ec.forgetObject(delobj)
      _saveTolerantlyChangesInEC(ec) // OK, we have gotten rid of the offending 
object, let's try again
    } else throw exception;
  }
}
===

Seems rather on the convoluted side -- can it be done in an easier way? -- but 
whatever else I did, it did not work (e.g., without forgetting the object, a 
retry tried to delete again, triggering again the same exception.

Seems to work all right, nevertheless. Still, if there's a simpler solution, 
I'd like to see it.

I can’t think of a simpler way.


(b) concurrent inserts

This problem is caused by my using fixed PKs (though if I did not, I might be 
getting duplicated EOs instead). If two instances try to insert a new EO with 
the same PK, I'm (naturally) getting a constraint PK violation exception from 
the database.

And I can't find a way to solve it :(

I can (and do) try to fetch the offending object -- and since the other 
instance committed meantime, I get it all right:

===
  ... code as above ...
  if (ocs_is_primary_key_constraint(exception) && 
adaptorOp.adaptorOperator()==EODatabaseOperation.AdaptorInsertOperator) {
    NSArray pka=entity.primaryKeyAttributes()
    EOQualifier 
pkq=ERXEOAccessUtilities.qualifierFromAttributes(pka,adaptorOp.changedValues()) 
// contains the PK
    EOFetchSpecification fs=new EOFetchSpecification(entityName,pkq,null)
    fs.setRefreshesRefetchedObjects(YES)
    NSArray objs=ec.objectsWithFetchSpecification(fs)
    if (objs.count()==1) {
      // OK, my code does get here, the object inserted by other instance is 
fetched all right. But what now?!?
      ???
      _saveTolerantlyChangesInEC(ec) // let's try again
    ... ...
===

What to do at the ??? place? If I do nothing, the insert operation stays in EC 
and fails again.

I've tried to remove the newly added object from ec.insertedObjects. Strangely 
enough it did work (i.e., it has been removed -- self evidently, internally 
insertedObjects is a mutable array), but did not help -- this way led to the 
dreaded "rowDiffsForAttributes: snapshot in 
com.webobjects.eoaccess.EODatabaseOperation {_dbSnapshot = {}; ..." exceptions.

Currently I am recording the PK and entity, and in my 
databaseContextWillOrderAdaptorOperations I do not add adaptor operation for 
such an insert. This seems to sort of work, but is TERRIBLY convoluted -- there 
must be a better solution?

Set the relationships for any other objects into the EC to the one fetched, not 
the one just created and then  ec.deleteObject(dupicate object))


(c) concurrent updates

When I get the "condition 379. Optimistic locking: multiple transaction 
conflict detected" I do essentially nothing -- I just wait a random couple of 
tenths of second, and retry.

I have seen that, but very rarely.  If all of the connections to the data base 
use "/isolation=read_committed/locking=optimistic” you should not get this.  I 
have caused this by using FrontBase Manager or some other tool to look at the 
database as it used a different isolation level and / or (don’t recall) locking


Again, is there as better solution? I keep pretty often the same exception 
again; perhaps I should wait for a longer random time? But that might slow the 
application perceptibly (well, the exceptions do, definitely).

Anyway, seems to me these problems should have been encountered thousand times 
(essentially always with multi-instance setup) and solved in a clean and easy 
way long long ago -- but perhaps I'm just dumb and blind, or my google-fu is 
terribly lacking, but whatever I do, I can't find a good solution?

Will be really grateful for any advice,
OC

Chuck

Chuck Hill, BSc
Senior Managing Partner
Information Technology Services – Development
Gevity Consulting, Inc.

E: ch...@gevityinc.com<mailto:rdh...@gevityinc.com>
W: gevityinc.com
Practical 
WebObjects<Practical%20WebObjects%20-%20for%20developers%20who%20want%20to%20increase%20their%20overall%20knowledge%20of%20WebObjects%20or%20who%20are%20trying%20to%20solve%20specific%20problems.%20%20%20%20
http://www.global-village.net/gvc/practical_webobjects
Practical%20WebObjects%20-%20for%20developers%20who%20want%20to%20increase%20their%20overall%20knowledge%20of%20WebObjects%20or%20who%20are%20trying%20to%20solve%20specific%20problems.%20%20%20%20
http://www.global-village.net/gvc/practical_webobjects
http://www.global-village.net/gvc/practical_webobjects> - in–depth WebObjects 
knowledge and problem solution

GEVITY
Informatics for a healthier world

CONFIDENTIALITY: This communication is confidential and for the exclusive use 
of its intended recipients. If you have received this communication by error, 
please notify the sender and delete the message without copying or disclosing 
it.
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (Webobjects-dev@lists.apple.com)
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to