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();