Author: rhauch
Date: 2008-12-11 14:42:19 -0500 (Thu, 11 Dec 2008)
New Revision: 681
Added:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/ChangeLogEntity.java
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModel.java
Log:
DNA-40
Added a table to store the change log, and changed BasicModel to include it in its schema
(though it is not currently populated in BasicModel). Also added some explanatory
JavaDocs to BasicModel.
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModel.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModel.java 2008-12-11
17:41:47 UTC (rev 680)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/basic/BasicModel.java 2008-12-11
19:42:19 UTC (rev 681)
@@ -26,13 +26,65 @@
import org.hibernate.ejb.Ejb3Configuration;
import org.jboss.dna.connector.store.jpa.JpaConnectorI18n;
import org.jboss.dna.connector.store.jpa.Model;
+import org.jboss.dna.connector.store.jpa.models.common.ChangeLogEntity;
import org.jboss.dna.connector.store.jpa.models.common.NamespaceEntity;
import org.jboss.dna.graph.ExecutionContext;
+import org.jboss.dna.graph.requests.CopyBranchRequest;
+import org.jboss.dna.graph.requests.DeleteBranchRequest;
+import org.jboss.dna.graph.requests.MoveBranchRequest;
+import org.jboss.dna.graph.requests.ReadBranchRequest;
import org.jboss.dna.graph.requests.processor.RequestProcessor;
/**
* Database model that stores node properties as opaque records and children as
transparent records. Large property values are
* stored separately.
+ * <p>
+ * The set of tables used in this model includes:
+ * <ul>
+ * <li>Namespaces - the set of namespace URIs used in paths, property names, and
property values.</li>
+ * <li>Properties - the properties for each node, stored in a serialized (and
optionally compressed) form.</li>
+ * <li>Large values - property values larger than a certain size will be broken out
into this table, where they are tracked by
+ * their SHA-1 has and shared by all properties that have that same value. The values are
stored in a binary (and optionally
+ * compressed) form.</li>
+ * <li>Children - the children for each node, where each child is represented by a
separate record. This approach makes it
+ * possible to efficiently work with nodes containing large numbers of children, where
adding and removing child nodes is largely
+ * independent of the number of children. Also, working with properties is also
completely independent of the number of child
+ * nodes.</li>
+ * <li>Subgraph - a working area for efficiently computing the space of a subgraph;
see below</li>
+ * <li>Change log - a record of the changes that have been made to the repository.
This is used to distribute change events across
+ * multiple distributed processes, and to allow a recently-connected client to identify
the set of changes that have been made
+ * since a particular time or date. Changes are serialized into a binary, compressed
format.</i></li>
+ * <li>Options - the parameters for this store's configuration (common to all
models)</li>
+ * </ul>
+ * </p>
+ * <h3>Subgraph queries</h3>
+ * <p>
+ * This database model contains two tables that are used in an efficient mechanism to
find all of the nodes in the subgraph below
+ * a certain node. This process starts by creating a record for the subgraph query, and
then proceeds by executing a join to find
+ * all the children of the top-level node, and inserting them into the database (in a
working area associated with the subgraph
+ * query). Then, another join finds all the children of those children and inserts them
into the same working area. This continues
+ * until the maximum depth has been reached, or until there are no more children
(whichever comes first). All of the nodes in the
+ * subgraph are then represented by records in the working area, and can be used to
quickly and efficient work with the subgraph
+ * nodes. When finished, the mechanism deletes the records in the working area associated
with the subgraph query.
+ * </p>
+ * <p>
+ * This subgraph query mechanism is extremely efficient, performing one join/insert
statement <i>per level of the subgraph</i>,
+ * and is completely independent of the number of nodes in the subgraph. For example,
consider a subgraph of node A, where A has
+ * 10 children, and each child contains 10 children, and each grandchild contains 10
children. This subgraph has a total of 1111
+ * nodes (1 root + 10 children + 10*10 grandchildren + 10*10*10 great-grandchildren).
Finding the nodes in this subgraph would
+ * normally require 1 query per node (in other words, 1111 queries). But with this
subgraph query mechanism, all of the nodes in
+ * the subgraph can be found with 1 insert plus 4 additional join/inserts.
+ * </p>
+ * <p>
+ * This mechanism has the added benefit that the set of nodes in the subgraph are kept in
a working area in the database, meaning
+ * they don't have to be pulled into memory.
+ * </p>
+ * <p>
+ * Subgraph queries are used to efficiently process a number of different requests,
including {@link ReadBranchRequest},
+ * {@link DeleteBranchRequest}, {@link MoveBranchRequest}, and {@link CopyBranchRequest}.
Processing each of these kinds of
+ * requests requires knowledge of the subgraph, and in fact all but the
<code>ReadBranchRequest</code> need to know the complete
+ * subgraph.
+ * </p>
*
* @author Randall Hauch
*/
@@ -76,6 +128,7 @@
configurator.addAnnotatedClass(ChildId.class);
configurator.addAnnotatedClass(SubgraphQueryEntity.class);
configurator.addAnnotatedClass(SubgraphNodeEntity.class);
+ configurator.addAnnotatedClass(ChangeLogEntity.class);
// Set the cache information for each persistent class ...
// configurator.setProperty("hibernate.ejb.classcache." +
KidpackNode.class.getName(), "read-write");
Added:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/ChangeLogEntity.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/ChangeLogEntity.java
(rev 0)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/ChangeLogEntity.java 2008-12-11
19:42:19 UTC (rev 681)
@@ -0,0 +1,148 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa.models.common;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import org.hibernate.annotations.Index;
+import org.jboss.dna.graph.properties.DateTime;
+import org.jboss.dna.graph.properties.basic.JodaDateTime;
+
+/**
+ * Represents a record of the changes that have been made to the repository. The actual
change events are serialized and stored in
+ * a binary (and compressed) format.
+ *
+ * @author Randall Hauch
+ */
+@Entity
+@Table( name = "DNA_CHANGELOG" )
+(a)org.hibernate.annotations.Table( appliesTo = "DNA_CHANGELOG", indexes =
@Index( name = "NS_CHANGE_TS_INX", columnNames = {"UTC_TIMESTAMP"} )
)
+@NamedQueries( {
+ @NamedQuery( name = "ChangeLogEntity.findBetween", query = "select
entry from ChangeLogEntity as entry where entry.timestampInUtc >= :start and
entry.timestampInUtc <= :end" ),
+ @NamedQuery( name = "ChangeLogEntity.deleteBefore", query = "delete
ChangeLogEntity entry where entry.timestampInUtc < :timestamp" )} )
+public class ChangeLogEntity {
+
+ @Id
+ @GeneratedValue( strategy = GenerationType.AUTO )
+ @Column( name = "ID", updatable = false )
+ private Long id;
+
+ @Column( name = "USERNAME", updatable = false, nullable = false, length =
64, unique = false )
+ private String username;
+
+ @Column( name = "UTC_TIMESTAMP", updatable = false, nullable = false,
unique = false )
+ private long timestampInUtc;
+
+ @Column( name = "CHANGE_COUNT", updatable = false, nullable = false, unique
= false )
+ private int numChanges;
+
+ @Lob
+ @Column( name = "CHANGES", updatable = false, nullable = false, unique =
false )
+ private byte[] changes;
+
+ public ChangeLogEntity( String username,
+ DateTime timestamp,
+ int numChanges,
+ byte[] changes ) {
+ this.username = username;
+ this.timestampInUtc = timestamp.toUtcTimeZone().getMilliseconds();
+ this.numChanges = numChanges;
+ this.changes = changes;
+ }
+
+ /**
+ * @return id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @return username
+ */
+ public String getUsername() {
+ return username;
+ }
+
+ /**
+ * @return timestampInUtc
+ */
+ public long getTimestampInUtc() {
+ return timestampInUtc;
+ }
+
+ /**
+ * @return changes
+ */
+ public byte[] getChanges() {
+ return changes;
+ }
+
+ /**
+ * @return numChanges
+ */
+ public int getNumChanges() {
+ return numChanges;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof ChangeLogEntity) {
+ ChangeLogEntity that = (ChangeLogEntity)obj;
+ return id.equals(that.id);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "" + numChanges + " changes by " + username + "
at " + new JodaDateTime(timestampInUtc);
+ }
+}
Property changes on:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/models/common/ChangeLogEntity.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain