bloritsch 01/05/04 12:43:12
Modified: src/org/apache/cocoon/reading Tag: xml-cocoon2
DatabaseReader.java
Log:
Made DatabaseReader cacheable. It's wicked fast. Great improvement.
Revision Changes Path
No revision
No revision
1.1.2.16 +115 -47
xml-cocoon/src/org/apache/cocoon/reading/Attic/DatabaseReader.java
Index: DatabaseReader.java
===================================================================
RCS file:
/home/cvs/xml-cocoon/src/org/apache/cocoon/reading/Attic/DatabaseReader.java,v
retrieving revision 1.1.2.15
retrieving revision 1.1.2.16
diff -u -r1.1.2.15 -r1.1.2.16
--- DatabaseReader.java 2001/04/30 14:17:33 1.1.2.15
+++ DatabaseReader.java 2001/05/04 19:43:07 1.1.2.16
@@ -26,13 +26,18 @@
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.excalibur.datasource.DataSourceComponent;
import org.apache.cocoon.Constants;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.ResourceNotFoundException;
import org.apache.cocoon.Roles;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Response;
-import org.apache.avalon.excalibur.datasource.DataSourceComponent;
+import org.apache.cocoon.caching.Cacheable;
+import org.apache.cocoon.caching.CacheValidity;
+import org.apache.cocoon.caching.NOPCacheValidity;
+import org.apache.cocoon.caching.TimeStampCacheValidity;
+import org.apache.cocoon.util.HashUtil;
import org.xml.sax.SAXException;
/**
@@ -42,9 +47,14 @@
*
* @author <a href="[EMAIL PROTECTED]">Berin Loritsch</a>
*/
-public class DatabaseReader extends AbstractReader implements Composable,
Configurable, Disposable {
- ComponentSelector dbselector;
- String dsn;
+public class DatabaseReader extends AbstractReader implements Composable,
Configurable, Disposable, Cacheable {
+ private ComponentSelector dbselector;
+ private String dsn;
+ private long lastModified = 0;
+ private Blob resource = null;
+ private Connection con = null;
+ private DataSourceComponent datasource = null;
+ private boolean doCommit = false;
private ComponentManager manager;
@@ -66,6 +76,48 @@
}
/**
+ * Set the <code>EntityResolver</code> the object model <code>Map</code>,
+ * the source and sitemap <code>Parameters</code> used to process the
request.
+ */
+ public void setup(EntityResolver resolver, Map objectModel, String src,
Parameters par)
+ throws ProcessingException, SAXException, IOException {
+ super.setup(resolver, objectModel, src, par);
+
+ try {
+ this.datasource = (DataSourceComponent) dbselector.select(dsn);
+ this.con = datasource.getConnection();
+
+ if (this.con.getAutoCommit() == true) {
+ this.con.setAutoCommit(false);
+ }
+
+ PreparedStatement statement = con.prepareStatement(getQuery());
+ statement.setString(1, this.source);
+ ResultSet set = statement.executeQuery();
+ if (set.next() == false) throw new
ResourceNotFoundException("There is no image with that key");
+
+ Response response = (Response)
objectModel.get(Constants.RESPONSE_OBJECT);
+ Request request = (Request)
objectModel.get(Constants.REQUEST_OBJECT);
+
+ if (this.modifiedSince(set, request, response)) {
+ this.resource = set.getBlob(1);
+
+ if (this.resource == null) {
+ throw new ResourceNotFoundException("There is no image
with that key");
+ }
+ }
+
+ this.doCommit = true;
+ } catch (Exception e) {
+ getLogger().warn("Could not get resource from Database", e);
+
+ this.doCommit = false;
+
+ throw new ResourceNotFoundException("DatabaseReader error:", e);
+ }
+ }
+
+ /**
* Generates the resource we need to retrieve verbatim from the
* database. Granted, this can be used for any resource from a
* database, so we may want to get rid of the bias toward images.
@@ -92,58 +144,22 @@
* the <code>source</code> string.
*/
public int generate() throws ProcessingException, SAXException,
IOException {
- DataSourceComponent datasource = null;
- Connection con = null;
int contentLength = 0;
try {
- datasource = (DataSourceComponent) dbselector.select(dsn);
- con = datasource.getConnection();
-
- if (con.getAutoCommit() == true) {
- con.setAutoCommit(false);
- }
-
- PreparedStatement statement = con.prepareStatement(getQuery());
- statement.setString(1, this.source);
- ResultSet set = statement.executeQuery();
- if (set.next() == false) throw new
ResourceNotFoundException("There is no image with that key");
-
- Response response = (Response)
objectModel.get(Constants.RESPONSE_OBJECT);
- Request request = (Request)
objectModel.get(Constants.REQUEST_OBJECT);
-
- if (this.modifiedSince(set, request, response)) {
- Blob object = set.getBlob(1);
-
- if (object == null) {
- throw new ResourceNotFoundException("There is no image
with that key");
- }
-
- contentLength = this.serialize(object, response);
- }
-
- con.commit();
+ return this.serialize(object, response);
} catch (IOException ioe) {
getLogger().debug("Assuming client reset stream");
- if (con != null) try {con.rollback();} catch (SQLException se) {}
+ this.doCommit = false;
} catch (Exception e) {
getLogger().warn("Could not get resource from Database", e);
- if (con != null) try {con.rollback();} catch (SQLException se) {}
+ this.doCommit = false;
throw new ResourceNotFoundException("DatabaseReader error:", e);
- } finally {
- if (con != null) {
- try {
- con.close();
- } catch (SQLException sqe) {
- getLogger().warn("Could not close connection", sqe);
- }
- }
-
- if (datasource != null) this.dbselector.release((Component)
datasource);
}
+
return contentLength; // length is unknown
}
@@ -194,8 +210,9 @@
if (lastModified != null) {
Timestamp modified = set.getTimestamp(lastModified, null);
+ this.lastModified = modified.getTime();
- response.setDateHeader("Last-Modified", modified.getTime());
+ response.setDateHeader("Last-Modified", this.lastModified);
return modified.getTime() >
request.getDateHeader("if-modified-since");
}
@@ -208,9 +225,9 @@
/**
* This method actually performs the serialization.
*/
- public int serialize(Blob object, Response response)
+ public int serialize(Response response)
throws IOException, SQLException {
- if (object == null) {
+ if (this.resource == null) {
throw new SQLException("The Blob is empty!");
}
@@ -235,6 +252,57 @@
out.flush();
return contentLength;
+ }
+
+ /**
+ * Generate the unique key.
+ * This key must be unique inside the space of this component.
+ *
+ * @return The generated key hashes the src
+ */
+ public long generateKey() {
+ return HashUtil.hash(this.source);
+ }
+
+ /**
+ * Generate the validity object.
+ *
+ * @return The generated validity object or <code>null</code> if the
+ * component is currently not cacheable.
+ */
+ public CacheValidity generateValidity() {
+ if (this.lastModified > 0) {
+ return new TimeStampCacheValidity(this.lastModified);
+ } else {
+ return new NOPCacheValidity();
+ }
+ }
+
+ public void recycle() {
+ super.recycle();
+ this.resource = null;
+ this.lastModified = 0;
+
+ if (this.con != null) {
+ if (this.doCommit) {
+ this.con.commit();
+ } else {
+ this.con.rollback();
+ }
+
+ try {
+ this.con.close();
+ } catch (SQLException se) {
+ getLogger().warn("Could not close connection", se);
+ }
+
+ this.con = null;
+ }
+
+ if (this.datasource != null) {
+ this.dbselector.release(this.datasource);
+ this.datasource = null;
+ }
}
/**
----------------------------------------------------------------------
In case of troubles, e-mail: [EMAIL PROTECTED]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]