Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (revision 1381059)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (working copy)
@@ -425,17 +425,33 @@
[...create block...]
*/
+ PropertyId propId = new PropertyId(getNodeId(), name);
try {
- PropertyId propId = new PropertyId(getNodeId(), name);
return (PropertyImpl) itemMgr.getItem(propId);
} catch (AccessDeniedException ade) {
throw new ItemNotFoundException(name.toString());
} catch (ItemNotFoundException e) {
- // does not exist yet:
- // find definition for the specified property and create property
+ // does not exist yet or has been removed transiently:
+ // find definition for the specified property and (re-)create property
PropertyDefinitionImpl def = getApplicablePropertyDefinition(
name, type, multiValued, exactTypeMatch);
- PropertyImpl prop = createChildProperty(name, type, def);
+ PropertyImpl prop;
+ if (stateMgr.hasTransientItemStateInAttic(propId)) {
+ // remove from attic
+ try {
+ stateMgr.disposeTransientItemStateInAttic(stateMgr.getAttic().getItemState(propId));
+ } catch (ItemStateException ise) {
+ // shouldn't happen because we checked if it is in the attic
+ throw new RepositoryException(ise);
+ }
+ prop = (PropertyImpl) itemMgr.getItem(propId);
+ PropertyState state = (PropertyState) prop.getOrCreateTransientItemState();
+ state.setMultiValued(multiValued);
+ state.setType(type);
+ getNodeState().addPropertyName(name);
+ } else {
+ prop = createChildProperty(name, type, def);
+ }
status.set(CREATED);
return prop;
}
Index: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ReplacePropertyWhileOthersReadTest.java
===================================================================
--- jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ReplacePropertyWhileOthersReadTest.java (revision 0)
+++ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/ReplacePropertyWhileOthersReadTest.java (revision 0)
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ReplacePropertyWhileOthersReadTest...
+ */
+public class ReplacePropertyWhileOthersReadTest extends AbstractJCRTest {
+
+ private static final Logger log = LoggerFactory.getLogger(ReplacePropertyWhileOthersReadTest.class);
+
+ private final List values = new ArrayList();
+
+ private Node test;
+
+ private final Random rand = new Random();
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ test = testRootNode.addNode("test");
+ test.addMixin(mixReferenceable);
+ superuser.save();
+ values.add(vf.createValue("value"));
+ values.add(vf.createValue(new BigDecimal(1234)));
+ values.add(vf.createValue(Calendar.getInstance()));
+ values.add(vf.createValue(1.234));
+ values.add(vf.createValue(true));
+ values.add(vf.createValue(test));
+ values.add(vf.createValue(vf.createBinary(
+ new ByteArrayInputStream(new byte[0]))));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ test = null;
+ values.clear();
+ super.tearDown();
+ }
+
+ public void testAddRemove() throws Exception {
+ final Property prop = test.setProperty("prop", getRandomValue());
+ superuser.save();
+
+ Thread reader = new Thread(new Runnable() {
+
+ String path = prop.getPath();
+
+ public void run() {
+ // run for three seconds
+ long stop = System.currentTimeMillis()
+ + TimeUnit.SECONDS.toMillis(3);
+ while (System.currentTimeMillis() < stop) {
+ try {
+ Session s = getHelper().getSuperuserSession();
+ try {
+ s.getProperty(path);
+ } finally {
+ s.logout();
+ }
+ } catch (RepositoryException e) {
+ log.warn("", e);
+ }
+ }
+ }
+ });
+ Tail tail = Tail.start(new File("target", "jcr.log"),
+ "overwriting cached entry");
+ try {
+ reader.start();
+ while (reader.isAlive()) {
+ test.getProperty("prop").remove();
+ int type;
+ boolean isMultivalued;
+ if (rand.nextBoolean()) {
+ Value v = getRandomValue();
+ isMultivalued = false;
+ type = v.getType();
+ test.setProperty("prop", v);
+ } else {
+ Value[] v = getRandomMultiValue();
+ type = v[0].getType();
+ isMultivalued = true;
+ test.setProperty("prop", v);
+ }
+ superuser.save();
+ assertEquals(isMultivalued, test.getProperty("prop").isMultiple());
+ assertEquals(type, test.getProperty("prop").getType());
+ }
+ assertFalse("detected 'overwriting cached entry' messages in log",
+ tail.getLines().iterator().hasNext());
+ } finally {
+ tail.close();
+ }
+ }
+
+ private Value getRandomValue() {
+ return values.get(rand.nextInt(values.size()));
+ }
+
+ private Value[] getRandomMultiValue() {
+ return new Value[]{getRandomValue()};
+ }
+}
Property changes on: jackrabbit-core\src\test\java\org\apache\jackrabbit\core\ReplacePropertyWhileOthersReadTest.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision Rev URL
Added: svn:eol-style
+ native
Index: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java
===================================================================
--- jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java (revision 1381059)
+++ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/TestAll.java (working copy)
@@ -78,6 +78,7 @@
suite.addTestSuite(NPEandCMETest.class);
suite.addTestSuite(ConsistencyCheck.class);
suite.addTestSuite(RemoveAddNodeWithUUIDTest.class);
+ suite.addTestSuite(ReplacePropertyWhileOthersReadTest.class);
return suite;
}