Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concurrency #669

Merged
merged 2 commits into from
Aug 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

import com.webobjects.appserver.WOApplication;
import com.webobjects.appserver.WOComponent;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.eocontrol.EOObjectStore;
import com.webobjects.eocontrol.EOObjectStoreCoordinator;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSForwardException;
import com.webobjects.foundation.NSMutableArray;
Expand Down Expand Up @@ -86,7 +89,9 @@ public static NSArray tasks() {
}

public abstract class DefaultImplementation implements Runnable, ERXLongResponseTask {

private volatile EOObjectStore _parentObjectStore;
private Long _taskEditingContextTimestampLag;


/** logging support */
public Logger log = Logger.getLogger(ERXUtilities.class);
Expand Down Expand Up @@ -344,5 +349,92 @@ public WOComponent nextPage() {
*/
public abstract Object performAction();

//---------------------- Copied from ERXTask -------------------------------------

/**
* See Effective Java item #71 for explanation of this threadsafe lazy
* initialization technique
*
* @return the parent, usually an {@link EOObjectStoreCoordinator} to
* partition the task's EOF intensive work form the rest of the app.
*/
protected final EOObjectStore parentObjectStore() {
EOObjectStore osc = _parentObjectStore;
if (osc == null) {
synchronized (this) {
osc = _parentObjectStore;
if (osc == null) {
_parentObjectStore = osc = ERXTaskObjectStoreCoordinatorPool.objectStoreCoordinator();
}
}
}
return osc;
}

/**
* @param parentObjectStore
* the parent, usually an {@link EOObjectStoreCoordinator} to
* partition the task's EOF intensive work from the rest of the
* app. If you are going to manually set this, you should do it
* before starting the task.
*/
public final synchronized void setParentObjectStore(EOObjectStore parentObjectStore) {
_parentObjectStore = parentObjectStore;
}

/**
* <strong>You must manually lock and unlock the editing context returned by
* this method.</strong> It is not recommended that you depend on auto
* locking in background threads.
*
* Even though this method currently returns an auto-locking EC if
* auto-locking is turned on for the app, a future update is planned that
* will return a manually locking EC from this method even if auto-locking
* is turned on for regular ECs used in normal request-response execution.
*
* @return a new EOEditingContext.
*/
protected EOEditingContext newEditingContext() {
EOEditingContext ec = ERXEC.newEditingContext(parentObjectStore());
// if this is not a nested EC, we can set the fetch time stamp
if (!(parentObjectStore() instanceof EOEditingContext)) {
ec.setFetchTimestamp(taskEditingContextTimestampLag());
}
return ec;
}

/**
* By design EOEditingContext's have a fetch timestamp (default is 1 hour)
* that effectively creates an in-memory caching system for EOs. This works
* great for users browsing through pages in the app. However, experience
* has shown that background EOF tasks are performing updates based on the
* state of other EOs, and thus we want to This is a long-running task. The
* last thing I want to do is perform a long running task with stale EOs, so
* we lazily create a fetch timestamp of the current time when we create the
* first EC and thus ensure fresh data. Secondly, we continue, by default to
* use this timestamp for the duration of the task since experience has
* shown that by doing so we can prevent unnecessary database fetching
* especially when our task is adding lots of items to a single relationship
* in batches.
*
* However if you want fresh data each time you create an EC in your task,
* feel free to set the fetch time stamp to the current time in your task
* each time you create a new EC.
*
* For R-R ec's we prefer fresh data on new pages. However for long running
* tasks, it is often best pick a single point in time, usually when the
* first ec is created as the timestamp lag. This works well when we are
* iterating and making new ec's especially if we are adding 100's of items
* to a relationship and cycling ec's
*
* @return the timestamp lag to use for new ec's created in the task thread.
*/
protected long taskEditingContextTimestampLag() {
if (_taskEditingContextTimestampLag == null) {
_taskEditingContextTimestampLag = Long.valueOf(System.currentTimeMillis());
}
return _taskEditingContextTimestampLag.longValue();
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ protected EOEditingContext newEditingContext() {
*
* @return the timestamp lag to use for new ec's created in the task thread.
*/
private long taskEditingContextTimestampLag() {
protected long taskEditingContextTimestampLag() {
if (_taskEditingContextTimestampLag == null) {
_taskEditingContextTimestampLag = Long.valueOf(System.currentTimeMillis());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
import com.webobjects.appserver.WOApplication;
import com.webobjects.appserver.WOComponent;
import com.webobjects.appserver.WOContext;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.eocontrol.EOObjectStore;
import com.webobjects.eocontrol.EOObjectStoreCoordinator;
import com.webobjects.woextensions.WOLongResponsePage;

import er.extensions.appserver.ERXApplication;
import er.extensions.eof.ERXEC;

/**
* ERXWOLongResponsePage is just like WOLongResponsePage except that it
Expand All @@ -21,6 +25,9 @@ public abstract class ERXWOLongResponsePage extends WOLongResponsePage {
* <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a>
*/
private static final long serialVersionUID = 1L;
private volatile EOObjectStore _parentObjectStore;
private Long _taskEditingContextTimestampLag;


public ERXWOLongResponsePage(WOContext context) {
super(context);
Expand All @@ -44,4 +51,92 @@ public void run() {
ERXApplication._endRequest();
}
}

//---------------------- Copied from ERXTask -------------------------------------

/**
* See Effective Java item #71 for explanation of this threadsafe lazy
* initialization technique
*
* @return the parent, usually an {@link EOObjectStoreCoordinator} to
* partition the task's EOF intensive work form the rest of the app.
*/
protected final EOObjectStore parentObjectStore() {
EOObjectStore osc = _parentObjectStore;
if (osc == null) {
synchronized (this) {
osc = _parentObjectStore;
if (osc == null) {
_parentObjectStore = osc = ERXTaskObjectStoreCoordinatorPool.objectStoreCoordinator();
}
}
}
return osc;
}

/**
* @param parentObjectStore
* the parent, usually an {@link EOObjectStoreCoordinator} to
* partition the task's EOF intensive work from the rest of the
* app. If you are going to manually set this, you should do it
* before starting the task.
*/
public final synchronized void setParentObjectStore(EOObjectStore parentObjectStore) {
_parentObjectStore = parentObjectStore;
}

/**
* <strong>You must manually lock and unlock the editing context returned by
* this method.</strong> It is not recommended that you depend on auto
* locking in background threads.
*
* Even though this method currently returns an auto-locking EC if
* auto-locking is turned on for the app, a future update is planned that
* will return a manually locking EC from this method even if auto-locking
* is turned on for regular ECs used in normal request-response execution.
*
* @return a new EOEditingContext.
*/
protected EOEditingContext newEditingContext() {
EOEditingContext ec = ERXEC.newEditingContext(parentObjectStore());
// if this is not a nested EC, we can set the fetch time stamp
if (!(parentObjectStore() instanceof EOEditingContext)) {
ec.setFetchTimestamp(taskEditingContextTimestampLag());
}
return ec;
}

/**
* By design EOEditingContext's have a fetch timestamp (default is 1 hour)
* that effectively creates an in-memory caching system for EOs. This works
* great for users browsing through pages in the app. However, experience
* has shown that background EOF tasks are performing updates based on the
* state of other EOs, and thus we want to This is a long-running task. The
* last thing I want to do is perform a long running task with stale EOs, so
* we lazily create a fetch timestamp of the current time when we create the
* first EC and thus ensure fresh data. Secondly, we continue, by default to
* use this timestamp for the duration of the task since experience has
* shown that by doing so we can prevent unnecessary database fetching
* especially when our task is adding lots of items to a single relationship
* in batches.
*
* However if you want fresh data each time you create an EC in your task,
* feel free to set the fetch time stamp to the current time in your task
* each time you create a new EC.
*
* For R-R ec's we prefer fresh data on new pages. However for long running
* tasks, it is often best pick a single point in time, usually when the
* first ec is created as the timestamp lag. This works well when we are
* iterating and making new ec's especially if we are adding 100's of items
* to a relationship and cycling ec's
*
* @return the timestamp lag to use for new ec's created in the task thread.
*/
protected long taskEditingContextTimestampLag() {
if (_taskEditingContextTimestampLag == null) {
_taskEditingContextTimestampLag = Long.valueOf(System.currentTimeMillis());
}
return _taskEditingContextTimestampLag.longValue();
}

}