All,

This is following on to conversations started about a month ago regarding a new pmf property, CopyOnAttach, that when set to false would force makePersistent to transition detached parameters back to P-clean or P-dirty and return the very same instance without making a copy.  For clarity, an example use case follows:

<example>

PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("jdo.properties");

assert pmf.getDetachAllOnCommit() == true;
assert pmf.getCopyOnAttach() == false;

// assuming (for convenience) that there's a single instance of an Employee in the database, let's query for it, detaching on commit.
final Employee emp;
{
    PersistenceManager pm = pmf.getPersistenceManager();
    pm.currentTransaction().begin();
    emp = (Employee) pm.newQuery("select unique from Employee").execute();
    pm.currentTransaction().commit();
}

// 'emp' is now detached-clean
assert isDetached(emp) && isClean(emp);

emp.setAge(32);

// 'emp' is now detached-dirty
assert isDetached(emp) && isDirty(emp);

Employee returned;
{
    PersistenceManager pm = pmf.getPersistenceManager();
    pm.currentTransaction().begin();
    returned = pm.makePersistent(emp);
    pm.currentTransaction().commit();
}

// 'emp' is now detached-clean.
assert isDetached(emp) && isClean(emp);

// and no copy was made during attachment
assert emp == returned;

</example>



Normally, without CopyOnAttach == false (i.e.: current-world behavior), the final state of 'emp' in the example above would be 'detached-dirty' and 'returned' would be a brand new instance ending up 'detached-clean'.

The new CopyOnAttach == false functionality allows the user to detach, modify and attach the same object an indefinite number of times without incurring a) the performance cost of copying and b) the usability cost of having to assign 'emp' to the return value on each call to makePersistent().

In the current world, the user *could* detach, modify and attach the same 'emp' object an indefinite number of times, simply disregarding the returned value, but there are two ill effects of doing this: a) copies are needlessly made, and worse, b) the parameter 'emp' instance remains forever 'detached-dirty'.  This means that any field ever dirtied in 'emp' will always be flushed to the datastore, even if it is not further modified during subsequent iterations.  This would be confusing to the user and another potential source of performance problems.  Allowing the 'emp' instance to transition back to persistent-dirty and subsequently to detached-clean after commit solves this problem completely.


I understand that I'm getting this in just under the wire for tomorrow's conference call; I don't expect folks to have reviewed it with such short lead time.  But it can provide some fodder for discussion, and we'll all have a week to consider it before the next call.  Please scrutinize this heavily; I consider this proposal a good start, and not necessarily complete by any means.

I've included the proposal inline below, and also attached it as an RTF document.  You'll likely find the RTF more readable as it uses bolding and italics to distinguish changes, etc.

I'll also be attaching this proposal to the JIRA issue for this topic at http://issues.apache.org/jira/browse/JDO-522.  I suggest that we add comments and changes there to cut down on duplications between email and JIRA.


<proposed>

11.1:
* CopyOnAttach: the PersistenceManager mode that indicates whether calls to makePersistent(pc) where pc is a detached instance will return the same instance or a copy of that instance.  For backward compatibility reasons, this flag must default to ‘true’.
A11.1-40 [PersistenceManagerFactory.setCopyOnAttach(boolean flag) sets the value of the CopyOnAttach flag.]
A11.1-41 [PersistenceManagerFactory.getCopyOnAttach() gets the value of the CopyOnAttach flag.]


11.1-33:
+ “javax.jdo.option.CopyOnAttach”  

A5.5.9-2 [Detached-dirty instances do not change their life cycle state unless CopyOnAttach is set to false.  If CopyOnAttach is false, detached-dirty instances may transition to persistent-clean or persistent-dirty when attached via makePersistent (see 5.9 for details)]

5.9:
Add the following rows to the last table in this section with headings:
| method / current state | P-nontrans-dirty | detached-clean | detached-dirty |

+ | makePersistent with CopyOnAttach=false | unchanged | parameter: P-clean, returned: P-clean (same instance as parameter) | parameter: P-dirty, returned: P-dirty (same instance as parameter) |
+ | makePersistent with CopyOnAttach=false when an object with the same identity already exists in the L1 cache |  unchanged | error | error |

(this last row stipulates that usage of CopyOnAttach=false is only valid in cases where a new PersistenceManager is used for each call to makePersistent.  Said another way, multiple calls to makePersistent with the same pc against the same pm will result in a JDOUserException.  It is unknown / unspecified what implications this has on L2 caches... comments?)

12.6.7:
A12.5.7-7: [These methods have no effect on parameter persistent instances already managed by this PersistenceManager unless the CopyOnAttach method is set to false, in which case detached parameter instances will be transitioned to P-dirty or P-clean per section 5.9]
A12.6.7-1:
[...]
The return value for detached instances is the persistent instance corresponding to the detached instance.  In the case of CopyOnAttach being set to false, the return value is the same object instance as the detached parameter instance, where the parameter has been transitioned from detached to P-dirty or P-clean per the rules in section 5.9

