• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: EOSharedEditingContext question
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: EOSharedEditingContext question


  • Subject: Re: EOSharedEditingContext question
  • From: "Jonathan Fleming" <email@hidden>
  • Date: Sat, 19 Feb 2005 18:19:41 +0000

I know this is weeks after this post, however, I use EOSharedEditing Context Extesivly now because of this and I have had no trouble wiht it too.
Jonathan :^)


HowToUseSharedEditingContexts Last edited: Tuesday, October 29, 2002 10:01:02

I personally have always been scared of using EOSharedEditingContexts, because there seemed such potential for problems. They are complex in how they work, not entirely well documented, and I suspected there would be Apple bugs.

However, one user kindly provided his own guidelines he uses with EOSharedEditingContexts, and which he says results in no problems at all. I include his guidelines here. --JonathanRochkind]

From: "Robert A. Decker" <email@hidden>
To: email@hidden
Subject: Re: Cache vs. Shared
Date: Mon, 28 Oct 2002 17:42:00 -0800 (PST)


I haven't had problems, yet, with EOSharedEditingContext and objects that are changed rarely, as long as I follow some rules:


1. NEVER fetch using the shared editing context yourself. Do all access to shared objects through the shared editing context's
objectsByEntityNameAndFetchSpecificationName or objectsByEntityName
methods, which return dictionaries containing the shared objects being
held by the shared editing context or you can even use the objectsWithFetchSpecification Method which returns a NSArray and they are all threadsafe. Repeat, DO NOT FETCH using the shared editing context.


2. When making changes to objects or deleting, you have to do it in an
editing context without a sharedEC. I always make a new ec and set its
sharedEc to null, then copy the object I'm going to edit into it using
EOUtilities.localInstanceOfObject

3. When adding objects you have to tell the sharedEc to refresh its array of objects the type you just added. You use the
bindObjectsWithFetchSpecificationName.


Again, do not fetch using the shared ec. Using this simple rule I haven't had any problems with objects that are changed rarely while the app is running. I've deleted and updated up to thousands of objects in separate threads using these rules without problems.

rob

[and on how the objects get in the shared ec in the first place, rob writes:]

Date: Tue, 29 Oct 2002 09:29:32 -0800 (PST)
From: "Robert A. Decker" <email@hidden>
To: email@hidden
Subject: Re: Cache vs. Shared


For each of my shared entities, I add a fetch spec named 'FetchAll' and in the EOModeler inspector I set that fetch spec to be the fetch that holds the shared instances. (click on entity, look at inspector third button, click on 'Shared objects fetched with' radio button for the FetchAll fetch specification).



You can keep your other fetch specs on those shared entities around, but you shouldn't really use them like you normally would - instead, only use them on doing in-memory fetching and sorting of the NSArrays you get back from the shared entity.


Then, in Application I have two methods:



public static void refreshSharedEntity(String entityName)
throws MarvinGeneralException {
Application.refreshSharedEntityForFetchSpecificationName(entityName, "FetchAll");
}
public static void refreshSharedEntityForFetchSpecificationName(String entityName, String fetchSpecName) throws MarvinGeneralException {
EOModelGroup modelGroup = EOModelGroup.defaultGroup();
EOSharedEditingContext sharedEC = EOSharedEditingContext.defaultSharedEditingContext();
EOFetchSpecification fs = modelGroup.fetchSpecificationNamed(fetchSpecName, entityName);
if (fs == null) {
throw new MarvinGeneralException(Application.class.getName()+
".refreshSharedEntityForFetchSpecificationName", entityName + "." +
fetchSpecName + " doesn't exist");
}
else { sharedEC.bindObjectsWithFetchSpecification(fs, fetchSpecName);
}
}



I use these methods for updating the shared editing context for a specific entity.


As an example for an entity, I have the methods:


