You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xindice-dev@xml.apache.org by vg...@apache.org on 2008/11/09 22:52:26 UTC

svn commit: r712565 - in /xml/xindice/trunk: ./ java/src/org/apache/xindice/client/xmldb/xmlrpc/ java/src/org/apache/xindice/server/rpc/messages/ java/src/org/apache/xindice/util/

Author: vgritsenko
Date: Sun Nov  9 13:52:26 2008
New Revision: 712565

URL: http://svn.apache.org/viewvc?rev=712565&view=rev
Log:
Optimized transmission of collection's symbol table between server and
the client for reduced traffic and better performance.


Modified:
    xml/xindice/trunk/java/src/org/apache/xindice/client/xmldb/xmlrpc/CollectionImpl.java
    xml/xindice/trunk/java/src/org/apache/xindice/server/rpc/messages/GetResource.java
    xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolDeserializer.java
    xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolSerializer.java
    xml/xindice/trunk/status.xml

Modified: xml/xindice/trunk/java/src/org/apache/xindice/client/xmldb/xmlrpc/CollectionImpl.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/client/xmldb/xmlrpc/CollectionImpl.java?rev=712565&r1=712564&r2=712565&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/client/xmldb/xmlrpc/CollectionImpl.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/client/xmldb/xmlrpc/CollectionImpl.java Sun Nov  9 13:52:26 2008
@@ -31,6 +31,7 @@
 import org.apache.xindice.server.rpc.RPCMessageInterface;
 import org.apache.xindice.util.SymbolDeserializer;
 import org.apache.xindice.xml.TextWriter;
+import org.apache.xindice.xml.SymbolTable;
 import org.apache.xindice.xml.dom.DOMParser;
 import org.apache.xindice.xml.dom.DocumentImpl;
 import org.apache.xmlrpc.XmlRpcException;
