You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2009/01/14 13:59:30 UTC

svn commit: r734374 - in /jackrabbit/branches/1.4/jackrabbit-core: ./ src/main/java/org/apache/jackrabbit/core/data/ src/main/java/org/apache/jackrabbit/core/data/db/ src/main/java/org/apache/jackrabbit/core/query/ src/test/java/org/apache/jackrabbit/c...

Author: jukka
Date: Wed Jan 14 04:59:10 2009
New Revision: 734374

URL: http://svn.apache.org/viewvc?rev=734374&view=rev
Log:
1.4: Merged revision 727402 (JCR-1838)

Modified:
    jackrabbit/branches/1.4/jackrabbit-core/   (props changed)
    jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java
    jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
    jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/   (props changed)
    jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java

Propchange: jackrabbit/branches/1.4/jackrabbit-core/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Jan 14 04:59:10 2009
@@ -1 +1 @@
-/jackrabbit/trunk/jackrabbit-core:653417,654078,654514,655917,656240,656655,656664,658583,668086,668147,672125,678788,679389,680135,681031,681287,682409,686688,691181,691550,694164,698200,698209,733080
+/jackrabbit/trunk/jackrabbit-core:653417,654078,654514,655917,656240,656655,656664,658583,668086,668147,672125,678788,679389,680135,681031,681287,682409,686688,691181,691550,694164,698200,698209,727402,733080

Modified: jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java?rev=734374&r1=734373&r2=734374&view=diff
==============================================================================
--- jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java (original)
+++ jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java Wed Jan 14 04:59:10 2009
@@ -162,6 +162,8 @@
         File temporary = null;
         try {
             temporary = newTemporaryFile();
+            DataIdentifier tempId = new DataIdentifier(temporary.getName());
+            usesIdentifier(tempId);
             // Copy the stream to the temporary file and calculate the
             // stream length and the message digest of the stream
             long length = 0;
@@ -212,7 +214,9 @@
                     throw new IOException(DIGEST + " collision: " + file);
                 }
             }