public static NSArray enclosureMasters() {
NSDictionary objectsByEntityName =
(NSDictionary) EOSharedEditingContext.defaultSharedEditingContext().objectsByEntityNameAndFetchSpecificationName();
NSDictionary objectsForEnclosureMaster =
(NSDictionary) objectsByEntityName.objectForKey("EnclosureMaster");
NSArray enclosureMasters = (NSArray) objectsForEnclosureMaster.objectForKey("FetchAll");
return enclosureMasters;
}
public static NSArray enclosureMasters(String fetchSpecName, NSDictionary bindings) {
// filter in memory against all enclosure masters
// EOQualifier.filteredArrayWithQualifier( NSArray objects, EOQualifieraQualifier)
if (bindings == null)
bindings = new NSDictionary();
EOFetchSpecification fetchSpec =
EOFetchSpecification.fetchSpecificationNamed(fetchSpecName, "EnclosureMaster");
EOQualifier boundQualifier =
fetchSpec.qualifier().qualifierWithBindings(bindings, fetchSpec.requiresAllQualifierBindingVariables());
if (boundQualifier == null)
return EnclosureMaster.enclosureMasters();
// return all -
// otherwise the next call will give us an empty array
NSArray results =
EOQualifier.filteredArrayWithQualifier(EnclosureMaster.enclosureMasters(), boundQualifier);
// we should now use the fetchSpec's sort orderings to sort the results
NSArray sortedResults = results;
NSArray sortOrderings = fetchSpec.sortOrderings();
if (sortOrderings != null)
sortedResults = EOSortOrdering.sortedArrayUsingKeyOrderArray(results, sortOrderings);
return sortedResults;
}



These two methods let me fetch all objects of a certain type and, even better, let me use my other fetch specs on these objects.

All other static methods I would put on EnclosureMaster will go through these two methods. This way I never do any fetches myself and instead just use the objects that are already in memory and held by eosharededitingcontext.

Also, when the app launches it will automaticalyl fetch the shared objects using the FetchAll fetch spec that you set earlier.

When you add a new object you have to reload by calling, for example,
Application.refreshSharedEntity("EnclosureMaster");

When you edit or delete a shared entity the SharedEditing context will
take care of updating the objects it's holding.

thanks,
rob

-----------------------------------------------------------------------------------------------

From: Chuck Hill <email@hidden>
To: Dov Rosenberg <email@hidden>
CC: WebObjects Dev <email@hidden>
Subject: Re: EOSharedEditingContext question
Date: Thu, 3 Feb 2005 10:39:01 -0800

I'm not a shared EC expert and not really comfortable playing at one. For the most part I have avoided using them due to the high number of bugs, historically speaking. OK, that said...

On Feb 3, 2005, at 10:02 AM, Dov Rosenberg wrote:

We use shared editing contexts to save the overhead on read only data and to
use it like a cache. When we use the shared context we always do a lock()
even for a read type operation. In cases where we are going to modify data
that has been retrieved into the shared context, we create a new editing
context and make the changes and save. We lock both the shared and the
regular context when we do.


IIRC, when editing a EO in shared ec the pattern is supposed to be:
- create ec
- lock ec
- set ec's shared ec to null
- fetch (faulting is OK?) the object into the EC
- edit the object and save the EC
- unlock the EC

There is not need to lock the shared EC, it will pick up the changes itself.


Based on your reply I think we need to make some changes. Does the following
make any sense?


1. Instead of creating a new regular EOEditingContext, perhaps we should
make them a nested editing context with the shared editing context as the
parent. That way we make sure to get the correct state of things before we
make the changes and save to the db. Can a shared editing context have
nested editing contexts? If so, hopefully the changes will get recorded
properly by the shared context and be more efficient than what we are doing


I don't think that would be good. If the EC is nested, to save any changes to objects in it, you would also have to save the shared EC. I'd follow Ben's advice: think of it as a data store not an editing context regardless of what the super class is.


2. If we remove the lock(), unlock() from the sharededitingcontext usage
will that start sending out the missing lock messages again? I kind of
remember we had to add the lock() calls to get rid of those.

If it does, that is a bug in the shared EC.


The big qualifier for us is our app is not a typical WO app from the
perspective that our JSP tag library uses EOF but not WO components. We
really don't have WOSessions (except for the JSP Session/WOSession
integration). Our app runs as a servlet outside of the scope of the .woa
application. For the most part this works very well and we have been this
way for the past 3 years with great success.

I would not expect this to be an issue. The shared EC locks _itself_ using, IIRC, com.webobjects.foundation.NSMultiReaderLock. This is in contrast to the defaultEditingContext() of WOSession which is locked and unlocked externally by WOSession. I am not aware of any functional dependancies on anything in the WO side of things.


HTH Chuck


On 2/3/05 12:35 PM, "Chuck Hill" <email@hidden> wrote:

Hi Dov, I don't know if this is what you are looking for, but this was
posted a (long) while ago by Ben Trumbull:

------------
Although an EOSharedEditingContext sounds and appears like an editing
context, it's probably a more useful view to consider it a very special
EOObjectStore.  I prefer to call it a "read mostly object store".

Several differences.

First, correctly locking and unlocking an EC at the application level
is your responsibility, regardless of whether or not you believe an
operation is "an edit".  For example, firing a fault causes side
effects upon various caches.  EOSharedEditingContexts manage their own
locking.

Second, EOSharedEditingContexts are "read mostly".  Mutating EOs in
them is complicated and inefficient.

Third, regular ECs "have" one shared EC, a lot like they have a parent
object store.  This means that several regular ECs all using the same
shared EC also use the same objects that are within the shared EC.  EOs
within a shared EC are unique instances, unlike all other EOs which
have individual instances in each regular EC, even though they have the
same primary key (GID).

Basically, this is a memory-performance compromise.  Using a shared EC
means not only do your EOs reuse the cached row level snapshots in
EOAccess, but they are also represented by the same Java objects. The
down side is that shared ECs do more locking, and changing EOs within
them is inconvenient.

In summary, EOSharedEditingContext is really more about implementation
inheritance than interface inheritance.
---------------------------------

I suspect your problem had to do with you locking the shared EC
yourself and the locks staying in place too long.  Consider this
hypothetical situation:

Thead 1: locks EC, shared EC, performs operations which results in an
attempt to lock object store coordinator

Thread 2: performs some operation, locks object store coordinator,
execution of operation requires operation on shared EC, shared EC
attempts to lock itself

At this point you have a deadly embrace.  Thread one has the shared ec
locked and is waiting to lock the OSC.  Thread 2 has the OSC locked and
is waiting to lock the shared EC.

Chuck


On Feb 2, 2005, at 3:42 PM, Dov Rosenberg wrote:

We recently fixed a bug in our application that was causing it to lock
when multiple users submitted a form request via http. After
scratching our heads for a long while we went to look in the “Bible”
(Chuck Hill’s Practical WebObjects – great book). We came across a
little blurb about not locking SharedEditingContexts. When we removed
the lock it seems to have cleared up our deadlock problem. But we are
stumped as to why this caused us a headache.

 Our app uses both a sharededitingcontext and regular editing contexts
created doing new EOEditingContext(). We lock and unlock both the
shared and regular editing contexts everywhere. It seems that our
problem only manifested itself when we were writing to the database
(not reading). It was also not consistently reproducible.

 Any thoughts or comments would be appreciated.

 Thanks in advance



 --
 Dov Rosenberg
 Conviveon Corporation
http://www.conviveon.com

     _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
village.net

This email sent to email@hidden




--
Practical WebObjects - a book for intermediate WebObjects developers who want to increase their overall knowledge of WebObjects, or those who are trying to solve specific application development problems.
http://www.global-village.net/products/practical_webobjects




_______________________________________________
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


_______________________________________________
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


References: 
 >Re: EOSharedEditingContext question (From: Chuck Hill <email@hidden>)

  • Prev by Date: Re: attempt to assign value to unknown key
  • Next by Date: Re: prefetching run amok
  • Previous by thread: Re: EOSharedEditingContext question
  • Next by thread: Re: EOSharedEditingContext question
  • Index(es):
    • Date
    • Thread