Skip to content

Commit

Permalink
MONDRIAN
Browse files Browse the repository at this point in the history
       Moved the JdbcSchema classname property to MondrianProperties.
       Replaced the WeakHashMap with a HashMap using SoftReferences.

[git-p4: depot-paths = "//open/mondrian/": change = 5899]
  • Loading branch information
Richard Emberson committed Mar 20, 2006
1 parent 28c7a40 commit 98796df
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 29 deletions.
4 changes: 4 additions & 0 deletions src/main/mondrian/olap/MondrianProperties.java
Expand Up @@ -723,6 +723,10 @@ private void load(final PropertySource source) {
*/
public final IntegerProperty MaxEvalDepth = new IntegerProperty(
this, "mondrian.rolap.evaluate.MaxEvalDepth", 10);


public final StringProperty JdbcFactoryClass = new StringProperty(
this, "mondrian.rolap.aggregates.jdbcFactoryClass", null);
}

// End MondrianProperties.java
39 changes: 31 additions & 8 deletions src/main/mondrian/rolap/aggmatcher/AggTableManager.java
Expand Up @@ -66,8 +66,15 @@ public AggTableManager(final RolapSchema schema) {
* associated RolapSchema object.
*/
public void finalCleanUp() {
clearJdbcSchema();
removeJdbcSchema();
deregisterTriggers(MondrianProperties.instance());

if (getLogger().isDebugEnabled()) {
StringBuffer buf = new StringBuffer(100);
buf.append("AggTableManager.finalCleanUp: schema=");
buf.append(schema.getName());
getLogger().debug(buf.toString());
}
}

/**
Expand Down Expand Up @@ -143,13 +150,6 @@ private void reLoadRolapStarAggregates() {
}
}

/**
* Clear the possibly already loaded snapshot of what is in the database.
*/
private void clearJdbcSchema() {
DataSource dataSource = schema.getInternalConnection().getDataSource();
JdbcSchema.clearDB(dataSource);
}
private JdbcSchema getJdbcSchema() {
DataSource dataSource = schema.getInternalConnection().getDataSource();

Expand All @@ -160,6 +160,23 @@ private JdbcSchema getJdbcSchema() {
return db;
}

/**
* Clear the possibly already loaded snapshot of what is in the database.
*/
private void clearJdbcSchema() {
DataSource dataSource = schema.getInternalConnection().getDataSource();
JdbcSchema.clearDB(dataSource);
}

/**
* Remove the possibly already loaded snapshot of what is in the database.
*/
private void removeJdbcSchema() {
DataSource dataSource = schema.getInternalConnection().getDataSource();
JdbcSchema.removeDB(dataSource);
}


/**
* This method loads and/or reloads the aggregate tables.
* <p>
Expand Down Expand Up @@ -374,13 +391,19 @@ public void execute(Property property, String value) {
}
};

// Note that for each AggTableManager theses triggers are
// added to the properties object. Each trigger has just
// been created and "knows" its AggTableManager instance.
// The triggers' hashCode and equals methods (those provided
// by the Object class) are used when removing the trigger.
properties.ChooseAggregateByVolume.addTrigger(triggers[0]);
properties.AggregateRules.addTrigger(triggers[1]);
properties.AggregateRuleTag.addTrigger(triggers[1]);
properties.ReadAggregates.addTrigger(triggers[2]);
}

private void deregisterTriggers(final MondrianProperties properties) {
// Remove this AggTableManager's instance's triggers.
properties.ChooseAggregateByVolume.removeTrigger(triggers[0]);
properties.AggregateRules.removeTrigger(triggers[1]);
properties.AggregateRuleTag.removeTrigger(triggers[1]);
Expand Down
142 changes: 121 additions & 21 deletions src/main/mondrian/rolap/aggmatcher/JdbcSchema.java
Expand Up @@ -10,6 +10,7 @@

package mondrian.rolap.aggmatcher;

import mondrian.olap.MondrianProperties;
import mondrian.olap.MondrianDef;
import mondrian.rolap.RolapAggregator;
import mondrian.rolap.RolapStar;
Expand All @@ -19,10 +20,19 @@

import org.apache.log4j.Logger;

import java.lang.ref.SoftReference;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.*;
import java.util.*;
import java.sql.ResultSet;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Types;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;

/**
* This class is used to scrape a database and store information about its
Expand Down Expand Up @@ -60,36 +70,39 @@ public Logger getLogger() {

public interface Factory {
JdbcSchema makeDB(DataSource dataSource);
void clearDB(DataSource dataSource);
void clearDB(JdbcSchema db);
void removeDB(JdbcSchema db);
}

private static final Map dbMap = new HashMap();

/**
* How often between sweeping through the dbMap looking for nulls.
*/
private static final int SWEEP_COUNT = 10;
private static int sweepDBCount = 0;

public static class StdFactory implements Factory {
private final WeakHashMap dbMap = new WeakHashMap();
StdFactory() {
}
public JdbcSchema makeDB(DataSource dataSource) {
JdbcSchema db = (JdbcSchema) dbMap.get(dataSource);
if (db == null) {
db = new JdbcSchema(dataSource);
dbMap.put(dataSource, db);
}
JdbcSchema db = new JdbcSchema(dataSource);
return db;
}
public void clearDB(DataSource dataSource) {
JdbcSchema db = (JdbcSchema) dbMap.get(dataSource);
if (db != null) {
db.clear();
}
public void clearDB(JdbcSchema db) {
// NoOp
}
public void removeDB(JdbcSchema db) {
// NoOp
}
}

public static final String FACTORY_CLASS =
"mondrian.rolap.aggregates.jdbcFactoryClass";
private static Factory factory;

private static void makeFactory() {
if (factory == null) {
String classname = System.getProperty(FACTORY_CLASS);
String classname =
MondrianProperties.instance().JdbcFactoryClass.get();
if (classname == null) {
factory = new StdFactory();
} else {
Expand All @@ -106,16 +119,98 @@ private static void makeFactory() {
}
}
}
public static synchronized void clearDB(DataSource dataSource) {

/**
* Create or retrieve an instance of the JdbcSchema for the given
* DataSource.
*
* @param dataSource
* @return
*/
public static synchronized JdbcSchema makeDB(DataSource dataSource) {
makeFactory();
factory.clearDB(dataSource);

JdbcSchema db = null;
SoftReference ref = (SoftReference) dbMap.get(dataSource);
if (ref != null) {
db = (JdbcSchema) ref.get();
}
if (db == null) {
db = factory.makeDB(dataSource);
dbMap.put(dataSource, new SoftReference(db));
}

sweepDB();

return db;
}
/**
* Clear information in a JdbcSchema associated with a DataSource.
*
* @param dataSource
*/
public static synchronized void clearDB(DataSource dataSource) {
makeFactory();

public static synchronized JdbcSchema makeDB(DataSource dataSource) {
SoftReference ref = (SoftReference) dbMap.get(dataSource);
if (ref != null) {
JdbcSchema db = (JdbcSchema) ref.get();
if (db != null) {
factory.clearDB(db);
db.clear();
} else {
dbMap.remove(dataSource);
}
}
sweepDB();
}

/**
* Remove a JdbcSchema associated with a DataSource.
*
* @param dataSource
*/
public static synchronized void removeDB(DataSource dataSource) {
makeFactory();
return factory.makeDB(dataSource);

SoftReference ref = (SoftReference) dbMap.remove(dataSource);
if (ref != null) {
JdbcSchema db = (JdbcSchema) ref.get();
if (db != null) {
factory.removeDB(db);
db.remove();
}
}
sweepDB();
}

/**
* Every SWEEP_COUNT calls to this method, go through all elements of
* the dbMap removing all that either have null values (null SoftReference)
* or those with SoftReference with null content.
*/
private static void sweepDB() {
if (sweepDBCount > SWEEP_COUNT) {
Iterator it = dbMap.values().iterator();
while (it.hasNext()) {
SoftReference ref = (SoftReference) it.next();
if ((ref == null) || (ref.get() == null)) {
try {
it.remove();
} catch (Exception ex) {
// Should not happen, but might still like to
// know that something's funky.
LOGGER.warn(ex);
}
}

}
// reset
sweepDBCount = 0;
}
}


//
// Types of column usages.
//
Expand Down Expand Up @@ -1132,6 +1227,11 @@ protected void clear() {
catalog = null;
tables.clear();
}
protected void remove() {
// set ALL instance variables to null
clear();
dataSource = null;
}

/**
* This is used for testing allowing one to load tables and their columns
Expand Down

0 comments on commit 98796df

Please sign in to comment.