Skip to content

Commit

Permalink
add diff impls for sorted collections
Browse files Browse the repository at this point in the history
  • Loading branch information
ztellman committed Feb 4, 2020
1 parent 059db93 commit 673ad0f
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 134 deletions.
2 changes: 2 additions & 0 deletions doc/durable.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ If we want to collapse our two files into one, we can simply call `compact()`:
m = m.compact();
```

This will create a third file, representing the merged result of the first two.

We can layer as many diffs atop a collection as we like, but they're primarily intended to be a way to convey changes. To perform a batch update, we can create diffs on one machine, transmit them to all the others, and finally compact them into a new canonical collection.

## comparative benchmarks
Expand Down
22 changes: 3 additions & 19 deletions src/io/lacuna/bifurcan/IDiffSortedMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,20 @@

import io.lacuna.bifurcan.utils.Iterators;

import java.util.Comparator;
import java.util.Iterator;
import java.util.OptionalLong;
import java.util.function.BiPredicate;
import java.util.function.ToLongFunction;

public interface IDiffSortedMap<K, V> extends ISortedMap<K, V> {

ISortedMap<K, ISortedMap<K, V>> segments();

ISortedSet<Long> segmentOffsets();

@Override
default ToLongFunction<K> keyHash() {
return segments().first().value().keyHash();
}

@Override
default BiPredicate<K, K> keyEquality() {
return segments().first().value().keyEquality();
}

@Override
default Comparator<K> comparator() {
return segments().first().value().comparator();
}

@Override
default long size() {
return segmentOffsets().last() + segments().last().value().size();
return segments().size() == 0
? 0
: segmentOffsets().last() + segments().last().value().size();
}

@Override
Expand Down
11 changes: 0 additions & 11 deletions src/io/lacuna/bifurcan/IDiffSortedSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import java.util.Comparator;
import java.util.Iterator;
import java.util.OptionalLong;
import java.util.function.BiPredicate;
import java.util.function.ToLongFunction;

public interface IDiffSortedSet<V> extends ISortedSet<V> {

Expand All @@ -16,15 +14,6 @@ public interface IDiffSortedSet<V> extends ISortedSet<V> {
default Comparator<V> comparator() {
return diffMap().comparator();
}
@Override
default ToLongFunction<V> valueHash() {
return diffMap().keyHash();
}

@Override
default BiPredicate<V, V> valueEquality() {
return diffMap().keyEquality();
}

@Override
default long size() {
Expand Down
1 change: 1 addition & 0 deletions src/io/lacuna/bifurcan/ISet.java
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ default ISet<V> linear() {

@Override
default IList<? extends ISet<V>> split(int parts) {
// TODO: do an actual slice here
parts = Math.max(1, Math.min((int) size(), parts));
return elements().split(parts).stream().map(LinearSet::from).collect(Lists.collector());
}
Expand Down
20 changes: 17 additions & 3 deletions src/io/lacuna/bifurcan/ISortedMap.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package io.lacuna.bifurcan;

import io.lacuna.bifurcan.diffs.ConcatSortedMap;

import java.util.Comparator;
import java.util.OptionalLong;
import java.util.function.BiPredicate;
import java.util.function.BinaryOperator;
import java.util.function.ToLongFunction;
import java.util.function.UnaryOperator;

/**
Expand All @@ -14,6 +18,16 @@ public interface ISortedMap<K, V> extends IMap<K, V> {

OptionalLong floorIndex(K key);

@Override
default ToLongFunction<K> keyHash() {
throw new UnsupportedOperationException("ISortedMap does not use hashes");
}

@Override
default BiPredicate<K, K> keyEquality() {
return (a, b) -> comparator().compare(a, b) == 0;
}

@Override
default ISortedSet<K> keys() {
return Sets.from(Lists.lazyMap(this.entries(), IEntry::key), comparator(), this::floorIndex);
Expand Down Expand Up @@ -100,7 +114,7 @@ default ISortedMap<K, V> difference(IMap<K, ?> m) {
}

default ISortedMap<K, V> put(K key, V value, BinaryOperator<V> merge) {
return null;
return ConcatSortedMap.from(comparator(), this).put(key, value, merge);
}

default ISortedMap<K, V> update(K key, UnaryOperator<V> update) {
Expand All @@ -112,15 +126,15 @@ default ISortedMap<K, V> put(K key, V value) {
}

default ISortedMap<K, V> remove(K key) {
return null;
return ConcatSortedMap.from(comparator(), this).remove(key);
}

default ISortedMap<K, V> forked() {
return this;
}

default ISortedMap<K, V> linear() {
return null;
return ConcatSortedMap.from(comparator(), this).linear();
}

default IEntry<K, V> first() {
Expand Down
20 changes: 17 additions & 3 deletions src/io/lacuna/bifurcan/ISortedSet.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package io.lacuna.bifurcan;

import io.lacuna.bifurcan.diffs.DiffSortedSet;

import java.util.Comparator;
import java.util.OptionalLong;
import java.util.function.BiPredicate;
import java.util.function.ToLongFunction;

public interface ISortedSet<V> extends ISet<V> {

Expand All @@ -13,6 +17,16 @@ public interface ISortedSet<V> extends ISet<V> {
*/
OptionalLong floorIndex(V val);

@Override
default ToLongFunction<V> valueHash() {
throw new UnsupportedOperationException("ISortedSet does not use hashes");
}

@Override
default BiPredicate<V, V> valueEquality() {
return (a, b) -> comparator().compare(a, b) == 0;
}

/**
* @return the entry whose key is either equal to {@code key}, or just above it. If {@code key} is greater than the
* maximum value in the map, returns {@code null}.
Expand Down Expand Up @@ -89,11 +103,11 @@ default ISortedSet<V> slice(V min, V max) {
}

default ISortedSet<V> add(V value) {
return null;
return new DiffSortedSet<V>(this).add(value);
}

default ISortedSet<V> remove(V value) {
return null;
return new DiffSortedSet<V>(this).remove(value);
}

default ISortedSet<V> union(ISet<V> s) {
Expand All @@ -113,7 +127,7 @@ default ISortedSet<V> forked() {
}

default ISortedSet<V> linear() {
return null;
return new DiffSortedSet<V>(this).linear();
}

default V first() {
Expand Down
29 changes: 19 additions & 10 deletions src/io/lacuna/bifurcan/Maps.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,6 @@ public ISortedMap<K, V> slice(K min, K max) {
return from(keys.slice(min, max), lookup);
}

@Override
public ToLongFunction<K> keyHash() {
return keys.valueHash();
}

@Override
public BiPredicate<K, K> keyEquality() {
return keys.valueEquality();
}

@Override
public long size() {
return keys.size();
Expand All @@ -210,6 +200,25 @@ public Iterator<IEntry<K, V>> iterator() {
public IMap<K, V> clone() {
return this;
}

@Override
public int hashCode() {
return (int) Maps.hash(this);
}

@Override
public boolean equals(Object obj) {
if (obj instanceof IMap) {
return Maps.equals(this, (IMap) obj);
} else {
return false;
}
}

@Override
public String toString() {
return Maps.toString(this);
}
};
}

Expand Down
29 changes: 19 additions & 10 deletions src/io/lacuna/bifurcan/Sets.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,16 +139,6 @@ public OptionalLong floorIndex(V val) {
return floorIndex.apply(val);
}

@Override
public ToLongFunction<V> valueHash() {
return Objects::hashCode;
}

@Override
public BiPredicate<V, V> valueEquality() {
return (a, b) -> comparator().compare(a, b) == 0;
}

@Override
public long size() {
return elements.size();
Expand All @@ -163,6 +153,25 @@ public V nth(long idx) {
public ISet<V> clone() {
return this;
}

@Override
public int hashCode() {
return (int) Sets.hash(this);
}

@Override
public boolean equals(Object obj) {
if (obj instanceof ISet) {
return Sets.equals(this, (ISet) obj);
} else {
return false;
}
}

@Override
public String toString() {
return Sets.toString(this);
}
};
}

Expand Down
3 changes: 1 addition & 2 deletions src/io/lacuna/bifurcan/SortedMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,12 @@ public Iterator<IEntry<K, V>> iterator() {
@Override
public IEntry<K, V> nth(long idx) {
if (idx < 0 || idx >= size()) {
throw new IndexOutOfBoundsException();
throw new IndexOutOfBoundsException(String.format("%d must be within [0,%d)", idx, size()));
}
Node<K, V> n = SortedMapNodes.nth(root, (int) idx);
return IEntry.of(n.k, n.v);
}

@Override
public long size() {
return root.size;
}
Expand Down
Loading

0 comments on commit 673ad0f

Please sign in to comment.