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]

Reply via email to