You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@manifoldcf.apache.org by kw...@apache.org on 2011/12/18 09:26:34 UTC

svn commit: r1220349 [3/6] - in /incubator/lcf/branches/CONNECTORS-286/warthog-reimport: ./ lib/ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/warthog/ src/main/java/org/apache/warthog/api/ src/main...

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/ColumnSumLong.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/ColumnSumLong.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/ColumnSumLong.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/ColumnSumLong.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,116 @@
+/* $Id: ColumnSumLong.java 1210225 2011-12-04 21:09:35Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+
+/** This class is used to create a column which sums long values found in the specified
+* base column.
+*/
+public class ColumnSumLong implements WHColumnDescription
+{
+  protected String baseColumnName;
+  protected String returnColumnName;
+  
+  /** Constructor */
+  public ColumnSumLong(String baseColumnName, String returnColumnName)
+  {
+    this.baseColumnName = baseColumnName;
+    this.returnColumnName = returnColumnName;
+  }
+  
+  /** Get the name of the return column */
+  public String getReturnColumnName()
+    throws WHException
+  {
+    return returnColumnName;
+  }
+  
+  /** Create a return column calculator for this column.
+  */
+  public WHColumnCalculator createCalculator()
+    throws WHException
+  {
+    return new SumLongCalculator(baseColumnName);
+  }
+  
+  protected static class SumLongCalculator implements WHColumnCalculator
+  {
+    protected String baseColumnName;
+    
+    protected long sum = 0L;
+    
+    public SumLongCalculator(String baseColumnName)
+    {
+      this.baseColumnName = baseColumnName;
+    }
+
+    /** Check whether a row can be added to to the column calculator.
+    * Does NOT actually change the result of the calculator!
+    *@return true if the row can be added and false if a tally should be done immediately.
+    */
+    public boolean canProcessRowValue(WHAccessor accessor)
+      throws WHException
+    {
+      // This calculator can always accept new values
+      return true;
+    }
+
+    /** Check whether this calculator is capable of generating a final summary row value.
+    *@return true if it is capable.  tally() will only be called at the end for the summary
+    *     row if all columns are capable of generating a summary value.
+    */
+    public boolean canGenerateSummaryValue()
+      throws WHException
+    {
+      // This calculator can always generate a summary value
+      return true;
+    }
+
+    /** Feed a row to the column calculator.
+    */
+    public void processRowValue(WHAccessor accessor)
+      throws WHException
+    {
+      WHValue value = accessor.getValue(baseColumnName);
+      if (value != null)
+      {
+        if (!(value instanceof LongValue))
+          throw new WHException("ColumnSumLong can only be used with values of LongValue type");
+        sum += ((LongValue)value).getValue();
+      }
+    }
+    
+    /** Tally a final result, obtaining whatever current aggregate value there is.
+    * Also resets the calculator in preparation for another set of rows.
+    */
+    public WHValue tally()
+      throws WHException
+    {
+      WHValue rval = new LongValue(sum);
+      sum = 0L;
+      return rval;
+    }
+
+  }
+    
+}
+  
+  
\ No newline at end of file

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/IntegerKey.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/IntegerKey.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/IntegerKey.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/IntegerKey.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,53 @@
+/* $Id: IntegerKey.java 1205831 2011-11-24 13:57:15Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+
+/** Integer key.
+*/
+public class IntegerKey extends IntegerValue implements WHKey
+{
+  public IntegerKey(int value)
+  {
+    super(value);
+  }
+  
+  public IntegerKey(byte[] bytes)
+  {
+    super(bytes);
+  }
+
+  /** Calculate the hash function. */
+  public long getHashCode()
+  {
+    return calculateHashCode(value);
+  }
+  
+  public static long calculateHashCode(int value)
+  {
+    long x = (long)value;
+    return (x << 5) ^ (x >> 3);
+  }
+  
+}
+
+

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/IntegerValue.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/IntegerValue.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/IntegerValue.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/IntegerValue.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,96 @@
+/* $Id: IntegerValue.java 1207794 2011-11-29 08:57:22Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+
+/** Integer value, serializable.
+*/
+public class IntegerValue implements WHValue,WHKeyValue
+{
+  int value;
+  
+  public IntegerValue(int value)
+  {
+    this.value = value;
+  }
+  
+  public IntegerValue(byte[] bytes)
+  {
+    value = readObject(new BufferPointer(bytes));
+  }
+  
+  public byte[] serializeObject()
+  {
+    byte[] rval = new byte[sizeObject()];
+    writeObject(new BufferPointer(rval),value);
+    return rval;
+  }
+
+  /** Check if equals (classes must already agree) */
+  public boolean isEquals(WHKeyValue value)
+  {
+    IntegerValue x = (IntegerValue)value;
+    return x.value == this.value;
+  }
+
+  public int getValue()
+  {
+    return value;
+  }
+  
+  public int hashCode()
+  {
+    return (value << 5) ^ (value >> 3);
+  }
+  
+  public boolean equals(Object o)
+  {
+    if (this.getClass() != o.getClass())
+      return false;
+    return ((IntegerValue)o).value == value;
+  }
+
+  public static int readObject(BufferPointer bp)
+  {
+    int value = (((int)bp.readValue()) & 0xff);
+    value += ((((int)bp.readValue()) << 8) & 0xff00);
+    value += ((((int)bp.readValue()) << 16) & 0xff0000);
+    value += ((((int)bp.readValue()) << 24) & 0xff000000);
+    return value;
+  }
+  
+  public static int sizeObject()
+  {
+    return 4;
+  }
+  
+  public static void writeObject(BufferPointer bp, int value)
+  {
+    bp.writeValue((byte)(value & 0xff));
+    bp.writeValue((byte)((value >> 8) & 0xff));
+    bp.writeValue((byte)((value >> 16) & 0xff));
+    bp.writeValue((byte)((value >> 24) & 0xff));
+  }
+  
+}
+
+

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongArray.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongArray.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongArray.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongArray.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,128 @@
+/* $Id: LongArray.java 1207794 2011-11-29 08:57:22Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+
+/** Long array, serializable.
+*/
+public class LongArray implements WHKeyValue
+{
+  long[] value;
+  
+  public LongArray(long[] value)
+  {
+    this.value = value;
+  }
+  
+  public LongArray()
+  {
+  }
+  
+  public LongArray(byte[] bytes)
+  {
+    value = readObject(new BufferPointer(bytes));
+  }
+  
+  public byte[] serializeObject()
+  {
+    byte[] rval = new byte[sizeObject(value.length)];
+    writeObject(new BufferPointer(rval),value);
+    return rval;
+  }
+  
+  public long[] getValue()
+  {
+    return value;
+  }
+
+  /** Check if equals (classes must already agree) */
+  public boolean isEquals(WHKeyValue value)
+  {
+    long[] otherValue = ((LongArray)value).value;
+    return compareObject(this.value,otherValue);
+  }
+
+  public int hashCode()
+  {
+    int rval = 0;
+    for (int i = 0 ; i < value.length ; i++)
+    {
+      rval += (((int)value[i]) << 5) ^ (((int)value[i]) >> 3);
+    }
+    return rval;
+  }
+  
+  public boolean equals(Object o)
+  {
+    if (this.getClass() != o.getClass())
+      return false;
+    LongArray sa = (LongArray)o;
+    if (sa.value.length != value.length)
+      return false;
+    for (int i = 0 ; i < value.length ; i++)
+    {
+      if (sa.value[i] != value[i])
+        return false;
+    }
+    return true;
+  }
+
+  public static long[] readObject(BufferPointer bp)
+  {
+    int size = IntegerValue.readObject(bp);
+    long[] rval = new long[size];
+    for (int i = 0 ; i < size ; i++)
+    {
+      rval[i] = LongValue.readObject(bp);
+    }
+    return rval;
+  }
+  
+  public static int sizeObject(int size)
+  {
+    return IntegerValue.sizeObject() + LongValue.sizeObject() * size;
+  }
+  
+  public static void writeObject(BufferPointer bp, long[] value)
+  {
+    IntegerValue.writeObject(bp,value.length);
+    for (int i = 0 ; i < value.length ; i++)
+    {
+      LongValue.writeObject(bp,value[i]);
+    }
+  }
+  
+  public static boolean compareObject(long[] value, long[] otherValue)
+  {
+    if (otherValue.length != value.length)
+      return false;
+    for (int i = 0 ; i < otherValue.length ; i++)
+    {
+      if (otherValue[i] != value[i])
+        return false;
+    }
+    return true;
+  }
+  
+}
+
+

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongComparatorAscending.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongComparatorAscending.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongComparatorAscending.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongComparatorAscending.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,50 @@
+/* $Id: LongComparatorAscending.java 1206460 2011-11-26 15:27:37Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+
+/** Class that compares long values, and sorts in ascending order.
+*/
+public class LongComparatorAscending implements WHComparator
+{
+  /** Comparison method.
+  * This is only ever used to compare values; it cannot be used to compare null vs. non-null.
+  */
+  public int compare(WHValue leftValue, WHValue rightValue)
+    throws WHException
+  {
+    if (leftValue == null && rightValue == null)
+      return RESULT_EQUALS;
+    // Sort null values to the end
+    if (leftValue == null)
+      return RESULT_LESS;
+    if (rightValue == null)
+      return RESULT_GREATER;
+    if (!(leftValue instanceof LongValue) || !(rightValue instanceof LongValue))
+      throw new WHException("Cannot compare anything other than LongValues here");
+    long leftLongValue = ((LongValue)leftValue).getValue();
+    long rightLongValue = ((LongValue)rightValue).getValue();
+    if (leftLongValue == rightLongValue)
+      return RESULT_EQUALS;
+    return (leftLongValue < rightLongValue)?RESULT_GREATER:RESULT_LESS;
+  }
+  
+}
\ No newline at end of file

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongKey.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongKey.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongKey.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongKey.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,52 @@
+/* $Id: LongKey.java 1208951 2011-12-01 05:05:52Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+
+/** Long key.
+*/
+public class LongKey extends LongValue implements WHKey
+{
+  public LongKey(long value)
+  {
+    super(value);
+  }
+  
+  public LongKey(byte[] bytes)
+  {
+    super(bytes);
+  }
+
+  /** Calculate the hash function. */
+  public long getHashCode()
+  {
+    return calculateHashCode(value);
+  }
+  
+  public static long calculateHashCode(long value)
+  {
+    return (value << 5) ^ (value >> 3);
+  }
+  
+}
+
+

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongValue.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongValue.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongValue.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/LongValue.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,103 @@
+/* $Id: LongValue.java 1208116 2011-11-29 22:36:26Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+
+/** Long value, serializable.
+*/
+public class LongValue implements WHValue,WHKeyValue,WHRowID
+{
+  long value;
+  
+  public LongValue(long value)
+  {
+    this.value = value;
+  }
+  
+  public LongValue(byte[] bytes)
+  {
+    value = readObject(new BufferPointer(bytes));
+  }
+  
+  public byte[] serializeObject()
+  {
+    byte[] rval = new byte[sizeObject()];
+    writeObject(new BufferPointer(rval),value);
+    return rval;
+  }
+
+  /** Check if equals (classes must already agree) */
+  public boolean isEquals(WHKeyValue value)
+  {
+    LongValue k = (LongValue)value;
+    return k.value == this.value;
+  }
+  
+  public long getValue()
+  {
+    return value;
+  }
+
+  public int hashCode()
+  {
+    return (int)((value << 5) ^ (value >> 3));
+  }
+  
+  public boolean equals(Object o)
+  {
+    if (this.getClass() != o.getClass())
+      return false;
+    return ((LongValue)o).value == value;
+  }
+  
+  public static long readObject(BufferPointer bp)
+  {
+    long value = (((long)bp.readValue()) & 0xffL);
+    value += ((((long)bp.readValue()) << 8) & 0xff00L);
+    value += ((((long)bp.readValue()) << 16) & 0xff0000L);
+    value += ((((long)bp.readValue()) << 24) & 0xff000000L);
+    value += ((((long)bp.readValue()) << 32) & 0xff00000000L);
+    value += ((((long)bp.readValue()) << 40) & 0xff0000000000L);
+    value += ((((long)bp.readValue()) << 48) & 0xff000000000000L);
+    value += ((((long)bp.readValue()) << 56) & 0xff00000000000000L);
+    return value;
+  }
+  
+  public static int sizeObject()
+  {
+    return 8;
+  }
+  
+  public static void writeObject(BufferPointer bp, long value)
+  {
+    bp.writeValue((byte)(value & 0xffL));
+    bp.writeValue((byte)((value >> 8) & 0xffL));
+    bp.writeValue((byte)((value >> 16) & 0xffL));
+    bp.writeValue((byte)((value >> 24) & 0xffL));
+    bp.writeValue((byte)((value >> 32) & 0xffL));
+    bp.writeValue((byte)((value >> 40) & 0xffL));
+    bp.writeValue((byte)((value >> 48) & 0xffL));
+    bp.writeValue((byte)((value >> 56) & 0xffL));
+  }
+}
+
+

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringArray.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringArray.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringArray.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringArray.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,128 @@
+/* $Id: StringArray.java 1207794 2011-11-29 08:57:22Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+
+/** String array, serializable.
+*/
+public class StringArray implements WHValue,WHKeyValue
+{
+  String[] value;
+  
+  public StringArray(String[] value)
+  {
+    this.value = value;
+  }
+  
+  public StringArray(byte[] bytes)
+  {
+    value = readObject(new BufferPointer(bytes));
+  }
+  
+  public byte[] serializeObject()
+  {
+    byte[] rval = new byte[sizeObject(value)];
+    writeObject(new BufferPointer(rval),value);
+    return rval;
+  }
+
+  /** Check if equals (classes must already agree) */
+  public boolean isEquals(WHKeyValue value)
+  {
+    StringArray other = (StringArray)value;
+    return compareObject(other.value,this.value);
+  }
+  
+  public String[] getValue()
+  {
+    return value;
+  }
+  
+  public int hashCode()
+  {
+    int rval = 0;
+    for (int i = 0 ; i < value.length ; i++)
+    {
+      rval += value[i].hashCode();
+    }
+    return rval;
+  }
+  
+  public boolean equals(Object o)
+  {
+    if (this.getClass() != o.getClass())
+      return false;
+    StringArray sa = (StringArray)o;
+    if (sa.value.length != value.length)
+      return false;
+    for (int i = 0 ; i < value.length ; i++)
+    {
+      if (!sa.value[i].equals(value[i]))
+        return false;
+    }
+    return true;
+  }
+
+  public static String[] readObject(BufferPointer bp)
+  {
+    int size = IntegerValue.readObject(bp);
+    String[] rval = new String[size];
+    for (int i = 0 ; i < size ; i++)
+    {
+      rval[i] = StringValue.readObject(bp);
+    }
+    return rval;
+  }
+  
+  public static int sizeObject(String[] value)
+  {
+    int rval = IntegerValue.sizeObject();
+    for (int i = 0 ; i < value.length ; i++)
+    {
+      rval += StringValue.sizeObject(value[i]);
+    }
+    return rval;
+  }
+  
+  public static void writeObject(BufferPointer bp, String[] value)
+  {
+    IntegerValue.writeObject(bp,value.length);
+    for (int i = 0 ; i < value.length ; i++)
+    {
+      StringValue.writeObject(bp,value[i]);
+    }
+  }
+  
+  public static boolean compareObject(String[] value, String[] otherValue)
+  {
+    if (otherValue.length != value.length)
+      return false;
+    for (int i = 0 ; i < otherValue.length ; i++)
+    {
+      if (!otherValue[i].equals(value[i]))
+        return false;
+    }
+    return true;
+  }
+}
+
+

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringComparatorAscending.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringComparatorAscending.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringComparatorAscending.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringComparatorAscending.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,51 @@
+/* $Id: StringComparatorAscending.java 1206460 2011-11-26 15:27:37Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+
+/** Class that compares string values, and sorts in ascending order.
+*/
+public class StringComparatorAscending implements WHComparator
+{
+  /** Comparison method.
+  * This is only ever used to compare values; it cannot be used to compare null vs. non-null.
+  */
+  public int compare(WHValue leftValue, WHValue rightValue)
+    throws WHException
+  {
+    if (leftValue == null && rightValue == null)
+      return RESULT_EQUALS;
+    // Sort null values to the end
+    if (leftValue == null)
+      return RESULT_LESS;
+    if (rightValue == null)
+      return RESULT_GREATER;
+    if (!(leftValue instanceof StringValue) || !(rightValue instanceof StringValue))
+      throw new WHException("Cannot compare anything other than StringValues here");
+    String leftStringValue = ((StringValue)leftValue).getValue();
+    String rightStringValue = ((StringValue)rightValue).getValue();
+    int compare = leftStringValue.compareTo(rightStringValue);
+    if (compare == 0)
+      return RESULT_EQUALS;
+    return (compare < 0)?RESULT_GREATER:RESULT_LESS;
+  }
+  
+}
\ No newline at end of file

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringKey.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringKey.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringKey.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringKey.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,61 @@
+/* $Id: StringKey.java 1206460 2011-11-26 15:27:37Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+
+/** This object represents a string that can be used as a key in the key/value store.
+*/
+public class StringKey extends StringValue implements WHKey
+{
+  protected long hashCodeValue;
+  
+  public StringKey(String value)
+  {
+    super(value);
+    hashCodeValue = calculateHashCode(value);
+  }
+  
+  public StringKey(byte[] bytes)
+  {
+    super(bytes);
+    hashCodeValue = calculateHashCode(value);
+  }
+
+  /** Calculate the hash function. */
+  public long getHashCode()
+  {
+    return hashCodeValue;
+  }
+  
+  public static long calculateHashCode(String value)
+  {
+    // Should be independent of JVM, which is why I do this myself
+    long rval = 0L;
+    for (int i = 0 ; i < value.length() ; i++)
+    {
+      long x = (long)value.charAt(i);
+      rval += (x << 5) ^ (x >> 3);
+    }
+    return rval;
+  }
+  
+}
\ No newline at end of file

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringValue.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringValue.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringValue.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/common/StringValue.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,88 @@
+/* $Id: WHValue.java 1199794 2011-11-09 15:28:08Z kwright $ */
+
+/**
+* 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.warthog.common;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+
+/** This object represents a string that can be stored in the key/value store.
+*/
+public class StringValue implements WHValue,WHKeyValue
+{
+  protected String value;
+  
+  public StringValue(String value)
+  {
+    this.value = value;
+  }
+  
+  public StringValue(byte[] bytes)
+  {
+    value = readObject(new BufferPointer(bytes));
+  }
+  
+  public String getValue()
+  {
+    return value;
+  }
+
+  public byte[] serializeObject()
+  {
+    byte[] rval = new byte[sizeObject(value)];
+    writeObject(new BufferPointer(rval),value);
+    return rval;
+  }
+
+  /** Check if equals (classes must already agree) */
+  public boolean isEquals(WHKeyValue value)
+  {
+    StringValue thisValue = (StringValue)value;
+    return thisValue.value.equals(this.value);
+  }
+  
+  public int hashCode()
+  {
+    return value.hashCode();
+  }
+  
+  public boolean equals(Object o)
+  {
+    if (this.getClass() != o.getClass())
+      return false;
+    return ((StringValue)o).value.equals(value);
+  }
+
+  public static String readObject(BufferPointer bp)
+  {
+    char[] array = CharacterArray.readObject(bp);
+    return new String(array);
+  }
+  
+  public static int sizeObject(String value)
+  {
+    return CharacterArray.sizeObject(value.length());
+  }
+  
+  public static void writeObject(BufferPointer bp, String value)
+  {
+    CharacterArray.writeObject(bp,value.toCharArray());
+  }
+
+}
\ No newline at end of file

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHAtomicKeyValueStore.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHAtomicKeyValueStore.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHAtomicKeyValueStore.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHAtomicKeyValueStore.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,52 @@
+/* $Id: WHAtomicKeyValueStore.java -1   $ */
+
+/**
+* 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.warthog.keyvalue;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+import java.util.*;
+
+/** Describes the general functionality requirements of an underlying (distributed?)
+* key value store, which use conflict detection as its mechanism for handling transactional
+* integrity.
+*/
+public interface WHAtomicKeyValueStore
+{
+  /** Get a value */
+  public WHKeyValue get(WHKey key)
+    throws WHException;
+  
+  /** Check a bunch of values atomically for consistency.
+  *@param checkValues is a map of keys/values that must be unchanged.  If any value is
+  * changed, a WHDeadlockException is thrown.
+  */
+  public void check(WHKeyMap checkValues)
+    throws WHException;
+  
+  /** Set a bunch of values atomically.
+  *@param checkValues is a map of keys/values that must be unchanged in order for the
+  * commit to proceed.  If these values are detected to have been changed, a WHDeadlockException
+  * will be thrown.  Null values are permitted.
+  *@param setValues is a map of keys to set to specified new values.  A null value implies removal of
+  * the key.
+  */
+  public void setAll(WHKeyMap checkValues, WHKeyMap setValues)
+    throws WHException;
+}

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHKeyIterator.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHKeyIterator.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHKeyIterator.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHKeyIterator.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,38 @@
+/* $Id: WHKeyIterator.java -1   $ */
+
+/**
+* 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.warthog.keyvalue;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+
+/** This interface describes an iterator over a set of WHKeys.  WHException
+* is possible on every iterator step.
+*/
+public interface WHKeyIterator
+{
+  /** Check if there is another value */
+  public boolean hasNext()
+    throws WHException;
+  
+  /** Get the next value */
+  public WHKey next()
+    throws WHException;
+}
+

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHKeyMap.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHKeyMap.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHKeyMap.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvalue/WHKeyMap.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,45 @@
+/* $Id: WHKeyMap.java -1   $ */
+
+/**
+* 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.warthog.keyvalue;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+import java.util.*;
+
+/** This interface describes a set of key/value pairs that is maintained locally.
+*/
+public interface WHKeyMap
+{
+  /** Get a value from the map.
+  */
+  public WHKeyValue get(WHKey key)
+    throws WHException;
+  
+  /** Iterate over the keys in the map.
+  */
+  public WHKeyIterator iterator()
+    throws WHException;
+  
+  /** Get the size of the map.
+  */
+  public long size()
+    throws WHException;
+}
+

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/GeneralIDFactoryKey.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/GeneralIDFactoryKey.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/GeneralIDFactoryKey.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/GeneralIDFactoryKey.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,64 @@
+/* $Id: GeneralIDFactoryKey.java 1208116 2011-11-29 22:36:26Z kwright $ */
+
+/**
+* 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.warthog.keyvaluetablestore;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+import org.apache.warthog.common.*;
+
+/** Key for accessing the general ID factory */
+public class GeneralIDFactoryKey implements WHKey
+{
+  /** Constructor */
+  public GeneralIDFactoryKey()
+  {
+  }
+    
+  public GeneralIDFactoryKey(byte[] data)
+  {
+  }
+
+  public byte[] serializeObject()
+  {
+    return new byte[0];
+  }
+  
+  /** Calculate the hash function. */
+  public long getHashCode()
+  {
+    return 15335L;
+  }
+
+  public boolean isEquals(WHKeyValue value)
+  {
+    return true;
+  }
+
+  public int hashCode()
+  {
+    return 15335;
+  }
+  
+  public boolean equals(Object o)
+  {
+    return o.getClass() == getClass();
+  }
+  
+}

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/Index.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/Index.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/Index.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/Index.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,646 @@
+/* $Id: Index.java 1209929 2011-12-03 15:06:22Z kwright $ */
+
+/**
+* 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.warthog.keyvaluetablestore;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+import org.apache.warthog.common.*;
+
+import java.util.*;
+
+/** This is the standard implementation of WHIndex.
+*
+* The index structure has a one-to-one correspondence with the rows
+* in the underlying table.  Since there is such a correspondence, we make
+* use of the rowID for each table row as a "nodeID".  This reduces the number
+* of keys/values we need to track for an index.
+*
+* The index has the following overall structure:
+* (a) An (optional) root node reference, as decribed by a root key, which points to
+*   either nothing or the root node for the first index column;
+* (b) A set of nodes for the first index column organized in a btree;
+* (c) A reference from each node representing the first index column which
+*   functions as the root pointer for a btree based on the second index column, etc.
+*
+* Each btree node has a lesser child node reference, a greater child node reference,
+* and an "equals" child node reference.  All of these relationships refer to comparisons
+* of the current column value for the row represented by the node.  There are also rules
+* for what is legal in any given context within each btree.  Specifically, nodes that 
+* exist in the "equals" chain cannot have greater or lesser children, only "equals"
+* children.
+*
+* For each node reference, there's also a back reference, which allows you to walk back
+* up the tree.  This is unique since every index node can have only one reference to it.
+*
+* In the future, a "maximum depth" value will also be associated with every node, so as
+* to allow automatic rebalancing of each btree.
+*
+*/
+public class Index implements WHIndex
+{
+  protected TableStore ts;
+  protected Table table;
+  protected LongValue indexID;
+  protected long indexIDValue;
+  protected long[] columnIDs;
+  protected WHComparator[] comparators;
+  protected boolean unique;
+  
+  /** Constructor */
+  public Index(TableStore ts, LongValue indexID, Table table, long[] columnIDs, String[] comparatorClasses, boolean unique)
+    throws WHException
+  {
+    if (columnIDs.length != comparatorClasses.length)
+      throw new WHException("Number of index column names must match number of comparator classes");
+    this.ts = ts;
+    this.table = table;
+    this.indexID = indexID;
+    this.indexIDValue = indexID.getValue();
+    this.columnIDs = columnIDs;
+    this.unique = unique;
+    this.comparators = new WHComparator[comparatorClasses.length];
+    try
+    {
+      for (int i = 0 ; i < comparators.length ; i++)
+      {
+        this.comparators[i] = (WHComparator)Class.forName(comparatorClasses[i]).newInstance();
+      }
+    }
+    catch (Exception e)
+    {
+      throw new WHException("Error instantiating comparator class for index '"+new Long(indexIDValue).toString()+"': "+e.getMessage(),e);
+    }
+  }
+  
+  /** Get the relationship the index applies to.
+  */
+  public WHRelationship getRelationship()
+    throws WHException
+  {
+    return table;
+  }
+  
+  /** Get the underlying relationship column names.
+  */
+  public String[] getColumnNames()
+    throws WHException
+  {
+    return table.getColumnNames();
+  }
+
+  /** Get a default accessor with default ordering and no filtering.
+  */
+  public WHAccessor buildAccessor()
+    throws WHException
+  {
+    // Use null criteria
+    return buildAccessor(null,null);
+  }
+  
+
+  /** Create an accessor based on this index which uses the provided criteria.  The
+  * criteria must align with the index's columns.  Null values are permitted where
+  * no criteria are present. 
+  *@param criteria are the criteria that apply to each individual index column; null for no criteria at all.
+  *@param orderReversed is a boolean for each individual index column; true if the comparator order of that column
+  * should be reversed for the accessor.  Null indicates no reversal for any column.
+  */
+  public WHAccessor buildAccessor(IndexCriteria[] criteria, boolean[] orderReversed)
+    throws WHException
+  {
+    if (criteria != null && criteria.length != columnIDs.length)
+      throw new WHException("Criteria count must match index column count");
+    if (orderReversed != null && orderReversed.length != columnIDs.length)
+      throw new WHException("Order reversal count must match index column count");
+    return new IndexAccessor(this,criteria,orderReversed);
+  }
+
+  // Below this line are methods that are not meant to be used for general purposes,
+
+  /** Get the columns that are indexed
+  */
+  protected long[] getIndexColumnIDs()
+  {
+    return columnIDs;
+  }
+
+  /** Get the index id */
+  protected LongValue getID()
+  {
+    return indexID;
+  }
+  
+  protected long getIDValue()
+  {
+    return indexIDValue;
+  }
+  
+  protected Table getTable()
+  {
+    return table;
+  }
+  
+  /** Get the comparators.
+  */
+  protected WHComparator[] getComparators()
+  {
+    return comparators;
+  }
+  
+  /** Add a new row to the index.
+  * The row must already exist in the underlying table.
+  */
+  protected void addNewRow(LongValue rowID)
+    throws WHException
+  {
+    // The algorithm here simply involves finding the right spot and adding a new node at that point.
+    // We should also rebalance the tree at that point, but that's going to be implemented in phase II.
+    
+    addNodeInto(rowID,new IndexRootKey(indexIDValue));
+  }
+  
+  /** Method to add a given node into a subtree where we start only with a parent key.
+  */
+  protected void addNodeInto(LongValue rowID, WHKey parentKey)
+    throws WHException
+  {
+    for (int columnIndex = 0 ; columnIndex < columnIDs.length ; columnIndex++ )
+    {
+      // Place a node into a specific tree as indicated by the column number.
+      // This will either wind up in an equals chain (in which case, a link to the column child will already exist),
+      // or it will wind up as a new primary node (in which case, the link to the column child will need to be created).
+      
+      parentKey = placeIntoBtree(rowID,parentKey,columnIndex);
+    }
+  }
+  
+  /** Method to place a new node into a specific tree for a column.
+  */
+  protected WHKey placeIntoBtree(LongValue rowID, WHKey parentKey, int columnIndex)
+    throws WHException
+  {
+    // Get the current column
+    long columnID = columnIDs[columnIndex];
+    WHComparator comparator = comparators[columnIndex];
+    // Read the value we're going to be inserting
+    WHValue insertValue = (WHValue)table.getTableColumnValue(rowID,columnID);
+    // Keep going until we've found the insertion point (or until it looks like we're looping,
+    // which means we've hit a concurrency problem)
+    //Set<LongValue> hitSoFar = new HashSet<LongValue>();
+    while (true)
+    {
+      // Pick up the current node from the parent
+      LongValue currentRowID = readIndexParentChild(parentKey);
+      if (currentRowID == null)
+      {
+        // Set the node in place
+        setIndexParentChild(parentKey,columnID,rowID);
+        return new IndexNodeColumnKey(indexIDValue,rowID.getValue(),columnID);
+      }
+
+      //if (hitSoFar.contains(currentRowID))
+      //  throw new WHConcurrencyException();
+      //hitSoFar.add(currentRowID);
+      
+      // Read the value at this node
+      WHValue currentValue = (WHValue)table.getTableColumnValue(currentRowID,columnID);
+      
+      // Perform the comparison
+      int comparatorResult = comparator.compare(currentValue,insertValue);
+      
+      // Based on the result, decide which way to go
+      switch (comparatorResult)
+      {
+      case WHComparator.RESULT_LESS:
+        // Descend the lesser tree for this column.
+        parentKey = new IndexNodeLesserKey(indexIDValue,currentRowID.getValue(),columnID);
+        continue;
+      case WHComparator.RESULT_GREATER:
+        // Descend the greater tree for this column.
+        parentKey = new IndexNodeGreaterKey(indexIDValue,currentRowID.getValue(),columnID);
+        continue;
+      case WHComparator.RESULT_EQUALS:
+        // Insert here!  into the chain if need be...
+        break;
+      default:
+        throw new WHException("Comparator returned illegal result");
+      }
+      
+      if (unique && columnIndex +1 == columnIDs.length)
+      {
+        // Unique constraint violation
+        throw new WHUniqueConstraintViolationException("Row "+new Long(rowID.getValue()).toString()+" violates uniqueness constraint on index "+new Long(indexIDValue).toString());
+      }
+      
+      // We keep a linked list of identical nodes.  We can insert into that chain at any point.
+      // We insert the new node at the beginning of the chain so we don't have to scan it, obviously...
+      
+      // First, get the old ref, if there is one.
+      LongValue currentEqualsRowID = readIndexNodeEqualsNode(currentRowID,columnID);
+      
+      // Move the old pointer to the new position
+      if (currentEqualsRowID != null)
+      {
+        // Delete the old one
+        deleteIndexNodeEqualsNode(currentRowID,columnID);
+        // Move the pointer to the child of the node we just created
+        setIndexNodeEqualsNode(rowID,columnID,currentEqualsRowID);
+      }
+      
+      // Now, set the new ref.
+      setIndexNodeEqualsNode(currentRowID,columnID,rowID);
+      
+      return new IndexNodeColumnKey(indexIDValue,currentRowID.getValue(),columnID);
+    }
+  }
+  
+  /** Remove a row from the index.  The row must currently exist.
+  */
+  protected void deleteRow(LongValue rowID)
+    throws WHException
+  {
+    // The deletion algorithm must remove N keys, one per column.  We start with the key for
+    // column N-1, and work back to column 0.
+    // 
+    // Each remove basically occurs independently within its own btree.  In each btree, if
+    // the node has an equals child, that child is promoted and takes on the greater and lesser children
+    // of the node that is going away.  If there is no equals child, then we promote either the lesser or
+    // the greater child, and if there are none of those we just remove the node and do nothing else.
+    //
+    // As part of promoting the lesser or greater child, the other child (if it exists) will be inserted
+    // into the btree and will be carried to the bottom and linked in.
+    
+    for (int i = columnIDs.length ; i > 0 ; i--)
+    {
+      removeFromBtree(rowID,i-1);
+    }
+  }
+  
+  /** Remove a row for a specific column from the corresponding btree.
+  */
+  protected void removeFromBtree(LongValue rowID, int columnIndex)
+    throws WHException
+  {
+    long columnID = columnIDs[columnIndex];
+    
+    // Build the index node's parent key
+    WHKey parentKey = readIndexNodeParentKey(rowID,columnID);
+    
+    // Look for an 'equals' child
+    LongValue equalsChild = readIndexNodeEqualsNode(rowID,columnID);
+    if (equalsChild != null)
+    {
+      // Case (1) (as described above).  Promote the child.  We know the child has
+      // no greater/lesser children.
+      deleteIndexNodeEqualsNode(rowID,columnID);
+      deleteIndexParentChild(parentKey,columnID);
+      setIndexParentChild(parentKey,columnID,equalsChild);
+      // Now, transfer the delete node's lesser/greater children to the equalsChild.
+      LongValue lesserChild = readIndexNodeLesserNode(rowID,columnID);
+      if (lesserChild != null)
+      {
+        deleteIndexNodeLesserNode(rowID,columnID);
+        setIndexNodeLesserNode(equalsChild,columnID,lesserChild);
+      }
+      LongValue greaterChild = readIndexNodeGreaterNode(rowID,columnID);
+      if (greaterChild != null)
+      {
+        deleteIndexNodeGreaterNode(rowID,columnID);
+        setIndexNodeGreaterNode(equalsChild,columnID,greaterChild);
+      }
+      return;
+    }
+    
+    // No equals chain.  Instead we look for a node to be promoted.
+    
+    // The column priority is fixed and will not change, but the priority of lesser vs. greater is
+    // arbitrary.  Someday we'll choose to promote the deeper side perhaps...
+    
+    // First, unhook the whole tree from the parent.
+    deleteIndexParentChild(parentKey,columnID);
+    
+    // Now look for a promotion candidate to hook in in its place.
+    LongValue promotionCandidate = null;
+    if (promotionCandidate == null)
+    {
+      promotionCandidate = readIndexNodeLesserNode(rowID,columnID);
+      if (promotionCandidate != null)
+        // We found our promotion candidate!
+        deleteIndexNodeLesserNode(rowID,columnID);
+    }
+    if (promotionCandidate == null)
+    {
+      promotionCandidate = readIndexNodeGreaterNode(rowID,columnID);
+      if (promotionCandidate != null)
+        // Candidate found
+        deleteIndexNodeGreaterNode(rowID,columnID);
+    }
+    
+    if (promotionCandidate != null)
+    {
+      // Hook in the promotion candidate as child of the parent.
+      setIndexParentChild(parentKey,columnID,promotionCandidate);
+      // Transfer the remaining lesser/greater children into the promotionCandidate node
+      LongValue lesserChild = readIndexNodeLesserNode(rowID,columnID);
+      if (lesserChild != null)
+      {
+        // Peel it away from the deleteNodeID
+        deleteIndexNodeLesserNode(rowID,columnID);
+        // Now insert this node into promotionCandidate via parentKey
+        placeIntoBtree(lesserChild,parentKey,columnIndex);
+      }
+      LongValue greaterChild = readIndexNodeGreaterNode(rowID,columnID);
+      if (greaterChild != null)
+      {
+        // Delete the reference from the deletion node
+        deleteIndexNodeGreaterNode(rowID,columnID);
+        // Now insert this node into promotionCandidate via parentKey
+        placeIntoBtree(greaterChild,parentKey,columnIndex);
+      }
+    }
+  }
+  
+  /** Initialize an entire index.
+  * WARNING: This effectively requires the entire new index to fit in memory!
+  * Better create the index when the table is small, then...
+  */
+  protected void initialize()
+    throws WHException
+  {
+    // Create an accessor for the table
+    WHAccessor tableAccessor = table.buildAccessor();
+    while (true)
+    {
+      LongValue rowID = (LongValue)tableAccessor.getCurrentRowID();
+      if (rowID == null)
+        break;
+      // Add this row to the index.
+      addNewRow(rowID);
+      tableAccessor.advance();
+    }
+  }
+  
+  /** Remove an entire index.
+  * WARNING: This effectively requires the entire index to fit in memory!
+  * It's far better to remove a bit at a time, in separate transactions.
+  */
+  protected void remove()
+    throws WHException
+  {
+    deleteBtree(new IndexRootKey(indexIDValue),0);
+  }
+  
+  /** Delete a single btree with specified column index.
+  */
+  protected void deleteBtree(WHKey key, int indexColumn)
+    throws WHException
+  {
+    if (indexColumn == columnIDs.length)
+      return;
+
+    // For this btree, start with the root
+    LongValue child = readIndexParentChild(key);
+    // If there's no root, we are done
+    if (child == null)
+      return;
+    
+    // Delete the child.
+    long columnID = columnIDs[indexColumn];
+    // First, unlink from the parent.
+    deleteIndexParentChild(key,columnID);
+    // Recursively clean up all child links.
+    deleteBtree(new IndexNodeEqualsKey(indexIDValue,child.getValue(),columnID),indexColumn);
+    deleteBtree(new IndexNodeLesserKey(indexIDValue,child.getValue(),columnID),indexColumn);
+    deleteBtree(new IndexNodeGreaterKey(indexIDValue,child.getValue(),columnID),indexColumn);
+    // Move on to next column
+    deleteBtree(new IndexNodeColumnKey(indexIDValue,child.getValue(),columnID),indexColumn+1);
+  }
+  
+  // Protected methods
+
+  /** Get next column's root node for an index node.
+  * This link is necessary in order to allow each tree to rebalance independently.
+  */
+  protected LongValue readIndexNodeColumnNode(LongValue rowID, long columnID)
+    throws WHException
+  {
+    return (LongValue)ts.get(new IndexNodeColumnKey(indexIDValue,rowID.getValue(),columnID));
+  }
+  
+  /** Set next column's root node for an index node.
+  */
+  protected void setIndexNodeColumnNode(LongValue rowID, long columnID, LongValue refRowID)
+    throws WHException
+  {
+    IndexNodeColumnKey key = new IndexNodeColumnKey(indexIDValue,rowID.getValue(),columnID);
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,refRowID.getValue(),columnID);
+    ts.put(key,refRowID);
+    ts.put(parentKey,key);
+  }
+
+  /** Delete the column root-node child reference for an index node.  Presumes that the reference exists.
+  */
+  protected void deleteIndexNodeColumnNode(LongValue rowID, long columnID)
+    throws WHException
+  {
+    IndexNodeColumnKey key = new IndexNodeColumnKey(indexIDValue,rowID.getValue(),columnID);
+    LongValue childReference = (LongValue)ts.get(key);
+    if (childReference == null)
+      throw new WHConcurrencyException();
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,childReference.getValue(),columnID);
+    ts.put(key,null);
+    ts.put(parentKey,null);
+  }
+  
+  /** Get the lesser child reference for an index node.
+  */
+  protected LongValue readIndexNodeLesserNode(LongValue rowID, long columnID)
+    throws WHException
+  {
+    return (LongValue)ts.get(new IndexNodeLesserKey(indexIDValue,rowID.getValue(),columnID));
+  }
+
+  /** Set the lesser child reference for an index node.  Presumes that no such reference already exists.
+  */
+  protected void setIndexNodeLesserNode(LongValue rowID, long columnID, LongValue refRowID)
+    throws WHException
+  {
+    IndexNodeLesserKey key = new IndexNodeLesserKey(indexIDValue,rowID.getValue(),columnID);
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,refRowID.getValue(),columnID);
+    ts.put(key,refRowID);
+    ts.put(parentKey,key);
+  }
+
+  /** Delete the lesser child reference for an index node.  Presumes that the reference exists.
+  */
+  protected void deleteIndexNodeLesserNode(LongValue rowID, long columnID)
+    throws WHException
+  {
+    IndexNodeLesserKey key = new IndexNodeLesserKey(indexIDValue,rowID.getValue(),columnID);
+    LongValue childReference = (LongValue)ts.get(key);
+    if (childReference == null)
+      throw new WHConcurrencyException();
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,childReference.getValue(),columnID);
+    ts.put(key,null);
+    ts.put(parentKey,null);
+  }
+
+  /** Get the greater child reference for an index node.
+  */
+  protected LongValue readIndexNodeGreaterNode(LongValue rowID, long columnID)
+    throws WHException
+  {
+    return (LongValue)ts.get(new IndexNodeGreaterKey(indexIDValue,rowID.getValue(),columnID));
+  }
+  
+  /** Set the greater child reference for an index node.  Presumes that the reference is currently empty.
+  */
+  protected void setIndexNodeGreaterNode(LongValue rowID, long columnID, LongValue refRowID)
+    throws WHException
+  {
+    IndexNodeGreaterKey key = new IndexNodeGreaterKey(indexIDValue,rowID.getValue(),columnID);
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,refRowID.getValue(),columnID);
+    ts.put(key,refRowID);
+    ts.put(parentKey,key);
+  }
+
+  /** Delete the greater child reference for an index node.  Presumes that the reference exists.
+  */
+  protected void deleteIndexNodeGreaterNode(LongValue rowID, long columnID)
+    throws WHException
+  {
+    IndexNodeGreaterKey key = new IndexNodeGreaterKey(indexIDValue,rowID.getValue(),columnID);
+    LongValue childReference = (LongValue)ts.get(key);
+    if (childReference == null)
+      throw new WHConcurrencyException();
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,childReference.getValue(),columnID);
+    ts.put(key,null);
+    ts.put(parentKey,null);
+  }
+  
+  /** Get the equals child reference for an index node.
+  */
+  protected LongValue readIndexNodeEqualsNode(LongValue rowID, long columnID)
+    throws WHException
+  {
+    return (LongValue)ts.get(new IndexNodeEqualsKey(indexIDValue,rowID.getValue(),columnID));
+  }
+  
+  /** Set the equals child reference for an index node.  Presumes that a reference doesn't yet exist.
+  */
+  protected void setIndexNodeEqualsNode(LongValue rowID, long columnID, LongValue refRowID)
+    throws WHException
+  {
+    IndexNodeEqualsKey key = new IndexNodeEqualsKey(indexIDValue,rowID.getValue(),columnID);
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,refRowID.getValue(),columnID);
+    ts.put(key,refRowID);
+    ts.put(parentKey,key);
+  }
+
+  /** Delete the equals child reference for an index node.  Presumes that the reference exists.
+  */
+  protected void deleteIndexNodeEqualsNode(LongValue rowID, long columnID)
+    throws WHException
+  {
+    IndexNodeEqualsKey key = new IndexNodeEqualsKey(indexIDValue,rowID.getValue(),columnID);
+    LongValue childReference = (LongValue)ts.get(key);
+    if (childReference == null)
+      throw new WHConcurrencyException();
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,childReference.getValue(),columnID);
+    ts.put(key,null);
+    ts.put(parentKey,null);
+  }
+
+  /** Get the parent reference for an index node.
+  */
+  protected WHKey readIndexNodeParentKey(LongValue rowID, long columnID)
+    throws WHException
+  {
+    WHKey rval = (WHKey)ts.get(new IndexNodeParentKey(indexIDValue,rowID.getValue(),columnID));
+    if (rval == null)
+      throw new WHConcurrencyException();
+    return rval;
+  }
+  
+  /** Read the child node of a specified parent node.
+  */
+  protected LongValue readIndexParentChild(WHKey parentKey)
+    throws WHException
+  {
+    return (LongValue)ts.get(parentKey);
+  }
+  
+  /** Set an index parent's child node.  Presumes this child is not set yet.
+  */
+  protected void setIndexParentChild(WHKey parentKey, long columnID, LongValue rowID)
+    throws WHException
+  {
+    ts.put(parentKey,rowID);
+    ts.put(new IndexNodeParentKey(indexIDValue,rowID.getValue(),columnID),parentKey);
+  }
+  
+  /** Remove an index parent's child node reference.  Presumes that this child exists.
+  */
+  protected void deleteIndexParentChild(WHKey parentKey, long columnID)
+    throws WHException
+  {
+    // Get the existing child
+    LongValue childNodeRef = (LongValue)ts.get(parentKey);
+    if (childNodeRef == null)
+      throw new WHConcurrencyException();
+    ts.put(parentKey,null);
+    ts.put(new IndexNodeParentKey(indexIDValue,childNodeRef.getValue(),columnID),null);
+  }
+  
+  /** Get the root pointer for an index.
+  */
+  protected LongValue readIndexRootNode()
+    throws WHException
+  {
+    return (LongValue)ts.get(new IndexRootKey(indexIDValue));
+  }
+  
+  /** Set the root pointer for an index.  Presumes the root pointer does not currently exist.
+  */
+  protected void setIndexRootNode(LongValue rootRowID, long columnID)
+    throws WHException
+  {
+    IndexRootKey key = new IndexRootKey(indexIDValue);
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,rootRowID.getValue(),columnID);
+    ts.put(key,rootRowID);
+    ts.put(parentKey,key);
+  }
+
+  /** Delete the root node reference for an index.  Presumes that the reference exists.
+  */
+  protected void deleteIndexRootNode(long columnID)
+    throws WHException
+  {
+    IndexRootKey key = new IndexRootKey(indexIDValue);
+    LongValue childReference = (LongValue)ts.get(key);
+    if (childReference == null)
+      throw new WHConcurrencyException();
+    IndexNodeParentKey parentKey = new IndexNodeParentKey(indexIDValue,childReference.getValue(),columnID);
+    ts.put(key,null);
+    ts.put(parentKey,null);
+  }
+  
+
+}

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexAccessor.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexAccessor.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexAccessor.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexAccessor.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,306 @@
+/* $Id: IndexAccessor.java 1209929 2011-12-03 15:06:22Z kwright $ */
+
+/**
+* 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.warthog.keyvaluetablestore;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+import org.apache.warthog.common.*;
+import java.util.*;
+
+/** Index accessor, with criteria.
+* The problem with writing an index accessor is the requirement that you be allowed to remove the node you just returned without anything bad
+* happening to the state.  This restriction severely limits how we can store the 'current node'.  Keeping state in a 'stack' won't work because
+* the parent node may well be destroyed, and thus when it becomes time to "pop" up a level we'll have meaningless state to work with.
+* The alternative - keeping a back pointer for each node - is better, since it allows us to keep the entire state using one node reference, but
+* it too has problems.  Specifically, all state is lost when descent into the child occurs, so upon returning to the parent, we don't know where
+* we are or which branches we've already taken.
+*
+* Another alternative is to keep nodes that we've "discovered" in an in-memory ordered queue.  Thus, when we visit a node, we assess immediately
+* which branches we will be taking, and which we will be skipping, and push the "taking" node id's onto the queue in proper order before doing anything else.
+* Since we pull nodes off the queue from the front, and since only that node can be deleted, by definition we cannot mess up the queue.  This is the
+* alternative this class uses.
+*/
+public class IndexAccessor implements WHAccessor
+{
+  protected Index index;
+  protected Table table;
+  protected long[] indexColumnIDs;
+  protected WHComparator[] comparators;
+  protected IndexCriteria[] indexCriteria;
+  protected boolean[] orderReversed;
+
+  /** This is the current node queue.  Nodes on the queue are unevaluated!! */
+  protected NodeQueue queue = new NodeQueue();
+  
+  /** The current (matching) rowID, to be returned */
+  protected LongValue currentRowID;
+  
+  /** Constructor */
+  public IndexAccessor(Index index, IndexCriteria[] indexCriteria, boolean[] orderReversed)
+    throws WHException
+  {
+    this.index = index;
+    this.table = index.getTable();
+    this.indexColumnIDs = index.getIndexColumnIDs();
+    this.comparators = index.getComparators();
+    this.indexCriteria = indexCriteria;
+    this.orderReversed = orderReversed;
+    LongValue rootRowID = index.readIndexRootNode();
+    if (rootRowID != null)
+      queue.pushNeedsAnalysis(rootRowID,0);
+    goToNextLegalRow();
+  }
+  
+  /** Advance to the next row.
+  */
+  public void advance()
+    throws WHException
+  {
+    if (currentRowID != null)
+    {
+      goToNextLegalRow();
+    }
+  }
+  
+  /** Read the current relationship row ID,  Null will be returned if we are
+  * at the end of the sequence.
+  */
+  public WHRowID getCurrentRowID()
+    throws WHException
+  {
+    return currentRowID;
+  }
+	
+  /** Get the data for the current row and specified column. 
+  */
+  public WHValue getValue(String columnName)
+    throws WHException
+  {
+    if (currentRowID != null)
+      return (WHValue)table.getTableColumnValue(currentRowID,table.getColumnID(columnName));
+    throw new WHException("Can't read beyond end of accessor");
+  }
+
+  protected void goToNextLegalRow()
+    throws WHException
+  {
+    while (true)
+    {
+      // Find the next node, using the queue
+      Node node = queue.pop();
+      if (node == null)
+      {
+        currentRowID = null;
+        return;
+      }
+
+      if (node.getAction() == ACTION_DEREFERENCE)
+      {
+        currentRowID = node.getRowID();
+        return;
+      }
+
+      if (node.getAction() == ACTION_CHASE_EQUALS)
+      {
+        // We can skip all analysis, and just chase the equals chain.
+        LongValue chaseRowID = node.getRowID();
+        // Push the rowID, then chase the equals chain.
+        queue.pushNeedsDereference(chaseRowID);
+        // Now find the next node in the equals chain.
+        LongValue nextEqualsNode = index.readIndexNodeEqualsNode(chaseRowID,indexColumnIDs[indexColumnIDs.length-1]);
+        if (nextEqualsNode != null)
+        {
+          // Because it's equals chain, we know that it is unnecessary to evaluate its fields, so note that when
+          // we queue it.
+          queue.pushChaseEquals(nextEqualsNode);
+        }
+        continue;
+      }
+      
+      // This node needs analysis.
+      int columnIndex = node.getColumnIndex();
+      LongValue rowID = node.getRowID();
+      
+      // Evaluate the node, pushing its descendents, and make a decision whether to
+      // use the row or not.
+      
+      // Look at the node and decide about whether to queue up all its pointers.
+      // We can only add at the beginning of the queue, so we must be careful to push
+      // nodes in backwards order!!
+      
+      // Evaluate this column
+      long currentColumnID = indexColumnIDs[columnIndex];
+      // Get the column value
+      WHValue columnValue = (WHValue)index.getTable().getTableColumnValue(rowID,currentColumnID);
+
+      // Do the assessment, if there are index criteria for this column
+      int criteria;
+      if (indexCriteria != null && indexCriteria[columnIndex] != null)
+        criteria = indexCriteria[columnIndex].evaluateValue(columnValue,comparators[columnIndex]);
+      else
+        criteria = IndexCriteria.SIGNAL_LESSER | IndexCriteria.SIGNAL_GREATER | IndexCriteria.SIGNAL_EQUALS;
+
+      // Remember, we want to push greater values first, then lesser.  Order reversal will swap that around.
+      if (orderReversed == null || orderReversed[columnIndex] == false)
+      {
+        if ((criteria & IndexCriteria.SIGNAL_GREATER) != 0)
+        {
+          // Dereference the greater child for this column and push that node for analysis
+          LongValue childRowID = index.readIndexNodeGreaterNode(rowID,indexColumnIDs[columnIndex]);
+          if (childRowID != null)
+            queue.pushNeedsAnalysis(childRowID,columnIndex);
+        }
+        // Do the equals children next
+        if ((criteria & IndexCriteria.SIGNAL_EQUALS) != 0)
+        {
+          // We want to continue on to the next column, or if we're at the end, we take the
+          // row ID. 
+          if (columnIndex + 1 == indexColumnIDs.length)
+            queue.pushChaseEquals(rowID);
+          else
+          {
+            LongValue childRowID = index.readIndexNodeColumnNode(rowID,indexColumnIDs[columnIndex]);
+            if (childRowID == null)
+              throw new WHConcurrencyException();
+            queue.pushNeedsAnalysis(childRowID,columnIndex+1);
+          }
+        }
+        if ((criteria & IndexCriteria.SIGNAL_LESSER) != 0)
+        {
+          // Dereference the lesser child for this column and push that node for analysis
+          LongValue childRowID = index.readIndexNodeLesserNode(rowID,indexColumnIDs[columnIndex]);
+          if (childRowID != null)
+            queue.pushNeedsAnalysis(childRowID,columnIndex);
+        }
+      }
+      else
+      {
+        if ((criteria & IndexCriteria.SIGNAL_LESSER) != 0)
+        {
+          // Dereference the lesser child for this column and push that node for analysis
+          LongValue childRowID = index.readIndexNodeLesserNode(rowID,indexColumnIDs[columnIndex]);
+          if (childRowID != null)
+            queue.pushNeedsAnalysis(childRowID,columnIndex);
+        }
+        // Do the equals children next
+        if ((criteria & IndexCriteria.SIGNAL_EQUALS) != 0)
+        {
+          // We want to continue on to the next column, or if we're at the end, we take the
+          // row ID. 
+          if (columnIndex + 1 == indexColumnIDs.length)
+            queue.pushChaseEquals(rowID);
+          else
+          {
+            LongValue childRowID = index.readIndexNodeColumnNode(rowID,indexColumnIDs[columnIndex]);
+            if (childRowID == null)
+              throw new WHConcurrencyException();
+            queue.pushNeedsAnalysis(childRowID,columnIndex+1);
+          }
+        }
+        if ((criteria & IndexCriteria.SIGNAL_GREATER) != 0)
+        {
+          // Dereference the greater child for this column and push that node for analysis
+          LongValue childRowID = index.readIndexNodeGreaterNode(rowID,indexColumnIDs[columnIndex]);
+          if (childRowID != null)
+            queue.pushNeedsAnalysis(childRowID,columnIndex);
+        }
+      }
+    }
+  }
+  
+  // The types of actions we need the engine to understand, which must be signaled in the queue
+  /** Full analysis */
+  protected static final int ACTION_FULL_ANALYSIS = 0;
+  /** Chase equals chain (no analysis needed) */
+  protected static final int ACTION_CHASE_EQUALS = 1;
+  /** Just dereference to rowID */
+  protected static final int ACTION_DEREFERENCE = 2;
+  
+  /** The node queue */
+  protected static class NodeQueue
+  {
+    protected List<Node> nodeList = new ArrayList<Node>();
+    
+    public NodeQueue()
+    {
+    }
+    
+    public void pushNeedsAnalysis(LongValue rowID, int columnIndex)
+    {
+      nodeList.add(new Node(rowID,columnIndex,ACTION_FULL_ANALYSIS));
+    }
+    
+    public void pushChaseEquals(LongValue rowID)
+    {
+      nodeList.add(new Node(rowID,-1,ACTION_CHASE_EQUALS));
+    }
+    
+    public void pushNeedsDereference(LongValue rowID)
+    {
+      nodeList.add(new Node(rowID,-1,ACTION_DEREFERENCE));
+    }
+    
+    public Node pop()
+    {
+      if (nodeList.size() == 0)
+        return null;
+      return nodeList.remove(nodeList.size()-1);
+    }
+  }
+  
+  /** A node in the queue */
+  protected static class Node
+  {
+    protected LongValue rowID;
+    protected int columnIndex;
+    protected int action;
+    
+    /** Constructor */
+    public Node(LongValue rowID, int columnIndex, int action)
+    {
+      this.rowID = rowID;
+      this.columnIndex = columnIndex;
+      this.action = action;
+    }
+    
+    /** Get the node id.
+    */
+    public LongValue getRowID()
+    {
+      return rowID;
+    }
+    
+    /** Get the column index.
+    */
+    public int getColumnIndex()
+    {
+      return columnIndex;
+    }
+    
+    /** Get whether this node should be treated as needing dereference or needing analysis.
+    */
+    public int getAction()
+    {
+      return action;
+    }
+    
+  }
+  
+}

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexKey.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexKey.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexKey.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexKey.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,39 @@
+/* $Id: IndexKey.java 1207727 2011-11-29 01:12:13Z kwright $ */
+
+/**
+* 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.warthog.keyvaluetablestore;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+import org.apache.warthog.common.*;
+
+/** Key for accessing an index definition */
+public class IndexKey extends LongKey
+{
+  /** Constructor */
+  public IndexKey(long indexID)
+  {
+    super(indexID);
+  }
+    
+  public IndexKey(byte[] data)
+  {
+    super(data);
+  }
+}

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexLookupKey.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexLookupKey.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexLookupKey.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexLookupKey.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,39 @@
+/* $Id: IndexLookupKey.java 1207727 2011-11-29 01:12:13Z kwright $ */
+
+/**
+* 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.warthog.keyvaluetablestore;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+import org.apache.warthog.common.*;
+
+/** Key for accessing an index identifier */
+public class IndexLookupKey extends StringKey
+{
+  /** Constructor */
+  public IndexLookupKey(String name)
+  {
+    super(name);
+  }
+    
+  public IndexLookupKey(byte[] data)
+  {
+    super(data);
+  }
+}

Added: incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexNameKey.java
URL: http://svn.apache.org/viewvc/incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexNameKey.java?rev=1220349&view=auto
==============================================================================
--- incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexNameKey.java (added)
+++ incubator/lcf/branches/CONNECTORS-286/warthog-reimport/src/main/java/org/apache/warthog/keyvaluetablestore/IndexNameKey.java Sun Dec 18 08:26:30 2011
@@ -0,0 +1,39 @@
+/* $Id: IndexNameKey.java 1207727 2011-11-29 01:12:13Z kwright $ */
+
+/**
+* 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.warthog.keyvaluetablestore;
+
+import org.apache.warthog.api.*;
+import org.apache.warthog.transactionalkeyvaluestore.*;
+import org.apache.warthog.common.*;
+
+/** Key class for accessing index name given ID */
+public class IndexNameKey extends LongKey
+{
+  /** Constructor */
+  public IndexNameKey(long indexID)
+  {
+    super(indexID);
+  }
+    
+  public IndexNameKey(byte[] data)
+  {
+    super(data);
+  }
+}