Skip to content

Commit

Permalink
Add a secondary index to VoltXMLElement for children
Browse files Browse the repository at this point in the history
findChild() was executing a linear search. The secondary index allows
a hash lookup, which is faster.
  • Loading branch information
rkennedy-mode committed May 24, 2019
1 parent 9630d68 commit 0833b78
Showing 1 changed file with 57 additions and 7 deletions.
64 changes: 57 additions & 7 deletions src/hsqldb19b3/org/hsqldb_voltpatches/VoltXMLElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
package org.hsqldb_voltpatches;

import com.google_voltpatches.common.base.Strings;
import com.google_voltpatches.common.collect.LinkedListMultimap;
import com.google_voltpatches.common.collect.ListMultimap;
import com.google_voltpatches.common.hash.Hasher;
import com.google_voltpatches.common.hash.Hashing;

Expand All @@ -33,7 +35,14 @@ public class VoltXMLElement {

public String name;
public final Map<String, String> attributes = new TreeMap<>();
public final List<VoltXMLElement> children = new ArrayList<>();

// This used to be a plain list, but we wanted a secondary index on
// the elements and the VoltDB team doesn't believe in encapsulation
// (this list was made public for some reason and now has 250+ references
// to it throughout the codebase). So we've introduced this gross hack,
// which enables us to act like a List with the added benefit of a
// secondary index.
public final SecondaryIndexList children = new SecondaryIndexList();

public VoltXMLElement(String name) {
this.name = name;
Expand Down Expand Up @@ -202,12 +211,7 @@ public List<VoltXMLElement> findChildren(String name)
*/
public VoltXMLElement findChild(String uniqueName)
{
for (VoltXMLElement vxe : children) {
if (uniqueName.equals(vxe.getUniqueName())) {
return vxe;
}
}
return null;
return children.getByUniqueName(uniqueName);
}

/**
Expand Down Expand Up @@ -521,4 +525,50 @@ public Integer getIntAttribute(String key, Integer defval) {
}
return(Integer.parseInt(valstr));
}

public class SecondaryIndexList extends AbstractList<VoltXMLElement> {
private final List<VoltXMLElement> childList = new ArrayList<>();
private final ListMultimap<String, VoltXMLElement> childUniqueNameIndex = LinkedListMultimap.create();

SecondaryIndexList() {
}

VoltXMLElement getByUniqueName(String uniqueName) {
final List<VoltXMLElement> elements = childUniqueNameIndex.get(uniqueName.toUpperCase());
if (elements.isEmpty()) {
return null;
}
return elements.get(0);
}

@Override
public VoltXMLElement get(int index) {
return childList.get(index);
}

@Override
public int size() {
return childList.size();
}

@Override
public VoltXMLElement set(int index, VoltXMLElement element) {
final VoltXMLElement setElement = childList.set(index, element);
childUniqueNameIndex.put(element.getUniqueName().toUpperCase(), element);
return setElement;
}

@Override
public void add(int index, VoltXMLElement element) {
childList.add(index, element);
childUniqueNameIndex.put(element.getUniqueName().toUpperCase(), element);
}

@Override
public VoltXMLElement remove(int index) {
final VoltXMLElement previous = childList.remove(index);
assert(childUniqueNameIndex.remove(previous.getUniqueName().toUpperCase(), previous));
return previous;
}
}
}

0 comments on commit 0833b78

Please sign in to comment.