You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2008/04/19 02:38:25 UTC

svn commit: r649733 - in /jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle: BundleDbPersistenceManager.java util/BundleBinding.java

Author: tripod
Date: Fri Apr 18 17:38:07 2008
New Revision: 649733

URL: http://svn.apache.org/viewvc?rev=649733&view=rev
Log:
JCR-1474 consistency check fails with derbypm

Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java?rev=649733&r1=649732&r2=649733&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/BundleDbPersistenceManager.java Fri Apr 18 17:38:07 2008
@@ -360,7 +360,7 @@
      * Sets the minimum blob size. This size defines the threshold of which
      * size a property is included in the bundle or is stored in the blob store.
      *
-     * @param minBlobSize the minimum blobsize in bytes.
+     * @param minBlobSize the minimum blob size in bytes.
      */
     public void setMinBlobSize(String minBlobSize) {
         this.minBlobSize = Integer.decode(minBlobSize).intValue();
@@ -488,7 +488,7 @@
     }
 
     /**
-     * Indicates if the username should be included when retrieving the tables
+     * Indicates if the user name should be included when retrieving the tables
      * during {@link #checkTablesExist()}.
      * <p/>
      * Please note that this currently only needs to be changed for oracle based
@@ -675,17 +675,14 @@
      * Checks a single bundle for inconsistencies, ie. inexistent child nodes
      * and inexistent parents.
      *
-     * @param id
-     *            node id for the bundle to check
-     * @param bundle
-     *            the bundle to check
-     * @param fix
-     *            if true, repair things that can be repaired
-     * @param modifications
-     *            if <code>fix == true</code>, collect the repaired
-     *            {@linkplain NodePropBundle bundles} here
+     * @param id node id for the bundle to check
+     * @param bundle the bundle to check
+     * @param fix if <code>true</code>, repair things that can be repaired
+     * @param modifications if <code>fix == true</code>, collect the repaired
+     * {@linkplain NodePropBundle bundles} here
      */
