Skip to content

Commit

Permalink
Add properties to ERXDatabase to define initial snapshot cache HashMa…
Browse files Browse the repository at this point in the history
…p parameters, and add the possibility to use a customer ERXDatabase subclass with ERXDatabaseContext
  • Loading branch information
maiksd committed Apr 28, 2016
1 parent 7c77ad0 commit 46f2054
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 10 deletions.
11 changes: 11 additions & 0 deletions Frameworks/Core/ERExtensions/Resources/Properties
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,17 @@ er.extensions.ERXComponentActionRedirector.enabled=false
# Set to true to have this delegate order the operations (e.g. or MS SQL Server)
com.webobjects.eoaccess.ERXEntityDependencyOrderingDelegate.active = false

## Defines the DB class to use together with ERXDatabaseContext
er.extensions.ERXDatabase.className = er.extensions.eof.ERXDatabase

## Define the HashMap initialization parameters to use for the HashMap that ERXDatabase
## uses for the snapshot cache. Usually the load factor is fine, but the capacity
## could use increasing for applications handling many objects. You can use
## ERXDatabase.snapshotCacheSize() to get the actual map size at runtime to
## determine how to tune this.
# er.extensions.ERXDatabase.snapshotCacheMapInitialCapacity = 1048576
# er.extensions.ERXDatabase.snapshotCacheMapInitialLoadFactor = 0.75