-
+            // this will also make sure that
+            // tempId is not garbage collected until here
+            inUse.remove(tempId);
             return new FileDataRecord(identifier, file);
         } catch (NoSuchAlgorithmException e) {
             throw new DataStoreException(DIGEST + " not available", e);
@@ -276,8 +280,9 @@
         int count = 0;
         if (file.isFile() && file.exists() && file.canWrite()) {
             synchronized (this) {
+                String fileName = file.getName();
                 if (file.lastModified() < min) {
-                    DataIdentifier id = new DataIdentifier(file.getName());
+                    DataIdentifier id = new DataIdentifier(fileName);
                     if (!inUse.containsKey(id)) {
                         file.delete();
                         count++;

Modified: jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java?rev=734374&r1=734373&r2=734374&view=diff
==============================================================================
--- jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java (original)
+++ jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java Wed Jan 14 04:59:10 2009
@@ -42,6 +42,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.WeakHashMap;
@@ -266,6 +267,11 @@
      * All data identifiers that are currently in use are in this set until they are garbage collected.
      */
     protected Map inUse = Collections.synchronizedMap(new WeakHashMap());
+    
+    /**
+     * The temporary identifiers that are currently in use.
+     */
+    protected List temporaryInUse = Collections.synchronizedList(new ArrayList());
 
     /**
      * {@inheritDoc}
@@ -274,9 +280,9 @@
         ResultSet rs = null;
         TempFileInputStream fileInput = null;
         ConnectionRecoveryManager conn = getConnection();
+        String id = null, tempId = null;
         try {
             conn.setAutoReconnect(false);
-            String id = null, tempId = null;            
             long now;            
             for (int i = 0; i < ConnectionRecoveryManager.TRIALS; i++) {
                 try {
@@ -300,6 +306,7 @@
                 log.error(msg);
                 throw new DataStoreException(msg);
             }
+            temporaryInUse.add(tempId);
             MessageDigest digest = getDigest();
             DigestInputStream dIn = new DigestInputStream(stream, digest);
             TrackingInputStream in = new TrackingInputStream(dIn);
@@ -354,6 +361,9 @@
         } catch (Exception e) {
             throw convert("Can not insert new record", e);
         } finally {
+            if (tempId != null) {
+                temporaryInUse.remove(tempId);
+            }
             conn.closeSilently(rs);
             putBack(conn);
             if (fileInput != null) {
@@ -386,13 +396,19 @@
     public synchronized int deleteAllOlderThan(long min) throws DataStoreException {
         ConnectionRecoveryManager conn = getConnection();
         try {
-            Iterator it = new ArrayList(inUse.keySet()).iterator();
-            while (it.hasNext()) {
+            ArrayList touch = new ArrayList();
+            for (Iterator it = new ArrayList(inUse.keySet()).iterator(); it.hasNext();) {
                 DataIdentifier identifier = (DataIdentifier) it.next();
                 if (identifier != null) {
-                    touch(identifier, 0);
+                    touch.add(identifier.toString());
                 }
             }
+            touch.addAll(temporaryInUse);
+            Iterator it = touch.iterator();
+            while (it.hasNext()) {
+                String key = (String) it.next();
+                updateLastModifiedDate(key, 0);
+            }
             // DELETE FROM DATASTORE WHERE LAST_MODIFIED<?
             PreparedStatement prep = conn.executeStmt(deleteOlderSQL, new Long[]{new Long(min)});
             return prep.getUpdateCount();
@@ -610,6 +626,10 @@
      */
     long touch(DataIdentifier identifier, long lastModified) throws DataStoreException {
         usesIdentifier(identifier);
+        return updateLastModifiedDate(identifier.toString(), lastModified);
+    }
+
+    private long updateLastModifiedDate(String key, long lastModified) throws DataStoreException {
         if (lastModified < minModifiedDate) {
             long now = System.currentTimeMillis();
             Long n = new Long(now);
@@ -617,7 +637,7 @@
             try {
                 // UPDATE DATASTORE SET LAST_MODIFIED = ? WHERE ID = ? AND LAST_MODIFIED < ?
                 conn.executeStmt(updateLastModifiedSQL, new Object[]{
-                        n, identifier.toString(), n
+                        n, key, n
                 });
                 return now;
             } catch (Exception e) {

Propchange: jackrabbit/branches/1.4/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/
            ('svn:mergeinfo' removed)

Modified: jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java?rev=734374&r1=734373&r2=734374&view=diff
==============================================================================
--- jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java (original)
+++ jackrabbit/branches/1.4/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/GarbageCollectorTest.java Wed Jan 14 04:59:10 2009
@@ -22,11 +22,11 @@
 import org.apache.jackrabbit.test.AbstractJCRTest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import EDU.oswego.cs.dl.util.concurrent.SynchronousChannel;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Iterator;
-
 import javax.jcr.Credentials;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
@@ -41,6 +41,61 @@
     /** logger instance */
     private static final Logger LOG = LoggerFactory.getLogger(GarbageCollectorTest.class);    
     
+    public void testConcurrentGC() throws Exception {
+        Node root = testRootNode;
+        Session session = root.getSession();
+        RepositoryImpl rep = (RepositoryImpl) session.getRepository();
+        if (rep.getDataStore() == null) {
+            LOG.info("testConcurrentGC skipped. Data store is not used.");
+            return;
+        }
+        final SynchronousChannel sync = new SynchronousChannel();
+        final Node node = root.addNode("slowBlob");
+        new Thread() {
+            public void run() {
+                try {
+                    node.setProperty("slowBlob", new InputStream() {
+                        int pos = 0;
+                        public int read() throws IOException {
+                            pos++;
+                            if (pos < 10000) {
+                                return pos % 80 == 0 ? '\n' : '.';
+                            } else if (pos == 10000) {
+                                try {
+                                    sync.put("x");
+                                    // deleted
+                                    sync.take();
+                                } catch (InterruptedException e) {
+                                    e.printStackTrace();
+                                }
+                                return 'x';
+                            }
+                            return -1;
+                        }
+                    });
+                    node.getSession().save();
+                    sync.put("saved");
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }.start();
+        assertEquals("x", sync.take());
+        GarbageCollector gc = ((SessionImpl) session).createDataStoreGarbageCollector();
+        gc.scan();
+        gc.stopScan();
+        gc.deleteUnused();
+        sync.put("deleted");
+        assertEquals("saved", sync.take());
+        InputStream in = node.getProperty("slowBlob").getStream();
+        for (int pos = 1; pos < 10000; pos++) {
+            int expected = pos % 80 == 0 ? '\n' : '.';
+            assertEquals(expected, in.read());
+        }
+        assertEquals('x', in.read());
+        in.close();
+    }
+
     public void testGC() throws Exception {
         Node root = testRootNode;
         Session session = root.getSession();