@@ -73,6 +74,11 @@
     private XmlRpcClient client;
 
     /**
+     * Cached symbol table
+     */
+    private SymbolDeserializer symsDeserializer;
+
+    /**
      * Creates new <code>CollectionImpl</code> instance representing connection
      * to server collection.
      *
@@ -96,6 +102,8 @@
                                      FaultCodes.COL_COLLECTION_NOT_FOUND,
                                      "Collection not found: " + collPath);
         }
+
+        symsDeserializer = new SymbolDeserializer();
     }
 
     /**
@@ -162,6 +170,7 @@
             params.put(RPCDefaultMessage.COLLECTION, collPath);
             params.put(RPCDefaultMessage.NAME, id);
             params.put(RPCDefaultMessage.COMPRESSED, "true");
+            params.put(RPCDefaultMessage.TIMESTAMP, Long.toString(symsDeserializer.getLastModified()));
 
             Object result = runRemoteCommand("GetResource", params);
 
@@ -172,15 +181,15 @@
             } else if (result instanceof Map) {
                 // Result is compressed XML.
                 Map compressed = (Map) result;
-                SymbolDeserializer symbolDeserial = new SymbolDeserializer();
-                return new XMLResourceImpl(id, id, this, symbolDeserial.getSymbols(compressed), (byte[]) compressed.get("document"));
+                SymbolTable syms = symsDeserializer.getSymbols(compressed);
+                return new XMLResourceImpl(id, id, this, syms, (byte[]) compressed.get("document"));
 
             } else if (result instanceof byte[]) {
                 // Result is binary.
                 return new BinaryResourceImpl(id, this, (byte[]) result);
 
             } else {
-                // Result is XML.
+                // Result is XML string.
                 return new XMLResourceImpl(id, this, (String) result);
             }
 

Modified: xml/xindice/trunk/java/src/org/apache/xindice/server/rpc/messages/GetResource.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/server/rpc/messages/GetResource.java?rev=712565&r1=712564&r2=712565&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/server/rpc/messages/GetResource.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/server/rpc/messages/GetResource.java Sun Nov  9 13:52:26 2008
@@ -39,10 +39,7 @@
  */
 public class GetResource extends RPCDefaultMessage {
 
-    private static final Log log = LogFactory.getLog(GetResource.class);
-
     public Map execute(Map message) throws Exception {
-
         if (!message.containsKey(COLLECTION)) {
             throw new Exception(MISSING_COLLECTION_PARAM);
         }
@@ -64,28 +61,25 @@
 
         } else if (message.containsKey(COMPRESSED)) {
             // Compressed XML resource
-            SymbolSerializer symbolSerializer = new SymbolSerializer(col.getSymbols());
 
-            long timestamp = 1;
-            /* TODO: Timestamp optimization.
-               Longs are causing problems with XML-RPC
-               so we'll try to get everything working without them.
-            if (!message.containsKey(TIMESTAMP)) {
-                throw new Exception(MISSING_TIMESTAMP_PARAM);
-            }
-            int timestamp = ((Integer) message.get("timestamp")).intValue();
-            */
+            // Document might be compressed (with bytes) or not. In a latter case, send a string.
+            CompressedDocument doc = (CompressedDocument) obj.getValue();
+            if (doc.getDataBytes() != null) {
+                SymbolSerializer symbolSerializer = new SymbolSerializer(col.getSymbols());
+
+                // Get client's symbol table timestamp
+                long timestamp = 0;
+                if (message.containsKey(TIMESTAMP)) {
+                    timestamp = Long.parseLong((String) message.get("timestamp"));
+                }
 
-            // Document might be compressed (with bytes) or not. In a latter case, convert to string.
-            Document doc = (Document) obj.getValue();
-            if (/*( timestamp != -1) &&*/ ((CompressedDocument) doc).getDataBytes() != null) {
-                result.put(RESULT, symbolSerializer.convertFromDocument(doc, timestamp));
+                result.put(RESULT, symbolSerializer.serialize(doc, timestamp));
             } else {
                 result.put(RESULT, TextWriter.toString(doc));
             }
 
         } else {
-            // XML resource
+            // Uncompressed XML resource
             Document doc = (Document) obj.getValue();
             result.put(RESULT, TextWriter.toString(doc));
         }

Modified: xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolDeserializer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolDeserializer.java?rev=712565&r1=712564&r2=712565&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolDeserializer.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolDeserializer.java Sun Nov  9 13:52:26 2008
@@ -19,13 +19,14 @@
 
 package org.apache.xindice.util;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.xindice.xml.SymbolTable;
 import org.apache.xindice.xml.SymbolTableSymbols;
 import org.apache.xindice.xml.dom.DocumentImpl;
 
 import org.w3c.dom.Document;
 
-import java.util.Hashtable;
 import java.util.Map;
 
 /**
@@ -35,66 +36,71 @@
  * @version $Revision$, $Date$
  */
 public final class SymbolDeserializer {
-    private static final SymbolTableSymbols hcSyms = SymbolTableSymbols.getInstance();
+
+    private static final Log log = LogFactory.getLog(SymbolSerializer.class);
 
     /**
      * The collection's SymbolTable
      */
-    private SymbolTable syms;
+    private final SymbolTable syms;
 
     /**
      * Last time we caught a SymbolTable modification
      */
     private long lastMod;
 
+
+    public SymbolDeserializer() {
+        this.syms = new SymbolTable();
+    }
+
     /**
-     * convertToDocument converts the compressed Hashtable to
-     * a DOM Document.
+     * getSymbols returns the Symbol Table being managed by this
+     * deserializer.
      *
-     * @param buffer The Hashtable
-     * @return The Document
+     * @return The Symbol Table
      */
-    public Document convertToDocument(Hashtable buffer) {
-        SymbolTable s = getSymbols(buffer);
-        return new DocumentImpl((byte[]) buffer.get("document"), s, null);
+    public SymbolTable getSymbols() {
+        return syms;
     }
 
     /**
+     * getLastModified returns the last modified time stamp of the
+     * client's image of the managed symbol table.
+     *
+     * @return The last modified stamp
+     */
+    public long getLastModified() {
+        return lastMod;
+    }
+    
+    /**
      * getSymbols returns the current SymbolTable image for the
      * server-side Collection that is being managed.  The Symbol
-     * table is shipped as part of an Hashtable when the server
+     * table is shipped as part of an Map when the server
      * has determined that its image of the SymbolTable is out of
      * date.  This method either returns the current image or
-     * extracts the new image from the Hashtable.
+     * extracts the new image from the Map.
      *
-     * @param buffer The Hashtable
+     * @param buffer The Map
      * @return The Symbol Table
      */
     public SymbolTable getSymbols(Map buffer) {
-        //if ( ((Long) buffer.get("timestamp")).longValue() != lastMod ) {
-        // lastMod = ((Long) buffer.get("timestamp")).longValue();
-
-        Document doc = new DocumentImpl((byte[]) buffer.get("symbols"), hcSyms, null);
-
-        if (syms == null) {
-            syms = new SymbolTable();
+        byte[] symBytes = (byte[]) buffer.get("symbols");
+        if (symBytes != null) {
+            String ts = (String) buffer.get("timestamp");
+            if (log.isDebugEnabled()) {
+                log.info("Receiving symbols. Client ts=" + lastMod + ", Server ts=" + ts);
+            }
+
+            Document doc = new DocumentImpl(symBytes, SymbolTableSymbols.getInstance(), null);
+            synchronized (syms) {
+                syms.streamFromXML(doc.getDocumentElement());
+                // Server v1.1 won't be sending timestamp. Will use 0.
+                lastMod = ts == null ? 0 : Long.parseLong(ts);
+            }
         }
 
-        synchronized (syms) {
-            syms.streamFromXML(doc.getDocumentElement());
-        }
-        // }
         return syms;
     }
-
-    /**
-     * getLastModified returns the last modified time stamp of the
-     * client's image of the managed Symbol Table.
-     *
-     * @return The last modified stamp
-     */
-    public long getLastModified() {
-        return lastMod;
-    }
 }
-

Modified: xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolSerializer.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolSerializer.java?rev=712565&r1=712564&r2=712565&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolSerializer.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/util/SymbolSerializer.java Sun Nov  9 13:52:26 2008
@@ -30,7 +30,8 @@
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
-import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * SymbolSerializer is a utility class for managing SymbolTables in
@@ -42,8 +43,6 @@
 
     private static final Log log = LogFactory.getLog(SymbolSerializer.class);
 
-    private static final SymbolTableSymbols hcSyms = SymbolTableSymbols.getInstance();
-
     /**
      * The collection's SymbolTable
      */
@@ -65,75 +64,75 @@
     }
 
     /**
-     * getSymBuffer returns a new Hashtable that includes a
+     * getSymbols returns the Symbol Table being managed by this
+     * Serializer.
+     *
+     * @return The Symbol Table
+     */
+    public SymbolTable getSymbols() {
+        return syms;
+    }
+
+    /**
+     * getLastModified returns a time stamp of the last server-side
+     * modified of the Symbol Table.  This is used to determine
+     * whether or not to regenerate the byte stream, and whether
+     * the client will need a new copy of the Symbol Table.
+     *
+     * @return Last modified stamp
+     */
+    public long getLastModified() {
+        return syms.getLastModified();
+    }
+    
+    /**
+     * getSymBuffer returns a new Map that optionally includes a
      * reference to the SymbolTable's byte array image for wire
-     * transmission.  Depending on whether the client is up to
-     * date, convertFromDocument will remove this reference.
+     * transmission.
      *
-     * @return A new Hashtable
+     * @return A new Map
      */
-    public Hashtable getSymBuffer() {
+    private Map getSymBuffer(long remoteLastMod) {
         long lm = syms.getLastModified();
-        if (lm > lastMod) {
+        if (lm != lastMod) {
             DocumentImpl doc = new DocumentImpl();
-            doc.setSymbols(hcSyms);
+            doc.setSymbols(SymbolTableSymbols.getInstance());
 
             synchronized (syms) {
-                Element elem = syms.streamToXML(doc);
-                doc.appendChild(elem);
+                Element element = syms.streamToXML(doc);
+                doc.appendChild(element);
 
-                symBytes = DOMCompressor.compress(doc, hcSyms);
+                symBytes = DOMCompressor.compress(doc, SymbolTableSymbols.getInstance());
                 lastMod = lm;
             }
         }
 
-        Hashtable result = new Hashtable();
-        //result.put("timestamp", new Long(lm));
-        result.put("symbols", symBytes);
+        Map result = new HashMap(5);
+        if (remoteLastMod != lastMod) {
+            if (log.isDebugEnabled()) {
+                log.info("Sending symbols. Client ts=" + remoteLastMod + ", Server ts=" + lastMod);
+            }
+            result.put("timestamp", Long.toString(lastMod));
+            result.put("symbols", symBytes);
+        }
+
         return result;
     }
 
     /**
-     * convertFromDocument converts a DOM Document into an
-     * Hashtable that, depending on the time stamp, possibly
-     * includes a current image of the managed Collection's Symbol
-     * Table.
+     * Converts a DOM Document into a Map that, depending on the
+     * time stamp, possibly includes a current image of the managed
+     * Collection's Symbol Table.
      *
      * @param doc The Document to Convert
-     * @param stamp The client's last modified stamp
-     * @return The Hashtable
+     * @param remoteLastMod The client's last modified time stamp
+     * @return The Map
      */
-    public Hashtable convertFromDocument(Document doc, long stamp) {
-        Hashtable result = getSymBuffer();
+    public Map serialize(Document doc, long remoteLastMod) {
+        Map result = getSymBuffer(remoteLastMod);
         byte[] docBytes = ((CompressedDocument) doc).getDataBytes();
         result.put("document", docBytes);
 
-        /*if ( ((Long) result.get("timestamp")).longValue() == stamp ) {
-           result.put("symbols", EmptyBytes);
-        }*/
-
         return result;
     }
-
-    /**
-     * getSymbols returns the Symbol Table being managed by this
-     * Serializer.
-     *
-     * @return The Symbol Table
-     */
-    public SymbolTable getSymbols() {
-        return syms;
-    }
-
-    /**
-     * getLastModified returns a time stamp of the last server-side
-     * modified of the Symbol Table.  This is used to determine
-     * whether or not to regenerate the byte stream, and whether
-     * the client will need a new copy of the Symbol Table.
-     *
-     * @return Last modified stamp
-     */
-    public long getLastModified() {
-        return syms.getLastModified();
-    }
 }

Modified: xml/xindice/trunk/status.xml
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/status.xml?rev=712565&r1=712564&r2=712565&view=diff
==============================================================================
--- xml/xindice/trunk/status.xml (original)
+++ xml/xindice/trunk/status.xml Sun Nov  9 13:52:26 2008
@@ -70,19 +70,8 @@
         XQuery implementation.
       </action>
     </actions>
-    <actions priority="High Priority">
-      <action context="code" dev="open">
-        <strong>Caching</strong> Revisit implementation of documents cache in
-        the core Collection class. Clarify caching semantics, implement caching
-        for all use cases (compressed, uncompressed, binary objects). Ensure
-        dirty data can not be placed in the cache.
-      </action>
-      <action context="code" dev="open">
-        <strong>XML-RPC</strong> Extend Xindice XML-RPC API to optimize transmission
-        of collection's symbol table between server and the client for reduced
-        traffic and improved performance.
-      </action>
-    </actions>
+    <!--<actions priority="High Priority">-->
+    <!--</actions>-->
     <actions priority="Medium Priority">
       <action context="code" dev="open">
         <strong>Entity Catalogue</strong> Xindice should have internal XML entity
@@ -115,6 +104,10 @@
   <changes>
     <release version="1.2-dev" date="unreleased">
       <action dev="VG" type="update">
+        Optimized transmission of collection's symbol table between server and
+        the client for reduced traffic and better performance.
+      </action>
+      <action dev="VG" type="update">
         Update jetty to version 6.1.11.
       </action>
       <action dev="NS" type="update">