The return values for makePersistentAll methods correspond by position to the parameter instances.  In the case of CopyOnAttach being set to false, the object instances in the collection returned by makePersistentAll must be the same object instances as found in the parameter collection, each having been transitioned to P-dirty or P-clean as appropriate per the rules in section 5.9

</proposed>

{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf420
{\fonttbl\f0\fswiss\fcharset77 Helvetica;\f1\fswiss\fcharset77 Helvetica-Bold;\f2\fmodern\fcharset77 Courier;
\f3\fswiss\fcharset77 Helvetica-Oblique;\f4\fmodern\fcharset77 Courier-Bold;\f5\fmodern\fcharset77 Courier-Oblique;
}
{\colortbl;\red255\green255\blue255;}
\margl1440\margr1440\vieww9000\viewh8400\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural

\f0\fs24 \cf0 For Review:\
\
<proposed>\
\

\f1\b 11.1:
\f0\b0 \
* 
\f2 CopyOnAttach
\f0 : the 
\f2 PersistenceManager
\f0  mode that indicates whether calls to 
\f2 makePersistent(pc)
\f0  where 
\f2 pc
\f0  is a detached instance will return the same instance or a copy of that instance.  For backward compatibility reasons, this flag must default to \'d4true\'d5.\

\f1\b A11.1-40 
\f0\b0 [
\f3\i PersistenceManagerFactory.setCopyOnAttach(boolean flag) sets the value of the CopyOnAttach flag.
\f0\i0 ]\

\f1\b A11.1-41
\f0\b0  [
\f3\i PersistenceManagerFactory.getCopyOnAttach() gets the value of the CopyOnAttach flag.
\f0\i0 ]\
\
\

\f1\b 11.1-33
\f0\b0 :\
+ 
\f2 \'d2javax.jdo.option.CopyOnAttach\'d3  
\f0 \
\

\f1\b A5.5.9-2
\f0\b0  [Detached-dirty instances do not change their life cycle state 
\f1\b unless 
\f4 CopyOnAttach
\f1  is set to false.  If 
\f4 CopyOnAttach
\f1  is false, detached-dirty instances may transition to persistent-clean or persistent-dirty when attached via 
\f4 makePersistent (see 5.9 for details)
\f2\b0 ]\
\

\f1\b 5.9:\

\f3\i\b0 Add the following rows to the last table in this section with headings:\
| method / current state | P-nontrans-dirty | detached-clean | detached-dirty |\

\f0\i0 \
+ | 
\f2 makePersistent
\f0  with 
\f2 CopyOnAttach
\f0 =false | unchanged | parameter: P-clean, returned: P-clean (same instance as parameter) | parameter: P-dirty, returned: P-dirty (same instance as parameter) |\
+ | 
\f2 makePersistent
\f0  with 
\f2 CopyOnAttach
\f0 =false when an object with the same identity already exists in the L1 cache |  unchanged | error | error |\
\

\f3\i (this last row stipulates that usage of 
\f5 CopyOnAttach
\f3 =false is only valid in cases where a new 
\f5 PersistenceManager
\f3  is used for each call to 
\f5 makePersistent
\f3 .  Said another way, multiple calls to 
\f5 makePersistent
\f3  with the same 
\f5 pc
\f3  against the same 
\f5 pm
\f3  will result in a 
\f5 JDOUserException
\f3 .  It is unknown / unspecified what implications this has on L2 caches... comments?)\

\f0\i0 \

\f1\b 12.6.7
\f0\b0 :\

\f1\b A12.5.7-7
\f0\b0 : [These methods have no effect on parameter persistent instances already managed by this 
\f2 PersistenceManager
\f0  
\f1\b unless the CopyOnAttach method is set to false, in which case detached parameter instances will be transitioned to P-dirty or P-clean per section 5.9
\f0\b0 ]\

\f1\b A12.6.7-1
\f0\b0 :\
[...]\
The return value for detached instances is the persistent instance corresponding to the detached instance.  
\f1\b In the case of 
\f4 CopyOnAttach
\f1  being set to false, the return value is the same object instance as the detached parameter instance, where the parameter has been transitioned from detached to P-dirty or P-clean per the rules in section 5.9
\f0\b0 \
\
The return values for 
\f2 makePersistentAll 
\f0 methods correspond by position to the parameter instances.  
\f1\b In the case of CopyOnAttach being set to false, the object instances in the collection returned by 
\f4 makePersistentAll 
\f1 must be the same object instances as found in the parameter collection, each having been transitioned to P-dirty or P-clean as appropriate per the rules in section 5.9
\f0\b0 \
\
</proposed>\
}

Regards,

- Chris

Chris Beams

Reply via email to