-    protected void checkBundleConsistency(NodeId id, NodePropBundle bundle, boolean fix, Collection modifications) {
+    protected void checkBundleConsistency(NodeId id, NodePropBundle bundle,
+                                          boolean fix, Collection modifications) {
         //log.info(name + ": checking bundle '" + id + "'");
 
         // look at the node's children
@@ -694,7 +691,7 @@
         while (iter.hasNext()) {
             NodePropBundle.ChildNodeEntry entry = (NodePropBundle.ChildNodeEntry) iter.next();
 
-            // skip check for system nodes (root, system root, version storage, nodetypes)
+            // skip check for system nodes (root, system root, version storage, node types)
             if (entry.getId().toString().endsWith("babecafebabe")) {
                 continue;
             }
@@ -760,35 +757,59 @@
             // get all node bundles in the database with a single sql statement,
             // which is (probably) faster than loading each bundle and traversing the tree
             ResultSet rs = null;
-            DataInputStream din = null;
             try {
-                String sql;
+                String sql = "select count(*) from " + schemaObjectPrefix + "BUNDLE";
+                Statement stmt = connectionManager.executeStmt(sql, new Object[0]);
+                try {
+                    rs = stmt.getResultSet();
+                    if (!rs.next()) {
+                        log.error("Could not retrieve total number of bundles. empty result set.");
+                        return;
+                    }
+                    total = rs.getInt(1);
+                } finally {
+                    closeResultSet(rs);
+                }
                 if (getStorageModel() == SM_BINARY_KEYS) {
-                    sql = "select NODE_ID, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
+                    sql = "select NODE_ID from " + schemaObjectPrefix + "BUNDLE";
                 } else {
-                    sql = "select NODE_ID_HI, NODE_ID_LO, BUNDLE_DATA from " + schemaObjectPrefix + "BUNDLE";
+                    sql = "select NODE_ID_HI, NODE_ID_LO from " + schemaObjectPrefix + "BUNDLE";
                 }
-                Statement stmt = connectionManager.executeStmt(sql, new Object[0]);
+                stmt = connectionManager.executeStmt(sql, new Object[0]);
                 rs = stmt.getResultSet();
 
-                // iterate over all nodebundles in the db
+                // iterate over all node bundles in the db
                 while (rs.next()) {
                     NodeId id;
-                    Blob blob;
                     if (getStorageModel() == SM_BINARY_KEYS) {
                         id = new NodeId(new UUID(rs.getBytes(1)));
-                        blob = rs.getBlob(2);
                     } else {
                         id = new NodeId(new UUID(rs.getLong(1), rs.getLong(2)));
-                        blob = rs.getBlob(3);
                     }
-                    din = new DataInputStream(blob.getBinaryStream());
+
+                    // issuing 2nd statement to circumvent issue JCR-1474
+                    ResultSet bRs = null;
+                    byte[] data = null;
+                    try {
+                        Statement bSmt = connectionManager.executeStmt(bundleSelectSQL, getKey(id.getUUID()));
+                        bRs = bSmt.getResultSet();
+                        if (!bRs.next()) {
+                            throw new SQLException("bundle cannot be retrieved?");
+                        }
+                        Blob blob = bRs.getBlob(1);
+                        data = getBytes(blob);
+                    } finally {
+                        closeResultSet(bRs);
+                    }
+
+
                     try {
                         // parse and check bundle
-                        // check bundle will log any problems itself
+                        // checkBundle will log any problems itself
+                        DataInputStream din = new DataInputStream(new ByteArrayInputStream(data));
                         if (binding.checkBundle(din)) {
                             // reset stream for readBundle()
-                            din = new DataInputStream(blob.getBinaryStream());
+                            din = new DataInputStream(new ByteArrayInputStream(data));
                             NodePropBundle bundle = binding.readBundle(din, id);
                             checkBundleConsistency(id, bundle, fix, modifications);
                         } else {
@@ -799,13 +820,12 @@
                     }
                     count++;
                     if (count % 1000 == 0) {
-                        log.info(name + ": checked " + count + " bundles...");
+                        log.info(name + ": checked " + count + "/" + total + " bundles...");
                     }
                 }
             } catch (Exception e) {
                 log.error("Error loading bundle", e);
             } finally {
-                IOUtils.closeQuietly(din);
                 closeResultSet(rs);
                 total = count;
             }
@@ -1048,8 +1068,7 @@
                 }
                 result.add(current);
             }
-            ListNodeIdIterator it = new ListNodeIdIterator(result);
-            return it;
+            return new ListNodeIdIterator(result);
         } catch (SQLException e) {
             String msg = "getAllNodeIds failed.";
             log.error(msg, e);
@@ -1068,12 +1087,36 @@
     }
     
     /**
+     * Reads the blob's bytes and returns it. this is a helper method to
+     * circumvent issue JCR-1039 and JCR-1474
+     * @param blob blob to read
+     * @return bytes of the blob
+     * @throws SQLException if an SQL error occurs
+     * @throws IOException if an I/O error occurs
+     */
+    private byte[] getBytes(Blob blob) throws SQLException, IOException {
+        InputStream in = null;
+        try {
+            long length = blob.length();
+            byte[] bytes = new byte[(int) length];
+            in = blob.getBinaryStream();
+            int read, pos = 0;
+            while ((read = in.read(bytes, pos, bytes.length - pos)) > 0) {
+                pos += read;
+            }
+            return bytes;
+        } finally {
+            IOUtils.closeQuietly(in);
+        }
+    }
+
+    /**
      * Loads a bundle from the underlying system and optionally performs
      * a check on the bundle first.
      *
      * @param id the node id of the bundle
      * @param checkBeforeLoading check the bundle before loading it and log
-     *                           detailed informations about it (slower)
+     *                           detailed information about it (slower)
      * @return the loaded bundle or <code>null</code> if the bundle does not
      *         exist.
      * @throws ItemStateException if an error while loading occurs.
@@ -1082,7 +1125,6 @@
             throws ItemStateException {
         ResultSet rs = null;
         InputStream in = null;
-        byte[] bytes = null;
         try {
             Statement stmt = connectionManager.executeStmt(bundleSelectSQL, getKey(id.getUUID()));
             rs = stmt.getResultSet();
@@ -1090,14 +1132,7 @@
                 return null;
             }
             Blob b = rs.getBlob(1);
-            // JCR-1039: pre-fetch/buffer blob data
-            long length = b.length();
-            bytes = new byte[(int) length];
-            in = b.getBinaryStream();
-            int read, pos = 0;
-            while ((read = in.read(bytes, pos, bytes.length - pos)) > 0) {
-                pos += read;
-            }
+            byte[] bytes = getBytes(b);
             DataInputStream din = new DataInputStream(new ByteArrayInputStream(bytes));
             
             if (checkBeforeLoading) {
@@ -1111,7 +1146,7 @@
             }
             
             NodePropBundle bundle = binding.readBundle(din, id);
-            bundle.setSize(length);
+            bundle.setSize(bytes.length);
             return bundle;
         } catch (Exception e) {
             String msg = "failed to read bundle: " + id + ": " + e;
@@ -1347,15 +1382,15 @@
     /**
      * logs an sql exception
      * @param message the message
-     * @param se the exception
+     * @param e the exception
      */
-    protected void logException(String message, SQLException se) {
+    protected void logException(String message, SQLException e) {
         if (message != null) {
             log.error(message);
         }
-        log.error("       Reason: " + se.getMessage());
-        log.error("   State/Code: " + se.getSQLState() + "/" + se.getErrorCode());
-        log.debug("   dump:", se);
+        log.error("       Reason: " + e.getMessage());
+        log.error("   State/Code: " + e.getSQLState() + "/" + e.getErrorCode());
+        log.debug("   dump:", e);
     }
 
     /**
@@ -1540,7 +1575,7 @@
 
     /**
      * Iterator over an in-memory list of node ids.
-     * This helper class is used by {@link BundleDbPersistenceManager#getAllNodeIds()}.
+     * This helper class is used by {@link BundleDbPersistenceManager#getAllNodeIds}.
      */
     private class ListNodeIdIterator implements NodeIdIterator {
 

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java?rev=649733&r1=649732&r2=649733&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/bundle/util/BundleBinding.java Fri Apr 18 17:38:07 2008
@@ -71,7 +71,7 @@
      * Deserializes a <code>NodePropBundle</code> from a data input stream.
      *
      * @param in the input stream
-     * @param id the nodeid for the new budle
+     * @param id the node id for the new bundle
      * @return the bundle
      * @throws IOException if an I/O error occurs.
      */
@@ -168,22 +168,22 @@
             String local = nameIndex.indexToString(in.readInt());
             Name nodeTypeName = NameFactoryImpl.getInstance().create(uri, local);
 
-            log.info("Serialzation Version: " + version);
-            log.info("NodeTypeName: " + nodeTypeName);
+            log.debug("Serialzation Version: " + version);
+            log.debug("NodeTypeName: " + nodeTypeName);
         } catch (IOException e) {
             log.error("Error while reading NodeTypeName: " + e);
             return false;
         }
         try {
             UUID parentUuid = readUUID(in);
-            log.info("ParentUUID: " + parentUuid);
+            log.debug("ParentUUID: " + parentUuid);
         } catch (IOException e) {
             log.error("Error while reading ParentUUID: " + e);
             return false;
         }
         try {
             String definitionId = in.readUTF();
-            log.info("DefinitionId: " + definitionId);
+            log.debug("DefinitionId: " + definitionId);
         } catch (IOException e) {
             log.error("Error while reading DefinitionId: " + e);
             return false;
@@ -191,7 +191,7 @@
         try {
             Name mixinName = readIndexedQName(in);
             while (mixinName != null) {
-                log.info("MixinTypeName: " + mixinName);
+                log.debug("MixinTypeName: " + mixinName);
                 mixinName = readIndexedQName(in);
             }
         } catch (IOException e) {
@@ -201,7 +201,7 @@
         try {
             Name propName = readIndexedQName(in);
             while (propName != null) {
-                log.info("PropertyName: " + propName);
+                log.debug("PropertyName: " + propName);
                 if (!checkPropertyState(in)) {
                     return false;
                 }
@@ -213,7 +213,7 @@
         }
         try {
             boolean hasUUID = in.readBoolean();
-            log.info("hasUUID: " + hasUUID);
+            log.debug("hasUUID: " + hasUUID);
         } catch (IOException e) {
             log.error("Error while reading 'hasUUID': " + e);
             return false;
@@ -222,7 +222,7 @@
             UUID cneUUID = readUUID(in);
             while (cneUUID != null) {
                 Name cneName = readQName(in);
-                log.info("ChildNodentry: " + cneUUID + ":" + cneName);
+                log.debug("ChildNodentry: " + cneUUID + ":" + cneName);
                 cneUUID = readUUID(in);
             }
         } catch (IOException e) {
@@ -233,7 +233,7 @@
         if (version >= VERSION_1) {
             try {
                 short modCount = readModCount(in);
-                log.info("modCount: " + modCount);
+                log.debug("modCount: " + modCount);
             } catch (IOException e) {
                 log.error("Error while reading mod cout: " + e);
                 return false;
@@ -315,7 +315,7 @@
      * Deserializes a <code>PropertyState</code> from the data input stream.
      *
      * @param in the input stream
-     * @param id the property id for the new propert entry
+     * @param id the property id for the new property entry
      * @return the property entry
      * @throws IOException if an I/O error occurs.
      */
@@ -412,22 +412,22 @@
             type = in.readInt();
             short modCount = (short) ((type >> 16) | 0xffff);
             type &= 0xffff;
-            log.info("  PropertyType: " + PropertyType.nameFromValue(type));
-            log.info("  ModCount: " + modCount);
+            log.debug("  PropertyType: " + PropertyType.nameFromValue(type));
+            log.debug("  ModCount: " + modCount);
         } catch (IOException e) {
             log.error("Error while reading property type: " + e);
             return false;
         }
         try {
             boolean isMV = in.readBoolean();
-            log.info("  MultiValued: " + isMV);
+            log.debug("  MultiValued: " + isMV);
         } catch (IOException e) {
             log.error("Error while reading multivalued: " + e);
             return false;
         }
         try {
             String defintionId = in.readUTF();
-            log.info("  DefinitionId: " + defintionId);
+            log.debug("  DefinitionId: " + defintionId);
         } catch (IOException e) {
             log.error("Error while reading definition id: " + e);
             return false;
@@ -436,7 +436,7 @@
         int count;
         try {
             count = in.readInt();
-            log.info("  num values: " + count);
+            log.debug("  num values: " + count);
         } catch (IOException e) {
             log.error("Error while reading number of values: " + e);
             return false;
@@ -447,7 +447,7 @@
                     int size;
                     try {
                         size = in.readInt();
-                        log.info("  binary size: " + size);
+                        log.debug("  binary size: " + size);
                     } catch (IOException e) {
                         log.error("Error while reading size of binary: " + e);
                         return false;
@@ -455,7 +455,11 @@
                     if (InternalValue.USE_DATA_STORE && size == -2) {
                         try {
                             String s = in.readUTF();
-                            log.info("  global data store id: " + s);
+                            // truncate log output
+                            if (s.length() > 80) {
+                                s = s.substring(80) + "...";
+                            }
+                            log.debug("  global data store id: " + s);
                         } catch (IOException e) {
                             log.error("Error while reading blob id: " + e);
                             return false;
@@ -463,7 +467,7 @@
                     } else if (size == -1) {
                         try {
                             String s = in.readUTF();
-                            log.info("  blobid: " + s);
+                            log.debug("  blobid: " + s);
                         } catch (IOException e) {
                             log.error("Error while reading blob id: " + e);
                             return false;
@@ -473,7 +477,7 @@
                         byte[] data = new byte[size];
                         try {
                             in.readFully(data);
-                            log.info("  binary: " + data.length + " bytes");
+                            log.debug("  binary: " + data.length + " bytes");
                         } catch (IOException e) {
                             log.error("Error while reading inlined binary: " + e);
                             return false;
@@ -483,7 +487,7 @@
                 case PropertyType.DOUBLE:
                     try {
                         double d = in.readDouble();
-                        log.info("  double: " + d);
+                        log.debug("  double: " + d);
                     } catch (IOException e) {
                         log.error("Error while reading double value: " + e);
                         return false;
@@ -492,7 +496,7 @@
                 case PropertyType.LONG:
                     try {
                         double l = in.readLong();
-                        log.info("  long: " + l);
+                        log.debug("  long: " + l);
                     } catch (IOException e) {
                         log.error("Error while reading long value: " + e);
                         return false;
@@ -501,7 +505,7 @@
                 case PropertyType.BOOLEAN:
                     try {
                         boolean b = in.readBoolean();
-                        log.info("  boolean: " + b);
+                        log.debug("  boolean: " + b);
                     } catch (IOException e) {
                         log.error("Error while reading boolean value: " + e);
                         return false;
@@ -510,7 +514,7 @@
                 case PropertyType.NAME:
                     try {
                         Name name = readQName(in);
-                        log.info("  name: " + name);
+                        log.debug("  name: " + name);
                     } catch (IOException e) {
                         log.error("Error while reading name value: " + e);
                         return false;
@@ -519,7 +523,7 @@
                 case PropertyType.REFERENCE:
                     try {
                         UUID uuid = readUUID(in);
-                        log.info("  reference: " + uuid);
+                        log.debug("  reference: " + uuid);
                     } catch (IOException e) {
                         log.error("Error while reading reference value: " + e);
                         return false;
@@ -531,7 +535,7 @@
                     int len;
                     try {
                         len = in.readInt();
-                        log.info("  size of string value: " + len);
+                        log.debug("  size of string value: " + len);
                     } catch (IOException e) {
                         log.error("Error while reading size of string value: " + e);
                         return false;
@@ -539,7 +543,12 @@
                     try {
                         byte[] bytes = new byte[len];
                         in.readFully(bytes);
-                        log.info("  string: " + new String(bytes, "UTF-8"));
+                        String s = new String(bytes, "UTF-8");
+                        // truncate log output
+                        if (s.length() > 80) {
+                            s = s.substring(80) + "...";
+                        }
+                        log.debug("  string: " + s);
                     } catch (IOException e) {
                         log.error("Error while reading string value: " + e);
                         return false;
@@ -675,7 +684,7 @@
                     // because writeUTF(String) has a size limit of 64k,
                     // we're using write(byte[]) instead
                     byte[] bytes = val.toString().getBytes("UTF-8");
-                    out.writeInt(bytes.length); // lenght of byte[]
+                    out.writeInt(bytes.length); // length of byte[]
                     out.write(bytes);   // byte[]
             }
         }