Return-Path: Delivered-To: apmail-activemq-commits-archive@www.apache.org Received: (qmail 57048 invoked from network); 16 Jul 2008 15:18:47 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 16 Jul 2008 15:18:47 -0000 Received: (qmail 26415 invoked by uid 500); 16 Jul 2008 15:18:47 -0000 Delivered-To: apmail-activemq-commits-archive@activemq.apache.org Received: (qmail 26360 invoked by uid 500); 16 Jul 2008 15:18:46 -0000 Mailing-List: contact commits-help@activemq.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@activemq.apache.org Delivered-To: mailing list commits@activemq.apache.org Received: (qmail 26351 invoked by uid 99); 16 Jul 2008 15:18:46 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Jul 2008 08:18:46 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 16 Jul 2008 15:18:00 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id CAE5B2388A81; Wed, 16 Jul 2008 08:18:24 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r677302 [4/4] - in /activemq/sandbox/xindice-stripped: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/xindice/ src/main/java/org/apache/xindice/core/ src/main/java/org/apache/xindice/c... Date: Wed, 16 Jul 2008 15:18:22 -0000 To: commits@activemq.apache.org From: chirino@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080716151824.CAE5B2388A81@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/IntrospectionSupport.java URL: http://svn.apache.org/viewvc/activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/IntrospectionSupport.java?rev=677302&view=auto ============================================================================== --- activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/IntrospectionSupport.java (added) +++ activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/IntrospectionSupport.java Wed Jul 16 08:18:20 2008 @@ -0,0 +1,299 @@ +/** + * 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.xindice.util; + +import java.beans.PropertyEditor; +import java.beans.PropertyEditorManager; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +public final class IntrospectionSupport { + + private IntrospectionSupport() { + } + + public static boolean getProperties(Object target, Map props, String optionPrefix) { + + boolean rc = false; + if (target == null) { + throw new IllegalArgumentException("target was null."); + } + if (props == null) { + throw new IllegalArgumentException("props was null."); + } + + if (optionPrefix == null) { + optionPrefix = ""; + } + + Class clazz = target.getClass(); + Method[] methods = clazz.getMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + String name = method.getName(); + Class type = method.getReturnType(); + Class params[] = method.getParameterTypes(); + if ((name.startsWith("is") || name.startsWith("get")) && params.length == 0 && type != null && isSettableType(type)) { + + try { + + Object value = method.invoke(target, new Object[] {}); + if (value == null) { + continue; + } + + String strValue = convertToString(value, type); + if (strValue == null) { + continue; + } + if (name.startsWith("get")) { + name = name.substring(3, 4).toLowerCase() + + name.substring(4); + } else { + name = name.substring(2, 3).toLowerCase() + + name.substring(3); + } + props.put(optionPrefix + name, strValue); + rc = true; + + } catch (Throwable ignore) { + } + + } + } + + return rc; + } + + public static boolean setProperties(Object target, Map props, String optionPrefix) { + boolean rc = false; + if (target == null) { + throw new IllegalArgumentException("target was null."); + } + if (props == null) { + throw new IllegalArgumentException("props was null."); + } + + for (Iterator iter = props.keySet().iterator(); iter.hasNext();) { + String name = iter.next(); + if (name.startsWith(optionPrefix)) { + Object value = props.get(name); + name = name.substring(optionPrefix.length()); + if (setProperty(target, name, value)) { + iter.remove(); + rc = true; + } + } + } + return rc; + } + + public static Map extractProperties(Map props, String optionPrefix) { + if (props == null) { + throw new IllegalArgumentException("props was null."); + } + + HashMap rc = new HashMap(props.size()); + + for (Iterator iter = props.keySet().iterator(); iter.hasNext();) { + String name = (String)iter.next(); + if (name.startsWith(optionPrefix)) { + Object value = props.get(name); + name = name.substring(optionPrefix.length()); + rc.put(name, value); + iter.remove(); + } + } + + return rc; + } + + public static boolean setProperties(Object target, Map props) { + boolean rc = false; + + if (target == null) { + throw new IllegalArgumentException("target was null."); + } + if (props == null) { + throw new IllegalArgumentException("props was null."); + } + + for (Iterator iter = props.entrySet().iterator(); iter.hasNext();) { + Map.Entry entry = (Entry)iter.next(); + if (setProperty(target, (String)entry.getKey(), entry.getValue())) { + iter.remove(); + rc = true; + } + } + + return rc; + } + + public static boolean setProperty(Object target, String name, Object value) { + try { + Class clazz = target.getClass(); + Method setter = findSetterMethod(clazz, name); + if (setter == null) { + return false; + } + + // If the type is null or it matches the needed type, just use the + // value directly + if (value == null || value.getClass() == setter.getParameterTypes()[0]) { + setter.invoke(target, new Object[] {value}); + } else { + // We need to convert it + setter.invoke(target, new Object[] {convert(value, setter.getParameterTypes()[0])}); + } + return true; + } catch (Throwable ignore) { + return false; + } + } + + private static Object convert(Object value, Class type) throws URISyntaxException { + PropertyEditor editor = PropertyEditorManager.findEditor(type); + if (editor != null) { + editor.setAsText(value.toString()); + return editor.getValue(); + } + if (type == URI.class) { + return new URI(value.toString()); + } + return null; + } + + private static String convertToString(Object value, Class type) throws URISyntaxException { + PropertyEditor editor = PropertyEditorManager.findEditor(type); + if (editor != null) { + editor.setValue(value); + return editor.getAsText(); + } + if (type == URI.class) { + return ((URI)value).toString(); + } + return null; + } + + private static Method findSetterMethod(Class clazz, String name) { + // Build the method name. + name = "set" + name.substring(0, 1).toUpperCase() + name.substring(1); + Method[] methods = clazz.getMethods(); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + Class params[] = method.getParameterTypes(); + if (method.getName().equals(name) && params.length == 1 ) { + return method; + } + } + return null; + } + + private static boolean isSettableType(Class clazz) { + if (PropertyEditorManager.findEditor(clazz) != null) { + return true; + } + if (clazz == URI.class) { + return true; + } + if (clazz == Boolean.class) { + return true; + } + return false; + } + + public static String toString(Object target) { + return toString(target, Object.class); + } + + public static String toString(Object target, Class stopClass) { + LinkedHashMap map = new LinkedHashMap(); + addFields(target, target.getClass(), stopClass, map); + StringBuffer buffer = new StringBuffer(simpleName(target.getClass())); + buffer.append(" {"); + Set entrySet = map.entrySet(); + boolean first = true; + for (Iterator iter = entrySet.iterator(); iter.hasNext();) { + Map.Entry entry = (Map.Entry)iter.next(); + if (first) { + first = false; + } else { + buffer.append(", "); + } + buffer.append(entry.getKey()); + buffer.append(" = "); + appendToString(buffer, entry.getValue()); + } + buffer.append("}"); + return buffer.toString(); + } + + protected static void appendToString(StringBuffer buffer, Object value) { + buffer.append(value); + } + + public static String simpleName(Class clazz) { + String name = clazz.getName(); + int p = name.lastIndexOf("."); + if (p >= 0) { + name = name.substring(p + 1); + } + return name; + } + + private static void addFields(Object target, Class startClass, Class stopClass, LinkedHashMap map) { + + if (startClass != stopClass) { + addFields(target, startClass.getSuperclass(), stopClass, map); + } + + Field[] fields = startClass.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers()) + || Modifier.isPrivate(field.getModifiers())) { + continue; + } + + try { + field.setAccessible(true); + Object o = field.get(target); + if (o != null && o.getClass().isArray()) { + try { + o = Arrays.asList((Object[])o); + } catch (Throwable e) { + } + } + map.put(field.getName(), o); + } catch (Throwable e) { + e.printStackTrace(); + } + } + + } + +} Propchange: activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/IntrospectionSupport.java ------------------------------------------------------------------------------ svn:executable = * Added: activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/LockManager.java URL: http://svn.apache.org/viewvc/activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/LockManager.java?rev=677302&view=auto ============================================================================== --- activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/LockManager.java (added) +++ activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/LockManager.java Wed Jul 16 08:18:20 2008 @@ -0,0 +1,190 @@ +/* + * 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. + * + * $Id: LockManager.java 541508 2007-05-25 01:54:12Z vgritsenko $ + */ + +package org.apache.xindice.util; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * LockManager manages resource locks. A resource is any shared object that + * can be represented as a long. The LockManager should be constructed using + * the maximum number of concurrent clients a specific resource might have. + * + * @version $Revision: 541508 $, $Date: 2007-05-24 21:54:12 -0400 (Thu, 24 May 2007) $ + */ +public final class LockManager { + + private static final Log log = LogFactory.getLog(LockManager.class); + + private int maxLocks = 0; + private Map locks = new HashMap(); // Long to LockInfo + + public LockManager(int maxLocks) { + this.maxLocks = maxLocks; + } + + /** + * acquireSharedLock acquires a shared lock on a resource. Shared locks + * are typically used for reads. + */ + public void acquireSharedLock(long id) { + acquireSharedLock(new Long(id)); + } + + /** + * acquireSharedLock acquires a shared lock on a resource. Shared locks + * are typically used for reads. + */ + public void acquireSharedLock(Object key) { + LockInfo info; + synchronized (this) { + info = (LockInfo) locks.get(key); + if (info == null) { + info = new LockInfo(); + locks.put(key, info); + } + } + synchronized (info) { + while (info.count >= maxLocks) { + try { + info.wait(); + } catch (Exception e) { + if (log.isWarnEnabled()) { + log.warn("ignored exception", e); + } + } + } + info.count++; + } + } + + /** + * releaseSharedLock releases a shared lock on a resource. Shared locks + * are typically used for reads. + */ + public void releaseSharedLock(long id) { + releaseSharedLock(new Long(id)); + } + + /** + * releaseSharedLock releases a shared lock on a resource. Shared locks + * are typically used for reads. + */ + public void releaseSharedLock(Object key) { + LockInfo info; + synchronized (this) { + info = (LockInfo) locks.get(key); + } + if (info == null) { + return; + } + + synchronized (info) { + info.count--; + info.notify(); + if (info.count == 0) { + synchronized (this) { + locks.remove(key); + } + } + } + } + + /** + * acquireExclusiveLock acquires an exclusive lock on a resource. Exclusive + * locks are typically used for writes. + */ + public void acquireExclusiveLock(long id) { + acquireExclusiveLock(new Long(id)); + } + + /** + * acquireExclusiveLock acquires an exclusive lock on a resource. Exclusive + * locks are typically used for writes. + */ + public void acquireExclusiveLock(Object key) { + LockInfo info; + synchronized (this) { + info = (LockInfo) locks.get(key); + if (info == null) { + info = new LockInfo(); + locks.put(key, info); + } + } + synchronized (info) { + int total = 0; + int stolen = 0; + while (total < maxLocks && info.count >= maxLocks) { + try { + info.wait(); + } catch (Exception e) { + if (log.isWarnEnabled()) { + log.warn("ignored exception", e); + } + } + stolen = maxLocks - info.count; + total += stolen; + info.count += stolen; + } + } + } + + /** + * releaseExclusiveLock releases an exclusive lock on a resource. Exclusive + * locks are typically used for writes. + */ + public void releaseExclusiveLock(long id) { + releaseExclusiveLock(new Long(id)); + } + + /** + * releaseExclusiveLock releases an exclusive lock on a resource. Exclusive + * locks are typically used for writes. + */ + public void releaseExclusiveLock(Object key) { + LockInfo info; + synchronized (this) { + info = (LockInfo) locks.get(key); + } + if (info == null) { + return; + } + + synchronized (info) { + info.count = 0; + info.notify(); + if (info.count == 0) { + synchronized (this) { + locks.remove(key); + } + } + } + } + + /** + * LockInfo is just an int wrapper. + */ + private class LockInfo { + public int count = 0; + } +} Added: activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/package.html URL: http://svn.apache.org/viewvc/activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/package.html?rev=677302&view=auto ============================================================================== --- activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/package.html (added) +++ activemq/sandbox/xindice-stripped/src/main/java/org/apache/xindice/util/package.html Wed Jul 16 08:18:20 2008 @@ -0,0 +1,27 @@ + + + + Xindice utilities package. + + This package contains many of the utility classes required by Xindice + + + + Added: activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/BTreeFilerTest.java URL: http://svn.apache.org/viewvc/activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/BTreeFilerTest.java?rev=677302&view=auto ============================================================================== --- activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/BTreeFilerTest.java (added) +++ activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/BTreeFilerTest.java Wed Jul 16 08:18:20 2008 @@ -0,0 +1,51 @@ +/* + * 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. + * + * $Id: BTreeFilerTest.java 541504 2007-05-25 01:43:39Z vgritsenko $ + */ + +package org.apache.xindice.core.filer; + +import org.apache.xindice.core.data.Key; + +/** + * + * @version $Revision: 541504 $, $Date: 2007-05-24 21:43:39 -0400 (Thu, 24 May 2007) $ + * @author Vadim Gritsenko + */ +public class BTreeFilerTest extends FilerTestBase { + + public BTreeFilerTest(String name) { + super(name, new BTreeFiler()); + } + + /** + * Test to see if BTreeFiler reuses deleted pages. + */ + public void testFreePages() throws Exception { + long count = ((BTreeFiler) filer).getFileHeader().getTotalCount(); + int iterations = 10; + + Key key = new Key("key"); + for (int i = 0; i < iterations; i++) { + filer.writeRecord(key, TEST_VALUE); + assertTrue(filer.deleteRecord(key)); + } + + // Check that file did not grow (much) + assertTrue(count + 1 >= ((BTreeFiler) filer).getFileHeader().getTotalCount()); + } +} Added: activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/FSFilerTest.java URL: http://svn.apache.org/viewvc/activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/FSFilerTest.java?rev=677302&view=auto ============================================================================== --- activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/FSFilerTest.java (added) +++ activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/FSFilerTest.java Wed Jul 16 08:18:20 2008 @@ -0,0 +1,37 @@ +/* + * 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. + * + * $Id: FSFilerTest.java 511423 2007-02-25 03:21:05Z vgritsenko $ + */ + +package org.apache.xindice.core.filer; + +/** + * @version $Revision: 511423 $, $Date: 2007-02-24 22:21:05 -0500 (Sat, 24 Feb 2007) $ + * @author Vadim Gritsenko + */ +public class FSFilerTest extends FilerTestBase { + + public FSFilerTest(String name) { + super(name, new FSFiler()); + } + + public void testLargeKey() throws Exception { + // Kay size is limited by the file system used + LARGE_KEY_SIZE = 128; + super.testLargeKey(); + } +} Added: activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/FilerTestBase.java URL: http://svn.apache.org/viewvc/activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/FilerTestBase.java?rev=677302&view=auto ============================================================================== --- activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/FilerTestBase.java (added) +++ activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/FilerTestBase.java Wed Jul 16 08:18:20 2008 @@ -0,0 +1,423 @@ +/* + * 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. + * + * $Id: FilerTestBase.java 541504 2007-05-25 01:43:39Z vgritsenko $ + */ + +package org.apache.xindice.core.filer; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Vector; + +import junit.framework.TestCase; +import org.apache.xindice.core.data.Key; +import org.apache.xindice.core.data.Record; +import org.apache.xindice.core.data.RecordSet; +import org.apache.xindice.core.data.Value; +import org.apache.xindice.util.IntrospectionSupport; + +/** + * Base class for filer test cases + * + * @version $Revision: 541504 $, $Date: 2007-05-24 21:43:39 -0400 (Thu, 24 May 2007) $ + * @author Kimbro Staken + * @author Vladimir R. Bossicard + * @author Vadim Gritsenko + */ +public abstract class FilerTestBase extends TestCase { + + public static final String TEST_COLLECTION_NAME = "tests"; + public static final Key TEST_KEY = new Key("test.xml"); + public static final Value TEST_VALUE = new Value("Just a test"); + public static final Value TEST_VALUE_2 = new Value("Just a test 2"); + public static final Value TEST_VALUE_3 = new Value("Just a test 3"); + + private static final File ROOT = new File(TEST_COLLECTION_NAME); + + /** + * Key size for the testLargeKey. FSFiler and HashFiler will set smaller value + * for their tests. + */ + protected int LARGE_KEY_SIZE = 8192 + 32; + + protected Filer filer; + private String testName; + + public FilerTestBase(String name, Filer filer) { + super(name); + this.filer = filer; + // After teardown filer is null and getName still can be called + testName = this.filer.getName() + " " + super.getName(); + } + + public void setUp() throws Exception { + ROOT.mkdir(); + filer.setLocation(ROOT, TEST_COLLECTION_NAME); + + HashMap config = new HashMap(); + config.put("dir", new File(TEST_COLLECTION_NAME)); + config.put("pagecount", "128"); + config.put("pagesize", "4096"); + IntrospectionSupport.setProperties(filer, config); + + if (!filer.exists()) { + filer.create(); + } + filer.open(); + + RecordSet set = filer.getRecordSet(); + while (set.hasMoreRecords()) { + Key key = set.getNextKey(); + filer.deleteRecord(key); + } + assertEquals(0, filer.getRecordCount()); + } + + protected void tearDown() throws Exception { + if (filer != null) { + filer.close(); + } + filer = null; + + String[] files = ROOT.list(); + for (int i = 0; i < files.length; i++) { + assertTrue(new File(ROOT, files[i]).delete()); + } + ROOT.delete(); + super.tearDown(); + } + + public String getName() { + return testName; + } + + public void testSuccessWriteRecord() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + assertEquals(1, filer.getRecordCount()); + + Record result = filer.readRecord(TEST_KEY, false); + assertEquals(TEST_VALUE, result.getValue()); + + RecordSet set = filer.getRecordSet(); + assertEquals(result.getValue(), set.getNextRecord().getValue()); + assertFalse(set.hasMoreRecords()); + + filer.deleteRecord(TEST_KEY); + assertEquals(0, filer.getRecordCount()); + } + + public void testFailReadDeletedRecord() throws Exception { + Record result = filer.readRecord(TEST_KEY, false); + assertNull(result); + } + + public void testFailWriteRecordNullKey() throws Exception { + try { + filer.writeRecord(null, TEST_VALUE); + fail("Expecting FilerException"); + } catch (FilerException e) { + // Ok + } + } + + public void testFailWriteRecordNullValue() throws Exception { + try { + filer.writeRecord(TEST_KEY, null); + fail("Expecting FilerException"); + } catch (FilerException e) { + // Ok + } + } + + public void testFailWriteRecordNullValueKey() throws Exception { + try { + filer.writeRecord(null, null); + fail("Expecting FilerException"); + } catch (FilerException e) { + // Ok + } + } + + public void testReadRecord() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + assertEquals(1, filer.getRecordCount()); + + // Valid key + Record result = filer.readRecord(TEST_KEY, false); + assertEquals(TEST_VALUE, result.getValue()); + } + + public void testFailReadRecordNullKey() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + assertEquals(1, filer.getRecordCount()); + + // Null key + Record result = filer.readRecord(null, false); + assertNull(result); + } + + public void testFailReadRecordEmptyKey() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + assertEquals(1, filer.getRecordCount()); + + // Empty key + Record result = filer.readRecord(new Key(""), false); + assertNull(result); + } + + public void testFailReadRecordUnknownKey() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + assertEquals(1, filer.getRecordCount()); + + // Non-existant key + Record result = filer.readRecord(new Key("non-existant-key"), false); + assertNull(result); + } + + public void testDeleteRecord() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + assertEquals(1, filer.getRecordCount()); + + // Valid key + filer.deleteRecord(TEST_KEY); + assertEquals(0, filer.getRecordCount()); + Record result = filer.readRecord(TEST_KEY, false); + assertNull(result); + } + + public void testDeleteRecordNullKey() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + assertEquals(1, filer.getRecordCount()); + + // These should all just fail silently. + assertFalse(filer.deleteRecord(null)); + assertEquals(1, filer.getRecordCount()); + } + + public void testDeleteRecordEmptyKey() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + assertEquals(1, filer.getRecordCount()); + + // These should all just fail silently. + assertFalse(filer.deleteRecord(new Key(""))); + assertEquals(1, filer.getRecordCount()); + } + + public void testDeleteRecordWrongKey() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + assertEquals(1, filer.getRecordCount()); + + // These should all just fail silently. + assertFalse(filer.deleteRecord(new Key("non-existant-key"))); + assertEquals(1, filer.getRecordCount()); + } + + public void testGetRecordCount() throws Exception { + assertEquals(0, filer.getRecordCount()); + + filer.writeRecord(TEST_KEY, TEST_VALUE); + filer.writeRecord(new Key("test1"), TEST_VALUE); + filer.writeRecord(new Key("test2"), TEST_VALUE); + assertEquals(3, filer.getRecordCount()); + + filer.writeRecord(new Key("test3"), TEST_VALUE); + assertEquals(4, filer.getRecordCount()); + + assertTrue(filer.deleteRecord(new Key("test3"))); + assertEquals(3, filer.getRecordCount()); + + assertTrue(filer.deleteRecord(TEST_KEY)); + assertTrue(filer.deleteRecord(new Key("test1"))); + assertTrue(filer.deleteRecord(new Key("test2"))); + + assertEquals(0, filer.getRecordCount()); + } + + public void testGetRecordSet() throws Exception { + filer.writeRecord(TEST_KEY, TEST_VALUE); + filer.writeRecord(new Key("test2"), TEST_VALUE_2); + filer.writeRecord(new Key("test3"), TEST_VALUE_3); + + RecordSet result = filer.getRecordSet(); + assertNotNull(result); + + List results = new Vector(); + while (result.hasMoreRecords()) { + results.add(result.getNextRecord().getValue()); + } + assertEquals(3, results.size()); + assertTrue(results.contains(TEST_VALUE)); + assertTrue(results.contains(TEST_VALUE_2)); + assertTrue(results.contains(TEST_VALUE_3)); + + assertTrue(filer.deleteRecord(TEST_KEY)); + assertTrue(filer.deleteRecord(new Key("test2"))); + assertTrue(filer.deleteRecord(new Key("test3"))); + + result = filer.getRecordSet(); + assertTrue(!result.hasMoreRecords()); + } + + public void testInsertManyDocuments() throws Exception { + int iterations = 1000; + for (int i = 0; i < iterations; i++) { + filer.writeRecord(new Key("key" + i), TEST_VALUE); + } + + assertTrue(filer.getRecordCount() == iterations); + + for (int i = 0; i < iterations; i++) { + assertTrue(filer.deleteRecord(new Key("key" + i))); + } + + assertTrue(filer.getRecordCount() == 0); + RecordSet result = filer.getRecordSet(); + assertTrue(!result.hasMoreRecords()); + } + + public void testConcurrentInsert() throws Exception { + assertEquals(0, filer.getRecordCount()); + + final Object go = new Object(); + final int THREADS = 30; + final int ITERATIONS = 65; + + Thread[] threads = new Thread[THREADS]; + for (int i = 0; i < THREADS; i++) { + final int threadID = i; + threads[i] = new Thread() { + public void run() { + synchronized (go) { + try { + go.wait(); + } catch (InterruptedException e) { /* ignored */ } + } + + for (int ii = 0; ii < ITERATIONS; ii++) { + Key key = new Key("T" + threadID + "I" + ii); + Value value = new Value(""); + try { + filer.writeRecord(key, value); + } catch (Exception e) { + e.printStackTrace(); + } + } + // System.out.println(this.getName() + " done."); + } + }; + threads[i].setName("FilerTest" + i); + threads[i].start(); + } + + // Start all the threads at once + Thread.sleep(250); + synchronized (go) { + go.notifyAll(); + } + for (int i = 0; i < THREADS; i++) { + threads[i].join(); + } + + // Check results + assertEquals(THREADS * ITERATIONS, filer.getRecordCount()); + for (int i = 0; i < THREADS; i++) { + for (int ii = 0; ii < ITERATIONS; ii++) { + Key key = new Key("T" + i + "I" + ii); + Value value = new Value(""); + Record record = filer.readRecord(key, false); + assertNotNull("Record with key '" + key + "' was not found", + record); + assertEquals("Expected record with key '" + key + "', found record with key '" + record.getKey() + "'", + key, record.getKey()); + assertEquals("Expected record with value '" + value + "', found record with value '" + record.getValue() + "'", + value, record.getValue()); + } + } + } + + public void testConcurrentSameInsert() throws Exception { + assertTrue(filer.getRecordCount() == 0); + + final int THREADS = 10; + final int ITERATIONS = 5; + + Thread[] threads = new Thread[THREADS]; + for (int i = 0; i < THREADS; i++) { + threads[i] = new Thread() { + public void run() { + for (int ii = 0; ii < ITERATIONS; ii++) { + Key key = new Key("key"); + Value value = new Value(""); + try { + filer.writeRecord(key, value); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + }; + threads[i].setName("FilerTest" + i); + } + + // Start all the threads at once + for (int i = 0; i < THREADS; i++) { + threads[i].start(); + } + Thread.sleep(100); + + for (int i = 0; i < THREADS; i++) { + threads[i].join(); + } + + filer.flush(); + + // Check results + assertEquals(1, filer.getRecordCount()); + Key key = new Key("key"); + Value value = new Value(""); + Record record = filer.readRecord(key, false); + assertNotNull("Record with key '" + key + "' was not found", record); + assertEquals("Expected record with key '" + key + "', found record with key '" + record.getKey() + "'", + key, record.getKey()); + assertEquals("Expected record with value '" + value + "', found record with value '" + record.getValue() + "'", + value, record.getValue()); + } + + public void testLargeKey() throws Exception { + assertTrue(filer.getRecordCount() == 0); + + StringBuffer sb = new StringBuffer(LARGE_KEY_SIZE); + sb.append("KEY"); + for (int k = 0; k < LARGE_KEY_SIZE - 3; k++) { + sb.append('0'); + } + final Key key = new Key(sb.toString()); + final Value value = new Value(""); + + filer.writeRecord(key, value); + + assertEquals(filer.getRecordCount(), 1); + Record record = filer.readRecord(key, false); + assertNotNull("Record with key '" + key + "' was not found", + record); + assertEquals("Expected record with key '" + key + "', found record with key '" + record.getKey() + "'", + key, record.getKey()); + assertEquals("Expected record with value '" + value + "', found record with value '" + record.getValue() + "'", + value, record.getValue()); + } +} Added: activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/HashFilerTest.java URL: http://svn.apache.org/viewvc/activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/HashFilerTest.java?rev=677302&view=auto ============================================================================== --- activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/HashFilerTest.java (added) +++ activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/HashFilerTest.java Wed Jul 16 08:18:20 2008 @@ -0,0 +1,37 @@ +/* + * 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. + * + * $Id: HashFilerTest.java 511423 2007-02-25 03:21:05Z vgritsenko $ + */ + +package org.apache.xindice.core.filer; + +/** + * @version $Revision: 511423 $, $Date: 2007-02-24 22:21:05 -0500 (Sat, 24 Feb 2007) $ + * @author Vadim Gritsenko + */ +public class HashFilerTest extends FilerTestBase { + + public HashFilerTest(String name) { + super(name, new HashFiler()); + } + + public void testLargeKey() throws Exception { + // HashFiler large key can not be large than page size (less page header) + LARGE_KEY_SIZE = 4030; + super.testLargeKey(); + } +} Added: activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/MemFilerTest.java URL: http://svn.apache.org/viewvc/activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/MemFilerTest.java?rev=677302&view=auto ============================================================================== --- activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/MemFilerTest.java (added) +++ activemq/sandbox/xindice-stripped/src/test/java/org/apache/xindice/core/filer/MemFilerTest.java Wed Jul 16 08:18:20 2008 @@ -0,0 +1,31 @@ +/* + * 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. + * + * $Id: MemFilerTest.java 511423 2007-02-25 03:21:05Z vgritsenko $ + */ + +package org.apache.xindice.core.filer; + +/** + * @version $Revision: 511423 $, $Date: 2007-02-24 22:21:05 -0500 (Sat, 24 Feb 2007) $ + * @author Vadim Gritsenko + */ +public class MemFilerTest extends FilerTestBase { + + public MemFilerTest(String name) { + super(name, new MemFiler()); + } +}