#########################################################################
# ERXDatabaseContextDelegate
#########################################################################
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import er.extensions.appserver.ERXApplication;
import er.extensions.eof.ERXAdaptorChannelDelegate;
import er.extensions.eof.ERXConstant;
import er.extensions.eof.ERXDatabase;
import er.extensions.eof.ERXDatabaseContext;
import er.extensions.eof.ERXDatabaseContextDelegate;
import er.extensions.eof.ERXDatabaseContextMulticastingDelegate;
Expand Down Expand Up @@ -281,12 +282,32 @@ public void finishInitialization() {
// ERXObjectStoreCoordinatorPool has a static initializer, so just load the class if
// the configuration setting exists
if (ERXRemoteSynchronizer.remoteSynchronizerEnabled() || ERXProperties.booleanForKey("er.extensions.ERXDatabaseContext.activate")) {
String className = ERXProperties.stringForKeyWithDefault("er.extensions.ERXDatabaseContext.className", ERXDatabaseContext.class.getName());
Class c = ERXPatcher.classForName(className);
if(c == null) {
throw new IllegalStateException("er.extensions.ERXDatabaseContext.className not found: " + className);
String dbCtxClassName = ERXProperties.stringForKeyWithDefault("er.extensions.ERXDatabaseContext.className", ERXDatabaseContext.class.getName());
Class dbCtxClass = ERXPatcher.classForName(dbCtxClassName);
if(dbCtxClass == null) {
throw new IllegalStateException("er.extensions.ERXDatabaseContext.className not found: " + dbCtxClassName);
}
EODatabaseContext.setContextClassToRegister(dbCtxClass);

String dbClassName = ERXProperties.stringForKeyWithDefault("er.extensions.ERXDatabase.className", ERXDatabase.class.getName());
Class dbClass = ERXPatcher.classForName(dbClassName);
if(dbClass == null) {
throw new IllegalStateException("er.extensions.ERXDatabase.className not found: " + dbClassName);
}
if( ERXDatabase.class.isAssignableFrom( dbClass ) ) {
ERXDatabaseContext.setDatabaseContextClass( dbClass );
} else {
throw new IllegalStateException("er.extensions.ERXDatabase.className is not a subclass of ERXDatabase: " + dbClassName);
}

int mapCapacity = ERXProperties.intForKey( "er.extensions.ERXDatabase.snapshotCacheMapInitialCapacity" );
if( mapCapacity > 0 ) {
ERXDatabase.setSnapshotCacheMapInitialCapacity( mapCapacity );
}
float mapLoadFactor = ERXProperties.floatForKey( "er.extensions.ERXDatabase.snapshotCacheMapInitialLoadFactor" );
if( mapLoadFactor > 0.0f ) {
ERXDatabase.setSnapshotCacheMapInitialLoadFactor( mapLoadFactor );
}
EODatabaseContext.setContextClassToRegister(c);
}
ERXObjectStoreCoordinatorPool.initializeIfNecessary();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.webobjects.eocontrol.EOTemporaryGlobalID;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSLog;
import com.webobjects.foundation.NSMutableDictionary;
import com.webobjects.foundation.NSNotification;
import com.webobjects.foundation.NSNotificationCenter;
Expand All @@ -25,15 +26,29 @@
public class ERXDatabase extends EODatabase {
public static final String SnapshotCacheChanged = "SnapshotCacheChanged";
public static final String CacheChangeKey = "CacheChange";

protected static int SnapshotCacheMapInitialCapacity = 1048576;
protected static float SnapshotCacheMapInitialLoadFactor = 0.75f;

private boolean _globalIDChanged;
private boolean _decrementSnapshot;

public static void setSnapshotCacheMapInitialCapacity( int capacity ) {
NSLog.out.appendln( "Setting SnapshotCacheMapInitialCapacity = " + capacity );
SnapshotCacheMapInitialCapacity = capacity;
}

public static void setSnapshotCacheMapInitialLoadFactor( float loadFactor ) {
NSLog.out.appendln( "Setting SnapshotCacheMapInitialLoadFactor = " + loadFactor );
SnapshotCacheMapInitialLoadFactor = loadFactor;
}

public ERXDatabase(EOAdaptor adaptor) {
super(adaptor);

// AK: huge performance optimization when you use badly distributed LONG keys

NSLog.out.appendln( "Using SnapshotCacheMapInitialCapacity = " + SnapshotCacheMapInitialCapacity );
NSLog.out.appendln( "Using SnapshotCacheMapInitialLoadFactor = " + SnapshotCacheMapInitialLoadFactor );
_snapshots = new NSMutableDictionary() {
/**
* Do I need to update serialVersionUID?
Expand All @@ -42,7 +57,7 @@ public ERXDatabase(EOAdaptor adaptor) {
*/
private static final long serialVersionUID = 1L;

Map hashMap = new HashMap();
Map hashMap = new HashMap( SnapshotCacheMapInitialCapacity, SnapshotCacheMapInitialLoadFactor );

@Override
public Object objectForKey(Object key) {
Expand All @@ -68,6 +83,16 @@ public NSDictionary immutableClone() {
public NSArray allKeys() {
return new NSArray(hashMap.keySet());
}

@Override
public int size() {
return hashMap.size();
}

@Override
public int count() {
return hashMap.size();
}
};
}

Expand All @@ -85,6 +110,10 @@ public ERXDatabase(EODatabase _database) {
_database.dispose();
}

public int snapshotCacheSize() {
return _snapshots.size();
}

public synchronized void _notifyCacheChange(CacheChange cacheChange) {
NSNotificationCenter.defaultCenter().postNotification(ERXDatabase.SnapshotCacheChanged, this, new NSDictionary(cacheChange, ERXDatabase.CacheChangeKey));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package er.extensions.eof;

import java.lang.reflect.InvocationTargetException;

import com.webobjects.eoaccess.EOAttribute;
import com.webobjects.eoaccess.EODatabase;
import com.webobjects.eoaccess.EODatabaseContext;
Expand All @@ -12,14 +14,21 @@
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSKeyValueCoding;
import com.webobjects.foundation.NSLog;

public class ERXDatabaseContext extends EODatabaseContext {
private static ThreadLocal _fetching = new ThreadLocal();

public ERXDatabaseContext(EODatabase database) {
super(new ERXDatabase(database));
protected static Class<? extends ERXDatabase> _dbClass = null;

public ERXDatabaseContext( EODatabase database ) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
super( _dbClass != null ? _dbClass.getConstructor( EODatabase.class ).newInstance( database ) : new ERXDatabase( database ) );
}

public static void setDatabaseContextClass( Class<? extends ERXDatabase> cls ) {
NSLog.out.appendln( "Setting ERXDatabase subclass to " + cls.getName() );
_dbClass = cls;
}

public static boolean isFetching() {
Boolean fetching = (Boolean) _fetching.get();
// System.out.println("ERXDatabaseContext.isFetching: " +
Expand Down

0 comments on commit 46f2054

Please sign in to comment.