delta-aggregation in the ORMap deltas (#22633)

This commit is contained in:
gosubpl 2017-03-24 16:18:01 +01:00
parent ecbcc56f28
commit 7c42627ea9
10 changed files with 728 additions and 231 deletions

View file

@ -10906,19 +10906,30 @@ public final class ReplicatedDataMessages {
*/ */
int getZeroTag(); int getZeroTag();
// optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4; // repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
boolean hasEntryData(); java.util.List<akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry>
getEntryDataList();
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry getEntryData(); akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry getEntryData(int index);
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder getEntryDataOrBuilder(); int getEntryDataCount();
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
java.util.List<? extends akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder>
getEntryDataOrBuilderList();
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder getEntryDataOrBuilder(
int index);
} }
/** /**
* Protobuf type {@code akka.cluster.ddata.ORMapDeltaGroup.Entry} * Protobuf type {@code akka.cluster.ddata.ORMapDeltaGroup.Entry}
@ -11001,16 +11012,11 @@ public final class ReplicatedDataMessages {
break; break;
} }
case 34: { case 34: {
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder subBuilder = null; if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
if (((bitField0_ & 0x00000008) == 0x00000008)) { entryData_ = new java.util.ArrayList<akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry>();
subBuilder = entryData_.toBuilder(); mutable_bitField0_ |= 0x00000008;
} }
entryData_ = input.readMessage(akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.PARSER, extensionRegistry); entryData_.add(input.readMessage(akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.PARSER, extensionRegistry));
if (subBuilder != null) {
subBuilder.mergeFrom(entryData_);
entryData_ = subBuilder.buildPartial();
}
bitField0_ |= 0x00000008;
break; break;
} }
} }
@ -11021,6 +11027,9 @@ public final class ReplicatedDataMessages {
throw new akka.protobuf.InvalidProtocolBufferException( throw new akka.protobuf.InvalidProtocolBufferException(
e.getMessage()).setUnfinishedMessage(this); e.getMessage()).setUnfinishedMessage(this);
} finally { } finally {
if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
entryData_ = java.util.Collections.unmodifiableList(entryData_);
}
this.unknownFields = unknownFields.build(); this.unknownFields = unknownFields.build();
makeExtensionsImmutable(); makeExtensionsImmutable();
} }
@ -11107,33 +11116,47 @@ public final class ReplicatedDataMessages {
return zeroTag_; return zeroTag_;
} }
// optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4; // repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;
public static final int ENTRYDATA_FIELD_NUMBER = 4; public static final int ENTRYDATA_FIELD_NUMBER = 4;
private akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry entryData_; private java.util.List<akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry> entryData_;
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
public boolean hasEntryData() { public java.util.List<akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry> getEntryDataList() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
/**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry getEntryData() {
return entryData_; return entryData_;
} }
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder getEntryDataOrBuilder() { public java.util.List<? extends akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder>
getEntryDataOrBuilderList() {
return entryData_; return entryData_;
} }
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public int getEntryDataCount() {
return entryData_.size();
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry getEntryData(int index) {
return entryData_.get(index);
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder getEntryDataOrBuilder(
int index) {
return entryData_.get(index);
}
private void initFields() { private void initFields() {
operation_ = akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaOp.ORMapPut; operation_ = akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaOp.ORMapPut;
underlying_ = akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORSet.getDefaultInstance(); underlying_ = akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORSet.getDefaultInstance();
zeroTag_ = 0; zeroTag_ = 0;
entryData_ = akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.getDefaultInstance(); entryData_ = java.util.Collections.emptyList();
} }
private byte memoizedIsInitialized = -1; private byte memoizedIsInitialized = -1;
public final boolean isInitialized() { public final boolean isInitialized() {
@ -11156,8 +11179,8 @@ public final class ReplicatedDataMessages {
memoizedIsInitialized = 0; memoizedIsInitialized = 0;
return false; return false;
} }
if (hasEntryData()) { for (int i = 0; i < getEntryDataCount(); i++) {
if (!getEntryData().isInitialized()) { if (!getEntryData(i).isInitialized()) {
memoizedIsInitialized = 0; memoizedIsInitialized = 0;
return false; return false;
} }
@ -11178,8 +11201,8 @@ public final class ReplicatedDataMessages {
if (((bitField0_ & 0x00000004) == 0x00000004)) { if (((bitField0_ & 0x00000004) == 0x00000004)) {
output.writeSInt32(3, zeroTag_); output.writeSInt32(3, zeroTag_);
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { for (int i = 0; i < entryData_.size(); i++) {
output.writeMessage(4, entryData_); output.writeMessage(4, entryData_.get(i));
} }
getUnknownFields().writeTo(output); getUnknownFields().writeTo(output);
} }
@ -11202,9 +11225,9 @@ public final class ReplicatedDataMessages {
size += akka.protobuf.CodedOutputStream size += akka.protobuf.CodedOutputStream
.computeSInt32Size(3, zeroTag_); .computeSInt32Size(3, zeroTag_);
} }
if (((bitField0_ & 0x00000008) == 0x00000008)) { for (int i = 0; i < entryData_.size(); i++) {
size += akka.protobuf.CodedOutputStream size += akka.protobuf.CodedOutputStream
.computeMessageSize(4, entryData_); .computeMessageSize(4, entryData_.get(i));
} }
size += getUnknownFields().getSerializedSize(); size += getUnknownFields().getSerializedSize();
memoizedSerializedSize = size; memoizedSerializedSize = size;
@ -11335,11 +11358,11 @@ public final class ReplicatedDataMessages {
zeroTag_ = 0; zeroTag_ = 0;
bitField0_ = (bitField0_ & ~0x00000004); bitField0_ = (bitField0_ & ~0x00000004);
if (entryDataBuilder_ == null) { if (entryDataBuilder_ == null) {
entryData_ = akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.getDefaultInstance(); entryData_ = java.util.Collections.emptyList();
bitField0_ = (bitField0_ & ~0x00000008);
} else { } else {
entryDataBuilder_.clear(); entryDataBuilder_.clear();
} }
bitField0_ = (bitField0_ & ~0x00000008);
return this; return this;
} }
@ -11384,10 +11407,11 @@ public final class ReplicatedDataMessages {
to_bitField0_ |= 0x00000004; to_bitField0_ |= 0x00000004;
} }
result.zeroTag_ = zeroTag_; result.zeroTag_ = zeroTag_;
if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
to_bitField0_ |= 0x00000008;
}
if (entryDataBuilder_ == null) { if (entryDataBuilder_ == null) {
if (((bitField0_ & 0x00000008) == 0x00000008)) {
entryData_ = java.util.Collections.unmodifiableList(entryData_);
bitField0_ = (bitField0_ & ~0x00000008);
}
result.entryData_ = entryData_; result.entryData_ = entryData_;
} else { } else {
result.entryData_ = entryDataBuilder_.build(); result.entryData_ = entryDataBuilder_.build();
@ -11417,8 +11441,31 @@ public final class ReplicatedDataMessages {
if (other.hasZeroTag()) { if (other.hasZeroTag()) {
setZeroTag(other.getZeroTag()); setZeroTag(other.getZeroTag());
} }
if (other.hasEntryData()) { if (entryDataBuilder_ == null) {
mergeEntryData(other.getEntryData()); if (!other.entryData_.isEmpty()) {
if (entryData_.isEmpty()) {
entryData_ = other.entryData_;
bitField0_ = (bitField0_ & ~0x00000008);
} else {
ensureEntryDataIsMutable();
entryData_.addAll(other.entryData_);
}
onChanged();
}
} else {
if (!other.entryData_.isEmpty()) {
if (entryDataBuilder_.isEmpty()) {
entryDataBuilder_.dispose();
entryDataBuilder_ = null;
entryData_ = other.entryData_;
bitField0_ = (bitField0_ & ~0x00000008);
entryDataBuilder_ =
akka.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
getEntryDataFieldBuilder() : null;
} else {
entryDataBuilder_.addAllMessages(other.entryData_);
}
}
} }
this.mergeUnknownFields(other.getUnknownFields()); this.mergeUnknownFields(other.getUnknownFields());
return this; return this;
@ -11441,8 +11488,8 @@ public final class ReplicatedDataMessages {
return false; return false;
} }
if (hasEntryData()) { for (int i = 0; i < getEntryDataCount(); i++) {
if (!getEntryData().isInitialized()) { if (!getEntryData(i).isInitialized()) {
return false; return false;
} }
@ -11655,116 +11702,239 @@ public final class ReplicatedDataMessages {
return this; return this;
} }
// optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4; // repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;
private akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry entryData_ = akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.getDefaultInstance(); private java.util.List<akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry> entryData_ =
private akka.protobuf.SingleFieldBuilder< java.util.Collections.emptyList();
private void ensureEntryDataIsMutable() {
if (!((bitField0_ & 0x00000008) == 0x00000008)) {
entryData_ = new java.util.ArrayList<akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry>(entryData_);
bitField0_ |= 0x00000008;
}
}
private akka.protobuf.RepeatedFieldBuilder<
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder> entryDataBuilder_; akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder> entryDataBuilder_;
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
public boolean hasEntryData() { public java.util.List<akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry> getEntryDataList() {
return ((bitField0_ & 0x00000008) == 0x00000008);
}
/**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry getEntryData() {
if (entryDataBuilder_ == null) { if (entryDataBuilder_ == null) {
return entryData_; return java.util.Collections.unmodifiableList(entryData_);
} else { } else {
return entryDataBuilder_.getMessage(); return entryDataBuilder_.getMessageList();
} }
} }
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
public Builder setEntryData(akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry value) { public int getEntryDataCount() {
if (entryDataBuilder_ == null) {
return entryData_.size();
} else {
return entryDataBuilder_.getCount();
}
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry getEntryData(int index) {
if (entryDataBuilder_ == null) {
return entryData_.get(index);
} else {
return entryDataBuilder_.getMessage(index);
}
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public Builder setEntryData(
int index, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry value) {
if (entryDataBuilder_ == null) { if (entryDataBuilder_ == null) {
if (value == null) { if (value == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
entryData_ = value; ensureEntryDataIsMutable();
entryData_.set(index, value);
onChanged(); onChanged();
} else { } else {
entryDataBuilder_.setMessage(value); entryDataBuilder_.setMessage(index, value);
} }
bitField0_ |= 0x00000008;
return this; return this;
} }
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
public Builder setEntryData( public Builder setEntryData(
int index, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder builderForValue) {
if (entryDataBuilder_ == null) {
ensureEntryDataIsMutable();
entryData_.set(index, builderForValue.build());
onChanged();
} else {
entryDataBuilder_.setMessage(index, builderForValue.build());
}
return this;
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public Builder addEntryData(akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry value) {
if (entryDataBuilder_ == null) {
if (value == null) {
throw new NullPointerException();
}
ensureEntryDataIsMutable();
entryData_.add(value);
onChanged();
} else {
entryDataBuilder_.addMessage(value);
}
return this;
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public Builder addEntryData(
int index, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry value) {
if (entryDataBuilder_ == null) {
if (value == null) {
throw new NullPointerException();
}
ensureEntryDataIsMutable();
entryData_.add(index, value);
onChanged();
} else {
entryDataBuilder_.addMessage(index, value);
}
return this;
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public Builder addEntryData(
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder builderForValue) { akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder builderForValue) {
if (entryDataBuilder_ == null) { if (entryDataBuilder_ == null) {
entryData_ = builderForValue.build(); ensureEntryDataIsMutable();
entryData_.add(builderForValue.build());
onChanged(); onChanged();
} else { } else {
entryDataBuilder_.setMessage(builderForValue.build()); entryDataBuilder_.addMessage(builderForValue.build());
} }
bitField0_ |= 0x00000008;
return this; return this;
} }
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
public Builder mergeEntryData(akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry value) { public Builder addEntryData(
int index, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder builderForValue) {
if (entryDataBuilder_ == null) { if (entryDataBuilder_ == null) {
if (((bitField0_ & 0x00000008) == 0x00000008) && ensureEntryDataIsMutable();
entryData_ != akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.getDefaultInstance()) { entryData_.add(index, builderForValue.build());
entryData_ =
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.newBuilder(entryData_).mergeFrom(value).buildPartial();
} else {
entryData_ = value;
}
onChanged(); onChanged();
} else { } else {
entryDataBuilder_.mergeFrom(value); entryDataBuilder_.addMessage(index, builderForValue.build());
} }
bitField0_ |= 0x00000008;
return this; return this;
} }
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public Builder addAllEntryData(
java.lang.Iterable<? extends akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry> values) {
if (entryDataBuilder_ == null) {
ensureEntryDataIsMutable();
super.addAll(values, entryData_);
onChanged();
} else {
entryDataBuilder_.addAllMessages(values);
}
return this;
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
public Builder clearEntryData() { public Builder clearEntryData() {
if (entryDataBuilder_ == null) { if (entryDataBuilder_ == null) {
entryData_ = akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.getDefaultInstance(); entryData_ = java.util.Collections.emptyList();
bitField0_ = (bitField0_ & ~0x00000008);
onChanged(); onChanged();
} else { } else {
entryDataBuilder_.clear(); entryDataBuilder_.clear();
} }
bitField0_ = (bitField0_ & ~0x00000008);
return this; return this;
} }
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder getEntryDataBuilder() { public Builder removeEntryData(int index) {
bitField0_ |= 0x00000008; if (entryDataBuilder_ == null) {
ensureEntryDataIsMutable();
entryData_.remove(index);
onChanged(); onChanged();
return getEntryDataFieldBuilder().getBuilder();
}
/**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder getEntryDataOrBuilder() {
if (entryDataBuilder_ != null) {
return entryDataBuilder_.getMessageOrBuilder();
} else { } else {
return entryData_; entryDataBuilder_.remove(index);
}
return this;
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder getEntryDataBuilder(
int index) {
return getEntryDataFieldBuilder().getBuilder(index);
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder getEntryDataOrBuilder(
int index) {
if (entryDataBuilder_ == null) {
return entryData_.get(index); } else {
return entryDataBuilder_.getMessageOrBuilder(index);
} }
} }
/** /**
* <code>optional .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code> * <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/ */
private akka.protobuf.SingleFieldBuilder< public java.util.List<? extends akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder>
getEntryDataOrBuilderList() {
if (entryDataBuilder_ != null) {
return entryDataBuilder_.getMessageOrBuilderList();
} else {
return java.util.Collections.unmodifiableList(entryData_);
}
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder addEntryDataBuilder() {
return getEntryDataFieldBuilder().addBuilder(
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.getDefaultInstance());
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder addEntryDataBuilder(
int index) {
return getEntryDataFieldBuilder().addBuilder(
index, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.getDefaultInstance());
}
/**
* <code>repeated .akka.cluster.ddata.ORMapDeltaGroup.MapEntry entryData = 4;</code>
*/
public java.util.List<akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder>
getEntryDataBuilderList() {
return getEntryDataFieldBuilder().getBuilderList();
}
private akka.protobuf.RepeatedFieldBuilder<
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder> akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder>
getEntryDataFieldBuilder() { getEntryDataFieldBuilder() {
if (entryDataBuilder_ == null) { if (entryDataBuilder_ == null) {
entryDataBuilder_ = new akka.protobuf.SingleFieldBuilder< entryDataBuilder_ = new akka.protobuf.RepeatedFieldBuilder<
akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder>( akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntry.Builder, akka.cluster.ddata.protobuf.msg.ReplicatedDataMessages.ORMapDeltaGroup.MapEntryOrBuilder>(
entryData_, entryData_,
((bitField0_ & 0x00000008) == 0x00000008),
getParentForChildren(), getParentForChildren(),
isClean()); isClean());
entryData_ = null; entryData_ = null;
@ -18398,7 +18568,7 @@ public final class ReplicatedDataMessages {
"erMessage\032\275\001\n\005Entry\0223\n\toperation\030\001 \002(\0162 ", "erMessage\032\275\001\n\005Entry\0223\n\toperation\030\001 \002(\0162 ",
".akka.cluster.ddata.ORMapDeltaOp\022-\n\nunde" + ".akka.cluster.ddata.ORMapDeltaOp\022-\n\nunde" +
"rlying\030\002 \002(\0132\031.akka.cluster.ddata.ORSet\022" + "rlying\030\002 \002(\0132\031.akka.cluster.ddata.ORSet\022" +
"\017\n\007zeroTag\030\003 \002(\021\022?\n\tentryData\030\004 \001(\0132,.ak" + "\017\n\007zeroTag\030\003 \002(\021\022?\n\tentryData\030\004 \003(\0132,.ak" +
"ka.cluster.ddata.ORMapDeltaGroup.MapEntr" + "ka.cluster.ddata.ORMapDeltaGroup.MapEntr" +
"y\"\206\002\n\006LWWMap\022\'\n\004keys\030\001 \002(\0132\031.akka.cluste" + "y\"\206\002\n\006LWWMap\022\'\n\004keys\030\001 \002(\0132\031.akka.cluste" +
"r.ddata.ORSet\0221\n\007entries\030\002 \003(\0132 .akka.cl" + "r.ddata.ORSet\0221\n\007entries\030\002 \003(\0132 .akka.cl" +

View file

@ -87,7 +87,7 @@ message ORMapDeltaGroup {
required ORMapDeltaOp operation = 1; required ORMapDeltaOp operation = 1;
required ORSet underlying = 2; required ORSet underlying = 2;
required sint32 zeroTag = 3; required sint32 zeroTag = 3;
optional MapEntry entryData = 4; repeated MapEntry entryData = 4;
} }
repeated Entry entries = 1; repeated Entry entries = 1;

View file

@ -6,10 +6,18 @@ package akka.cluster.ddata
import akka.cluster.Cluster import akka.cluster.Cluster
import akka.cluster.UniqueAddress import akka.cluster.UniqueAddress
import akka.annotation.InternalApi import akka.annotation.InternalApi
import akka.cluster.ddata.ORMap.LWWMapTag import akka.cluster.ddata.ORMap.ZeroTag
object LWWMap { object LWWMap {
private val _empty: LWWMap[Any, Any] = new LWWMap(ORMap.emptyWithLWWMapTag) /**
* INTERNAL API
*/
@InternalApi private[akka] case object LWWMapTag extends ZeroTag {
override def zero: DeltaReplicatedData = LWWMap.empty
override final val value: Int = 4
}
private val _empty: LWWMap[Any, Any] = new LWWMap(new ORMap(ORSet.empty, Map.empty, zeroTag = LWWMapTag))
def empty[A, B]: LWWMap[A, B] = _empty.asInstanceOf[LWWMap[A, B]] def empty[A, B]: LWWMap[A, B] = _empty.asInstanceOf[LWWMap[A, B]]
def apply(): LWWMap[Any, Any] = _empty def apply(): LWWMap[Any, Any] = _empty
/** /**

View file

@ -12,7 +12,7 @@ import akka.cluster.ddata.ORMap.{ AtomicDeltaOp, ZeroTag }
import scala.collection.immutable import scala.collection.immutable
object ORMap { object ORMap {
private val _empty: ORMap[Any, ReplicatedData] = new ORMap(ORSet.empty, Map.empty) private val _empty: ORMap[Any, ReplicatedData] = new ORMap(ORSet.empty, Map.empty, VanillaORMapTag)
def empty[A, B <: ReplicatedData]: ORMap[A, B] = _empty.asInstanceOf[ORMap[A, B]] def empty[A, B <: ReplicatedData]: ORMap[A, B] = _empty.asInstanceOf[ORMap[A, B]]
def apply(): ORMap[Any, ReplicatedData] = _empty def apply(): ORMap[Any, ReplicatedData] = _empty
/** /**
@ -30,26 +30,6 @@ object ORMap {
override def zero: DeltaReplicatedData override def zero: DeltaReplicatedData
} }
/**
* INTERNAL API
*/
@InternalApi private[akka] def emptyWithPNCounterMapTag[A, B <: ReplicatedData]: ORMap[A, B] = new ORMap(ORSet.empty, Map.empty, zeroTag = PNCounterMapTag)
/**
* INTERNAL API
*/
@InternalApi private[akka] def emptyWithORMultiMapTag[A, B <: ReplicatedData]: ORMap[A, B] = new ORMap(ORSet.empty, Map.empty, zeroTag = ORMultiMapTag)
/**
* INTERNAL API
*/
@InternalApi private[akka] def emptyWithORMultiMapWithValueDeltasTag[A, B <: ReplicatedData]: ORMap[A, B] = new ORMap(ORSet.empty, Map.empty, zeroTag = ORMultiMapWithValueDeltasTag)
/**
* INTERNAL API
*/
@InternalApi private[akka] def emptyWithLWWMapTag[A, B <: ReplicatedData]: ORMap[A, B] = new ORMap(ORSet.empty, Map.empty, zeroTag = LWWMapTag)
/** /**
* INTERNAL API * INTERNAL API
* Tags for ORMap.DeltaOp's, so that when the Replicator needs to re-create full value from delta, * Tags for ORMap.DeltaOp's, so that when the Replicator needs to re-create full value from delta,
@ -68,38 +48,6 @@ object ORMap {
override final val value: Int = 0 override final val value: Int = 0
} }
/**
* INTERNAL API
*/
@InternalApi private[akka] case object PNCounterMapTag extends ZeroTag {
override def zero: DeltaReplicatedData = PNCounterMap.empty
override final val value: Int = 1
}
/**
* INTERNAL API
*/
@InternalApi private[akka] case object ORMultiMapTag extends ZeroTag {
override def zero: DeltaReplicatedData = ORMultiMap.empty
override final val value: Int = 2
}
/**
* INTERNAL API
*/
@InternalApi private[akka] case object ORMultiMapWithValueDeltasTag extends ZeroTag {
override def zero: DeltaReplicatedData = ORMultiMap.emptyWithValueDeltas
override final val value: Int = 3
}
/**
* INTERNAL API
*/
@InternalApi private[akka] case object LWWMapTag extends ZeroTag {
override def zero: DeltaReplicatedData = LWWMap.empty
override final val value: Int = 4
}
/** /**
* INTERNAL API * INTERNAL API
*/ */
@ -107,7 +55,6 @@ object ORMap {
def underlying: ORSet.DeltaOp def underlying: ORSet.DeltaOp
def zeroTag: ZeroTag def zeroTag: ZeroTag
override def zero: DeltaReplicatedData = zeroTag.zero override def zero: DeltaReplicatedData = zeroTag.zero
override def merge(that: DeltaOp): DeltaOp = that match { override def merge(that: DeltaOp): DeltaOp = that match {
case other: AtomicDeltaOp[A, B] DeltaGroup(Vector(this, other)) case other: AtomicDeltaOp[A, B] DeltaGroup(Vector(this, other))
case DeltaGroup(ops) DeltaGroup(this +: ops) case DeltaGroup(ops) DeltaGroup(this +: ops)
@ -116,30 +63,79 @@ object ORMap {
// PutDeltaOp contains ORSet delta and full value // PutDeltaOp contains ORSet delta and full value
/** INTERNAL API */ /** INTERNAL API */
@InternalApi private[akka] final case class PutDeltaOp[A, B <: ReplicatedData](underlying: ORSet.DeltaOp, value: (A, B), zeroTag: ZeroTag = VanillaORMapTag) extends AtomicDeltaOp[A, B] { @InternalApi private[akka] final case class PutDeltaOp[A, B <: ReplicatedData](underlying: ORSet.DeltaOp, value: (A, B), zeroTag: ZeroTag) extends AtomicDeltaOp[A, B] {
override def merge(that: DeltaOp): DeltaOp = that match {
case put: PutDeltaOp[A, B] if this.value._1 == put.value._1
new PutDeltaOp[A, B](this.underlying.merge(put.underlying), put.value, zeroTag)
case update: UpdateDeltaOp[A, B] if update.values.size == 1 && update.values.contains(this.value._1)
val (key, elem1) = this.value
val newValue = elem1 match {
case e1: DeltaReplicatedData
val e2 = update.values.head._2.asInstanceOf[e1.D]
(key, e1.mergeDelta(e2).asInstanceOf[B])
case _
val elem2 = update.values.head._2.asInstanceOf[elem1.T]
(key, elem1.merge(elem2).asInstanceOf[B])
}
new PutDeltaOp[A, B](this.underlying.merge(update.underlying), newValue, zeroTag)
case other: AtomicDeltaOp[A, B] DeltaGroup(Vector(this, other))
case DeltaGroup(ops) DeltaGroup(this +: ops)
}
} }
// UpdateDeltaOp contains ORSet delta and either delta of value (in case where underlying type supports deltas) or full value // UpdateDeltaOp contains ORSet delta and either delta of value (in case where underlying type supports deltas) or full value
/** INTERNAL API */ /** INTERNAL API */
@InternalApi private[akka] final case class UpdateDeltaOp[A, X <: ReplicatedDelta](underlying: ORSet.DeltaOp, values: Map[A, X], zeroTag: ZeroTag = VanillaORMapTag) extends AtomicDeltaOp[A, X] { @InternalApi private[akka] final case class UpdateDeltaOp[A, B <: ReplicatedData](underlying: ORSet.DeltaOp, values: Map[A, B], zeroTag: ZeroTag) extends AtomicDeltaOp[A, B] {
override def merge(that: DeltaOp): DeltaOp = that match {
case update: UpdateDeltaOp[A, B]
new UpdateDeltaOp[A, B](
this.underlying.merge(update.underlying),
update.values.foldLeft(this.values) {
(map, pair)
val (key, value) = pair
if (this.values.contains(key)) {
val elem1 = this.values(key)
val elem2 = value.asInstanceOf[elem1.T]
map + (key elem1.merge(elem2).asInstanceOf[B])
} else map + pair
},
zeroTag)
case put: PutDeltaOp[A, B] if this.values.size == 1 && this.values.contains(put.value._1)
new PutDeltaOp[A, B](this.underlying.merge(put.underlying), put.value, zeroTag)
case other: AtomicDeltaOp[A, B] DeltaGroup(Vector(this, other))
case DeltaGroup(ops) DeltaGroup(this +: ops)
}
} }
// RemoveDeltaOp does not contain any value at all - the propagated 'value' map is empty // RemoveDeltaOp does not contain any value at all - the propagated 'value' map would be empty
/** INTERNAL API */ /** INTERNAL API */
@InternalApi private[akka] final case class RemoveDeltaOp[A, B <: ReplicatedData](underlying: ORSet.DeltaOp, zeroTag: ZeroTag = VanillaORMapTag) extends AtomicDeltaOp[A, B] { @InternalApi private[akka] final case class RemoveDeltaOp[A, B <: ReplicatedData](underlying: ORSet.DeltaOp, zeroTag: ZeroTag) extends AtomicDeltaOp[A, B]
}
// RemoveKeyDeltaOp contains a single value - to provide the recipient with the removed key for value map // RemoveKeyDeltaOp contains a single value - to provide the recipient with the removed key for value map
/** INTERNAL API */ /** INTERNAL API */
@InternalApi private[akka] final case class RemoveKeyDeltaOp[A, B <: ReplicatedData](underlying: ORSet.DeltaOp, removedKey: A, zeroTag: ZeroTag = VanillaORMapTag) extends AtomicDeltaOp[A, B] { @InternalApi private[akka] final case class RemoveKeyDeltaOp[A, B <: ReplicatedData](underlying: ORSet.DeltaOp, removedKey: A, zeroTag: ZeroTag) extends AtomicDeltaOp[A, B]
}
// DeltaGroup is effectively a causally ordered list of individual deltas // DeltaGroup is effectively a causally ordered list of individual deltas
/** INTERNAL API */ /** INTERNAL API */
@InternalApi private[akka] final case class DeltaGroup[A, B <: ReplicatedData](ops: immutable.IndexedSeq[DeltaOp]) extends DeltaOp { @InternalApi private[akka] final case class DeltaGroup[A, B <: ReplicatedData](ops: immutable.IndexedSeq[DeltaOp]) extends DeltaOp {
override def merge(that: DeltaOp): DeltaOp = that match { override def merge(that: DeltaOp): DeltaOp = that match {
case that: AtomicDeltaOp[A, B]
ops.last match {
case thisPut: PutDeltaOp[A, B]
val merged = thisPut.merge(that)
merged match {
case op: AtomicDeltaOp[A, B] DeltaGroup(ops.dropRight(1) :+ op)
case DeltaGroup(thatOps) DeltaGroup(ops.dropRight(1) ++ thatOps)
}
case thisUpdate: UpdateDeltaOp[A, B]
val merged = thisUpdate.merge(that)
merged match {
case op: AtomicDeltaOp[A, B] DeltaGroup(ops.dropRight(1) :+ op)
case DeltaGroup(thatOps) DeltaGroup(ops.dropRight(1) ++ thatOps)
}
case _ DeltaGroup(ops :+ that)
}
case DeltaGroup(thatOps) DeltaGroup(ops ++ thatOps) case DeltaGroup(thatOps) DeltaGroup(ops ++ thatOps)
case that: AtomicDeltaOp[A, B] DeltaGroup(ops :+ that)
} }
override def zero: DeltaReplicatedData = ops.headOption.fold(ORMap.empty[A, B].asInstanceOf[DeltaReplicatedData])(_.zero) override def zero: DeltaReplicatedData = ops.headOption.fold(ORMap.empty[A, B].asInstanceOf[DeltaReplicatedData])(_.zero)
@ -158,7 +154,7 @@ object ORMap {
final class ORMap[A, B <: ReplicatedData] private[akka] ( final class ORMap[A, B <: ReplicatedData] private[akka] (
private[akka] val keys: ORSet[A], private[akka] val keys: ORSet[A],
private[akka] val values: Map[A, B], private[akka] val values: Map[A, B],
private[akka] val zeroTag: ZeroTag = ORMap.VanillaORMapTag, private[akka] val zeroTag: ZeroTag,
override val delta: Option[ORMap.DeltaOp] = None) override val delta: Option[ORMap.DeltaOp] = None)
extends DeltaReplicatedData with ReplicatedDataSerialization with RemovedNodePruning { extends DeltaReplicatedData with ReplicatedDataSerialization with RemovedNodePruning {
@ -390,12 +386,13 @@ final class ORMap[A, B <: ReplicatedData] private[akka] (
case removeKeyOp: RemoveKeyDeltaOp[A, B] case removeKeyOp: RemoveKeyDeltaOp[A, B]
tombstonedVals = tombstonedVals + removeKeyOp.removedKey tombstonedVals = tombstonedVals + removeKeyOp.removedKey
case updateOp: UpdateDeltaOp[A, _] case updateOp: UpdateDeltaOp[A, _]
val key = updateOp.values.head._1 updateOp.values.foreach {
val value = (key, updateOp.values.head._2) case (key, value)
if (thatValueDeltas.contains(key)) if (thatValueDeltas.contains(key))
thatValueDeltas = thatValueDeltas + (key (thatValueDeltas(key) :+ value)) thatValueDeltas = thatValueDeltas + (key (thatValueDeltas(key) :+ (key, value)))
else else
thatValueDeltas += (key (value :: Nil)) thatValueDeltas += (key ((key, value) :: Nil))
}
} }
val processNestedDelta: PartialFunction[ORMap.DeltaOp, Unit] = { val processNestedDelta: PartialFunction[ORMap.DeltaOp, Unit] = {

View file

@ -8,9 +8,24 @@ import akka.annotation.InternalApi
import akka.cluster.ddata.ORMap._ import akka.cluster.ddata.ORMap._
object ORMultiMap { object ORMultiMap {
/**
* INTERNAL API
*/
@InternalApi private[akka] case object ORMultiMapTag extends ZeroTag {
override def zero: DeltaReplicatedData = ORMultiMap.empty
override final val value: Int = 2
}
val _empty: ORMultiMap[Any, Any] = new ORMultiMap(ORMap.emptyWithORMultiMapTag, false) /**
val _emptyWithValueDeltas: ORMultiMap[Any, Any] = new ORMultiMap(ORMap.emptyWithORMultiMapTag, true) * INTERNAL API
*/
@InternalApi private[akka] case object ORMultiMapWithValueDeltasTag extends ZeroTag {
override def zero: DeltaReplicatedData = ORMultiMap.emptyWithValueDeltas
override final val value: Int = 3
}
val _empty: ORMultiMap[Any, Any] = new ORMultiMap(new ORMap(ORSet.empty, Map.empty, zeroTag = ORMultiMapTag), false)
val _emptyWithValueDeltas: ORMultiMap[Any, Any] = new ORMultiMap(new ORMap(ORSet.empty, Map.empty, zeroTag = ORMultiMapWithValueDeltasTag), true)
/** /**
* Provides an empty multimap. * Provides an empty multimap.
*/ */

View file

@ -11,7 +11,15 @@ import akka.annotation.InternalApi
import akka.cluster.ddata.ORMap._ import akka.cluster.ddata.ORMap._
object PNCounterMap { object PNCounterMap {
def empty[A]: PNCounterMap[A] = new PNCounterMap(ORMap.emptyWithPNCounterMapTag) /**
* INTERNAL API
*/
@InternalApi private[akka] case object PNCounterMapTag extends ZeroTag {
override def zero: DeltaReplicatedData = PNCounterMap.empty
override final val value: Int = 1
}
def empty[A]: PNCounterMap[A] = new PNCounterMap(new ORMap(ORSet.empty, Map.empty, zeroTag = PNCounterMapTag))
def apply[A](): PNCounterMap[A] = empty def apply[A](): PNCounterMap[A] = empty
/** /**
* Java API * Java API

View file

@ -8,6 +8,7 @@ import java.util.ArrayList
import java.util.Collections import java.util.Collections
import java.util.Comparator import java.util.Comparator
import java.util.TreeSet import java.util.TreeSet
import scala.annotation.tailrec import scala.annotation.tailrec
import scala.collection.JavaConverters._ import scala.collection.JavaConverters._
import scala.collection.breakOut import scala.collection.breakOut
@ -24,6 +25,7 @@ import akka.util.ByteString.UTF_8
import scala.collection.immutable.TreeMap import scala.collection.immutable.TreeMap
import akka.cluster.UniqueAddress import akka.cluster.UniqueAddress
import java.io.NotSerializableException import java.io.NotSerializableException
import akka.cluster.ddata.protobuf.msg.ReplicatorMessages.OtherMessage import akka.cluster.ddata.protobuf.msg.ReplicatorMessages.OtherMessage
import akka.cluster.ddata.ORSet.DeltaOp import akka.cluster.ddata.ORSet.DeltaOp
@ -570,60 +572,60 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
val entries = mapTypeFromProto(ormap.getEntriesList, (v: dm.OtherMessage) otherMessageFromProto(v).asInstanceOf[ReplicatedData]) val entries = mapTypeFromProto(ormap.getEntriesList, (v: dm.OtherMessage) otherMessageFromProto(v).asInstanceOf[ReplicatedData])
new ORMap( new ORMap(
keys = orsetFromProto(ormap.getKeys), keys = orsetFromProto(ormap.getKeys),
entries) entries,
ORMap.VanillaORMapTag)
} }
def singleMapEntryFromProto[PEntry <: GeneratedMessage, A <: GeneratedMessage, B <: ReplicatedData](entry: PEntry, valueCreator: A B)(implicit eh: ProtoMapEntryReader[PEntry, A]): Map[Any, B] = { def singleMapEntryFromProto[PEntry <: GeneratedMessage, A <: GeneratedMessage, B <: ReplicatedData](input: util.List[PEntry], valueCreator: A B)(implicit eh: ProtoMapEntryReader[PEntry, A]): Map[Any, B] = {
val elem = if (eh.hasStringKey(entry)) Some(eh.getStringKey(entry) valueCreator(eh.getValue(entry))) val map = mapTypeFromProto(input, valueCreator)
else if (eh.hasIntKey(entry)) Some(eh.getIntKey(entry) valueCreator(eh.getValue(entry))) if (map.size > 1)
else if (eh.hasLongKey(entry)) Some(eh.getLongKey(entry) valueCreator(eh.getValue(entry))) throw new IllegalArgumentException(s"Can't deserialize the key/value pair in the ORMap delta - too many pairs on the wire")
else if (eh.hasOtherKey(entry)) Some(otherMessageFromProto(eh.getOtherKey(entry)) valueCreator(eh.getValue(entry))) else
else None map
elem match {
case Some(e) Map(e)
case _ Map.empty[Any, B]
}
} }
def singleKeyEntryFromProto[PEntry <: GeneratedMessage, A <: GeneratedMessage](entry: PEntry)(implicit eh: ProtoMapEntryReader[PEntry, A]): Any = def singleKeyEntryFromProto[PEntry <: GeneratedMessage, A <: GeneratedMessage](entryOption: Option[PEntry])(implicit eh: ProtoMapEntryReader[PEntry, A]): Any =
if (eh.hasStringKey(entry)) eh.getStringKey(entry) entryOption match {
case Some(entry) if (eh.hasStringKey(entry)) eh.getStringKey(entry)
else if (eh.hasIntKey(entry)) eh.getIntKey(entry) else if (eh.hasIntKey(entry)) eh.getIntKey(entry)
else if (eh.hasLongKey(entry)) eh.getLongKey(entry) else if (eh.hasLongKey(entry)) eh.getLongKey(entry)
else if (eh.hasOtherKey(entry)) otherMessageFromProto(eh.getOtherKey(entry)) else if (eh.hasOtherKey(entry)) otherMessageFromProto(eh.getOtherKey(entry))
else throw new IllegalArgumentException(s"Can't deserialize the key in the ORMap delta") else throw new IllegalArgumentException(s"Can't deserialize the key in the ORMap delta")
case _ throw new IllegalArgumentException(s"Can't deserialize the key in the ORMap delta")
}
// wire protocol is always DeltaGroup // wire protocol is always DeltaGroup
private def ormapPutFromBinary(bytes: Array[Byte]): ORMap.PutDeltaOp[Any, ReplicatedData] = { private def ormapPutFromBinary(bytes: Array[Byte]): ORMap.PutDeltaOp[Any, ReplicatedData] = {
val group = ormapDeltaGroupFromBinary(bytes) val ops = ormapDeltaGroupOpsFromBinary(bytes)
if (group.ops.size == 1 && group.ops.head.isInstanceOf[ORMap.PutDeltaOp[_, _]]) if (ops.size == 1 && ops.head.isInstanceOf[ORMap.PutDeltaOp[_, _]])
group.ops.head.asInstanceOf[ORMap.PutDeltaOp[Any, ReplicatedData]] ops.head.asInstanceOf[ORMap.PutDeltaOp[Any, ReplicatedData]]
else else
throw new NotSerializableException("Improper ORMap delta put operation size or kind") throw new NotSerializableException("Improper ORMap delta put operation size or kind")
} }
// wire protocol is always delta group // wire protocol is always delta group
private def ormapRemoveFromBinary(bytes: Array[Byte]): ORMap.RemoveDeltaOp[Any, ReplicatedData] = { private def ormapRemoveFromBinary(bytes: Array[Byte]): ORMap.RemoveDeltaOp[Any, ReplicatedData] = {
val group = ormapDeltaGroupFromBinary(bytes) val ops = ormapDeltaGroupOpsFromBinary(bytes)
if (group.ops.size == 1 && group.ops.head.isInstanceOf[ORMap.RemoveDeltaOp[_, _]]) if (ops.size == 1 && ops.head.isInstanceOf[ORMap.RemoveDeltaOp[_, _]])
group.ops.head.asInstanceOf[ORMap.RemoveDeltaOp[Any, ReplicatedData]] ops.head.asInstanceOf[ORMap.RemoveDeltaOp[Any, ReplicatedData]]
else else
throw new NotSerializableException("Improper ORMap delta remove operation size or kind") throw new NotSerializableException("Improper ORMap delta remove operation size or kind")
} }
// wire protocol is always delta group // wire protocol is always delta group
private def ormapRemoveKeyFromBinary(bytes: Array[Byte]): ORMap.RemoveKeyDeltaOp[Any, ReplicatedData] = { private def ormapRemoveKeyFromBinary(bytes: Array[Byte]): ORMap.RemoveKeyDeltaOp[Any, ReplicatedData] = {
val group = ormapDeltaGroupFromBinary(bytes) val ops = ormapDeltaGroupOpsFromBinary(bytes)
if (group.ops.size == 1 && group.ops.head.isInstanceOf[ORMap.RemoveKeyDeltaOp[_, _]]) if (ops.size == 1 && ops.head.isInstanceOf[ORMap.RemoveKeyDeltaOp[_, _]])
group.ops.head.asInstanceOf[ORMap.RemoveKeyDeltaOp[Any, ReplicatedData]] ops.head.asInstanceOf[ORMap.RemoveKeyDeltaOp[Any, ReplicatedData]]
else else
throw new NotSerializableException("Improper ORMap delta remove key operation size or kind") throw new NotSerializableException("Improper ORMap delta remove key operation size or kind")
} }
// wire protocol is always delta group // wire protocol is always delta group
private def ormapUpdateFromBinary(bytes: Array[Byte]): ORMap.UpdateDeltaOp[Any, ReplicatedDelta] = { private def ormapUpdateFromBinary(bytes: Array[Byte]): ORMap.UpdateDeltaOp[Any, ReplicatedDelta] = {
val group = ormapDeltaGroupFromBinary(bytes) val ops = ormapDeltaGroupOpsFromBinary(bytes)
if (group.ops.size == 1 && group.ops.head.isInstanceOf[ORMap.UpdateDeltaOp[_, _]]) if (ops.size == 1 && ops.head.isInstanceOf[ORMap.UpdateDeltaOp[_, _]])
group.ops.head.asInstanceOf[ORMap.UpdateDeltaOp[Any, ReplicatedDelta]] ops.head.asInstanceOf[ORMap.UpdateDeltaOp[Any, ReplicatedDelta]]
else else
throw new NotSerializableException("Improper ORMap delta update operation size or kind") throw new NotSerializableException("Improper ORMap delta update operation size or kind")
} }
@ -631,68 +633,73 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
// this can be made client-extendable in the same way as Http codes in Spray are // this can be made client-extendable in the same way as Http codes in Spray are
private def zeroTagFromCode(code: Int) = code match { private def zeroTagFromCode(code: Int) = code match {
case ORMap.VanillaORMapTag.value ORMap.VanillaORMapTag case ORMap.VanillaORMapTag.value ORMap.VanillaORMapTag
case ORMap.PNCounterMapTag.value ORMap.PNCounterMapTag case PNCounterMap.PNCounterMapTag.value PNCounterMap.PNCounterMapTag
case ORMap.ORMultiMapTag.value ORMap.ORMultiMapTag case ORMultiMap.ORMultiMapTag.value ORMultiMap.ORMultiMapTag
case ORMap.ORMultiMapWithValueDeltasTag.value ORMap.ORMultiMapWithValueDeltasTag case ORMultiMap.ORMultiMapWithValueDeltasTag.value ORMultiMap.ORMultiMapWithValueDeltasTag
case ORMap.LWWMapTag.value ORMap.LWWMapTag case LWWMap.LWWMapTag.value LWWMap.LWWMapTag
case _ throw new IllegalArgumentException("Invalid ZeroTag code") case _ throw new IllegalArgumentException("Invalid ZeroTag code")
} }
private def ormapDeltaGroupFromBinary(bytes: Array[Byte]): ORMap.DeltaGroup[Any, ReplicatedData] = { private def ormapDeltaGroupFromBinary(bytes: Array[Byte]): ORMap.DeltaGroup[Any, ReplicatedData] = {
ORMap.DeltaGroup(ormapDeltaGroupOpsFromBinary(bytes))
}
private def ormapDeltaGroupOpsFromBinary(bytes: Array[Byte]): scala.collection.immutable.IndexedSeq[ORMap.DeltaOp] = {
val deltaGroup = rd.ORMapDeltaGroup.parseFrom(bytes) val deltaGroup = rd.ORMapDeltaGroup.parseFrom(bytes)
val ops: Vector[ORMap.DeltaOp] = val ops: Vector[ORMap.DeltaOp] =
deltaGroup.getEntriesList.asScala.map { entry deltaGroup.getEntriesList.asScala.map { entry
if (entry.getOperation == rd.ORMapDeltaOp.ORMapPut) { if (entry.getOperation == rd.ORMapDeltaOp.ORMapPut) {
val map = singleMapEntryFromProto(entry.getEntryData, (v: dm.OtherMessage) otherMessageFromProto(v).asInstanceOf[ReplicatedData]) val map = singleMapEntryFromProto(entry.getEntryDataList, (v: dm.OtherMessage) otherMessageFromProto(v).asInstanceOf[ReplicatedData])
ORMap.PutDeltaOp(ORSet.AddDeltaOp(orsetFromProto(entry.getUnderlying)), map.head, zeroTagFromCode(entry.getZeroTag)) ORMap.PutDeltaOp(ORSet.AddDeltaOp(orsetFromProto(entry.getUnderlying)), map.head, zeroTagFromCode(entry.getZeroTag))
} else if (entry.getOperation == rd.ORMapDeltaOp.ORMapRemove) { } else if (entry.getOperation == rd.ORMapDeltaOp.ORMapRemove) {
ORMap.RemoveDeltaOp(ORSet.RemoveDeltaOp(orsetFromProto(entry.getUnderlying)), zeroTagFromCode(entry.getZeroTag)) ORMap.RemoveDeltaOp(ORSet.RemoveDeltaOp(orsetFromProto(entry.getUnderlying)), zeroTagFromCode(entry.getZeroTag))
} else if (entry.getOperation == rd.ORMapDeltaOp.ORMapRemoveKey) { } else if (entry.getOperation == rd.ORMapDeltaOp.ORMapRemoveKey) {
val elem = singleKeyEntryFromProto(entry.getEntryData) val elem = singleKeyEntryFromProto(entry.getEntryDataList.asScala.headOption)
ORMap.RemoveKeyDeltaOp(ORSet.RemoveDeltaOp(orsetFromProto(entry.getUnderlying)), elem, zeroTagFromCode(entry.getZeroTag)) ORMap.RemoveKeyDeltaOp(ORSet.RemoveDeltaOp(orsetFromProto(entry.getUnderlying)), elem, zeroTagFromCode(entry.getZeroTag))
} else if (entry.getOperation == rd.ORMapDeltaOp.ORMapUpdate) { } else if (entry.getOperation == rd.ORMapDeltaOp.ORMapUpdate) {
val map = singleMapEntryFromProto(entry.getEntryData, (v: dm.OtherMessage) otherMessageFromProto(v).asInstanceOf[ReplicatedDelta]) val map = mapTypeFromProto(entry.getEntryDataList, (v: dm.OtherMessage) otherMessageFromProto(v).asInstanceOf[ReplicatedDelta])
ORMap.UpdateDeltaOp(ORSet.AddDeltaOp(orsetFromProto(entry.getUnderlying)), map, zeroTagFromCode(entry.getZeroTag)) ORMap.UpdateDeltaOp(ORSet.AddDeltaOp(orsetFromProto(entry.getUnderlying)), map, zeroTagFromCode(entry.getZeroTag))
} else } else
throw new NotSerializableException(s"Unknown ORMap delta operation ${entry.getOperation}") throw new NotSerializableException(s"Unknown ORMap delta operation ${entry.getOperation}")
}(collection.breakOut) }(collection.breakOut)
ORMap.DeltaGroup(ops) ops
} }
private def ormapPutToProto(deltaOp: ORMap.PutDeltaOp[_, _]): rd.ORMapDeltaGroup = { private def ormapPutToProto(deltaOp: ORMap.PutDeltaOp[_, _]): rd.ORMapDeltaGroup = {
ormapDeltaGroupToProto(ORMap.DeltaGroup(scala.collection.immutable.IndexedSeq(deltaOp.asInstanceOf[ORMap.DeltaOp]))) ormapDeltaGroupOpsToProto(scala.collection.immutable.IndexedSeq(deltaOp.asInstanceOf[ORMap.DeltaOp]))
} }
private def ormapRemoveToProto(deltaOp: ORMap.RemoveDeltaOp[_, _]): rd.ORMapDeltaGroup = { private def ormapRemoveToProto(deltaOp: ORMap.RemoveDeltaOp[_, _]): rd.ORMapDeltaGroup = {
ormapDeltaGroupToProto(ORMap.DeltaGroup(scala.collection.immutable.IndexedSeq(deltaOp.asInstanceOf[ORMap.DeltaOp]))) ormapDeltaGroupOpsToProto(scala.collection.immutable.IndexedSeq(deltaOp.asInstanceOf[ORMap.DeltaOp]))
} }
private def ormapRemoveKeyToProto(deltaOp: ORMap.RemoveKeyDeltaOp[_, _]): rd.ORMapDeltaGroup = { private def ormapRemoveKeyToProto(deltaOp: ORMap.RemoveKeyDeltaOp[_, _]): rd.ORMapDeltaGroup = {
ormapDeltaGroupToProto(ORMap.DeltaGroup(scala.collection.immutable.IndexedSeq(deltaOp.asInstanceOf[ORMap.DeltaOp]))) ormapDeltaGroupOpsToProto(scala.collection.immutable.IndexedSeq(deltaOp.asInstanceOf[ORMap.DeltaOp]))
} }
private def ormapUpdateToProto(deltaOp: ORMap.UpdateDeltaOp[_, _]): rd.ORMapDeltaGroup = { private def ormapUpdateToProto(deltaOp: ORMap.UpdateDeltaOp[_, _]): rd.ORMapDeltaGroup = {
ormapDeltaGroupToProto(ORMap.DeltaGroup(scala.collection.immutable.IndexedSeq(deltaOp.asInstanceOf[ORMap.DeltaOp]))) ormapDeltaGroupOpsToProto(scala.collection.immutable.IndexedSeq(deltaOp.asInstanceOf[ORMap.DeltaOp]))
} }
private def ormapDeltaGroupToProto(deltaGroup: ORMap.DeltaGroup[_, _]): rd.ORMapDeltaGroup = { private def ormapDeltaGroupToProto(deltaGroup: ORMap.DeltaGroup[_, _]): rd.ORMapDeltaGroup = {
ormapDeltaGroupOpsToProto(deltaGroup.ops)
}
private def ormapDeltaGroupOpsToProto(deltaGroupOps: scala.collection.immutable.IndexedSeq[ORMap.DeltaOp]): rd.ORMapDeltaGroup = {
def createEntry(opType: rd.ORMapDeltaOp, u: ORSet[_], m: Map[_, _], zt: Int) = { def createEntry(opType: rd.ORMapDeltaOp, u: ORSet[_], m: Map[_, _], zt: Int) = {
if (m.size > 1) if (m.size > 1 && opType != rd.ORMapDeltaOp.ORMapUpdate)
throw new IllegalArgumentException("Invalid size of ORMap delta map") throw new IllegalArgumentException("Invalid size of ORMap delta map")
else { else {
val entryDataBuilder = rd.ORMapDeltaGroup.MapEntry.newBuilder()
m.headOption.map {
case (key: String, value) entryDataBuilder.setStringKey(key).setValue(otherMessageToProto(value))
case (key: Int, value) entryDataBuilder.setIntKey(key).setValue(otherMessageToProto(value))
case (key: Long, value) entryDataBuilder.setLongKey(key).setValue(otherMessageToProto(value))
case (key, value) entryDataBuilder.setOtherKey(otherMessageToProto(key)).setValue(otherMessageToProto(value))
}
val builder = rd.ORMapDeltaGroup.Entry.newBuilder() val builder = rd.ORMapDeltaGroup.Entry.newBuilder()
.setOperation(opType) .setOperation(opType)
.setUnderlying(orsetToProto(u)) .setUnderlying(orsetToProto(u))
.setZeroTag(zt) .setZeroTag(zt)
if (m.size > 0) m.foreach {
builder.setEntryData(entryDataBuilder.build()) case (key: String, value) builder.addEntryData(rd.ORMapDeltaGroup.MapEntry.newBuilder().setStringKey(key).setValue(otherMessageToProto(value)).build())
case (key: Int, value) builder.addEntryData(rd.ORMapDeltaGroup.MapEntry.newBuilder().setIntKey(key).setValue(otherMessageToProto(value)).build())
case (key: Long, value) builder.addEntryData(rd.ORMapDeltaGroup.MapEntry.newBuilder().setLongKey(key).setValue(otherMessageToProto(value)).build())
case (key, value) builder.addEntryData(rd.ORMapDeltaGroup.MapEntry.newBuilder().setOtherKey(otherMessageToProto(key)).setValue(otherMessageToProto(value)).build())
}
builder builder
} }
} }
@ -709,12 +716,12 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
.setOperation(opType) .setOperation(opType)
.setUnderlying(orsetToProto(u)) .setUnderlying(orsetToProto(u))
.setZeroTag(zt) .setZeroTag(zt)
builder.setEntryData(entryDataBuilder.build()) builder.addEntryData(entryDataBuilder.build())
builder builder
} }
val b = rd.ORMapDeltaGroup.newBuilder() val b = rd.ORMapDeltaGroup.newBuilder()
deltaGroup.ops.foreach { deltaGroupOps.foreach {
case ORMap.PutDeltaOp(op, pair, zt) case ORMap.PutDeltaOp(op, pair, zt)
b.addEntries(createEntry(rd.ORMapDeltaOp.ORMapPut, op.asInstanceOf[ORSet.AddDeltaOp[_]].underlying, Map(pair), zt.value)) b.addEntries(createEntry(rd.ORMapDeltaOp.ORMapPut, op.asInstanceOf[ORSet.AddDeltaOp[_]].underlying, Map(pair), zt.value))
case ORMap.RemoveDeltaOp(op, zt) case ORMap.RemoveDeltaOp(op, zt)
@ -742,7 +749,7 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
val entries = mapTypeFromProto(lwwmap.getEntriesList, lwwRegisterFromProto) val entries = mapTypeFromProto(lwwmap.getEntriesList, lwwRegisterFromProto)
new LWWMap(new ORMap( new LWWMap(new ORMap(
keys = orsetFromProto(lwwmap.getKeys), keys = orsetFromProto(lwwmap.getKeys),
entries, ORMap.LWWMapTag)) entries, LWWMap.LWWMapTag))
} }
def pncountermapToProto(pncountermap: PNCounterMap[_]): rd.PNCounterMap = { def pncountermapToProto(pncountermap: PNCounterMap[_]): rd.PNCounterMap = {
@ -758,7 +765,7 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
val entries = mapTypeFromProto(pncountermap.getEntriesList, pncounterFromProto) val entries = mapTypeFromProto(pncountermap.getEntriesList, pncounterFromProto)
new PNCounterMap(new ORMap( new PNCounterMap(new ORMap(
keys = orsetFromProto(pncountermap.getKeys), keys = orsetFromProto(pncountermap.getKeys),
entries, ORMap.PNCounterMapTag)) entries, PNCounterMap.PNCounterMapTag))
} }
def multimapToProto(multimap: ORMultiMap[_, _]): rd.ORMultiMap = { def multimapToProto(multimap: ORMultiMap[_, _]): rd.ORMultiMap = {
@ -783,9 +790,9 @@ class ReplicatedDataSerializer(val system: ExtendedActorSystem)
keys = orsetFromProto(multimap.getKeys), keys = orsetFromProto(multimap.getKeys),
entries, entries,
if (withValueDeltas) if (withValueDeltas)
ORMap.ORMultiMapWithValueDeltasTag ORMultiMap.ORMultiMapWithValueDeltasTag
else else
ORMap.ORMultiMapTag), ORMultiMap.ORMultiMapTag),
withValueDeltas) withValueDeltas)
} }

View file

@ -439,6 +439,77 @@ class ORMapSpec extends WordSpec with Matchers {
merged6.entries("c").elements should be(Set("C")) merged6.entries("c").elements should be(Set("C"))
} }
"work with delta-coalescing scenario 1" in {
val m1 = ORMap.empty.put(node1, "a", GSet.empty + "A").put(node2, "b", GSet.empty + "B")
val m2 = m1.resetDelta.put(node2, "b", GSet.empty + "B2").updated(node2, "b", GSet.empty[String])(_.add("B3"))
val merged1 = m1 merge m2
merged1.entries("a").elements should be(Set("A"))
merged1.entries("b").elements should be(Set("B", "B2", "B3"))
val merged2 = m1 mergeDelta m2.delta.get
merged2.entries("a").elements should be(Set("A"))
merged2.entries("b").elements should be(Set("B", "B2", "B3"))
val m3 = ORMap.empty.put(node1, "a", GSet.empty + "A").put(node2, "b", GSet.empty + "B")
val m4 = m3.resetDelta.put(node2, "b", GSet.empty + "B2").put(node2, "b", GSet.empty + "B3")
val merged3 = m3 merge m4
merged3.entries("a").elements should be(Set("A"))
merged3.entries("b").elements should be(Set("B", "B3"))
val merged4 = m3 mergeDelta m4.delta.get
merged4.entries("a").elements should be(Set("A"))
merged4.entries("b").elements should be(Set("B", "B3"))
val m5 = ORMap.empty.put(node1, "a", GSet.empty + "A").put(node2, "b", GSet.empty + "B")
val m6 = m5.resetDelta.put(node2, "b", GSet.empty + "B2").updated(node2, "b", GSet.empty[String])(_.add("B3"))
.updated(node2, "b", GSet.empty[String])(_.add("B4"))
val merged5 = m5 merge m6
merged5.entries("a").elements should be(Set("A"))
merged5.entries("b").elements should be(Set("B", "B2", "B3", "B4"))
val merged6 = m5 mergeDelta m6.delta.get
merged6.entries("a").elements should be(Set("A"))
merged6.entries("b").elements should be(Set("B", "B2", "B3", "B4"))
val m7 = ORMap.empty.put(node1, "a", GSet.empty + "A").put(node2, "b", GSet.empty + "B")
val m8 = m7.resetDelta.put(node2, "b", GSet.empty + "B2").put(node2, "d", GSet.empty + "D").put(node2, "b", GSet.empty + "B3")
val merged7 = m7 merge m8
merged7.entries("a").elements should be(Set("A"))
merged7.entries("b").elements should be(Set("B", "B3"))
merged7.entries("d").elements should be(Set("D"))
val merged8 = m7 mergeDelta m8.delta.get
merged8.entries("a").elements should be(Set("A"))
merged8.entries("b").elements should be(Set("B", "B3"))
merged8.entries("d").elements should be(Set("D"))
val m9 = ORMap.empty.put(node1, "a", GSet.empty + "A").put(node2, "b", GSet.empty + "B")
val m10 = m9.resetDelta.put(node2, "b", GSet.empty + "B2").put(node2, "d", GSet.empty + "D")
.remove(node2, "d").put(node2, "b", GSet.empty + "B3")
val merged9 = m9 merge m10
merged9.entries("a").elements should be(Set("A"))
merged9.entries("b").elements should be(Set("B", "B3"))
val merged10 = m9 mergeDelta m10.delta.get
merged10.entries("a").elements should be(Set("A"))
merged10.entries("b").elements should be(Set("B", "B3"))
}
"work with deltas and updated for GSet elements type" in { "work with deltas and updated for GSet elements type" in {
val m1 = ORMap.empty.put(node1, "a", GSet.empty + "A") val m1 = ORMap.empty.put(node1, "a", GSet.empty + "A")
val m2 = m1.resetDelta.updated(node1, "a", GSet.empty[String])(_.add("B")) val m2 = m1.resetDelta.updated(node1, "a", GSet.empty[String])(_.add("B"))

View file

@ -133,6 +133,12 @@ class ORMultiMapSpec extends WordSpec with Matchers {
merged3.entries("a") should be(Set("A")) merged3.entries("a") should be(Set("A"))
merged3.entries("b") should be(Set("B2")) merged3.entries("b") should be(Set("B2"))
merged3.entries("c") should be(Set("C")) merged3.entries("c") should be(Set("C"))
val merged4 = merged1 mergeDelta m3.delta.get.merge(m4.delta.get)
merged4.entries("a") should be(Set("A"))
merged4.entries("b") should be(Set("B2"))
merged4.entries("c") should be(Set("C"))
} }
"not have usual anomalies for remove+addBinding scenario and delta-deltas 2" in { "not have usual anomalies for remove+addBinding scenario and delta-deltas 2" in {
@ -181,6 +187,217 @@ class ORMultiMapSpec extends WordSpec with Matchers {
merged6.entries("c") should be(Set("C")) merged6.entries("c") should be(Set("C"))
} }
"work with delta-coalescing scenario 1" in {
val m1 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m2 = m1.resetDelta.put(node2, "b", Set("B2")).addBinding(node2, "b", "B3")
val merged1 = m1 merge m2
merged1.entries("a") should be(Set("A"))
merged1.entries("b") should be(Set("B2", "B3"))
val merged2 = m1 mergeDelta m2.delta.get
merged2.entries("a") should be(Set("A"))
merged2.entries("b") should be(Set("B2", "B3"))
val m3 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m4 = m3.resetDelta.put(node2, "b", Set("B2")).put(node2, "b", Set("B3"))
val merged3 = m3 merge m4
merged3.entries("a") should be(Set("A"))
merged3.entries("b") should be(Set("B3"))
val merged4 = m3 mergeDelta m4.delta.get
merged4.entries("a") should be(Set("A"))
merged4.entries("b") should be(Set("B3"))
val m5 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m6 = m5.resetDelta.put(node2, "b", Set("B2")).addBinding(node2, "b", "B3").addBinding(node2, "b", "B4")
val merged5 = m5 merge m6
merged5.entries("a") should be(Set("A"))
merged5.entries("b") should be(Set("B2", "B3", "B4"))
val merged6 = m5 mergeDelta m6.delta.get
merged6.entries("a") should be(Set("A"))
merged6.entries("b") should be(Set("B2", "B3", "B4"))
val m7 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m8 = m7.resetDelta.put(node2, "d", Set("D")).addBinding(node2, "b", "B3").put(node2, "b", Set("B4"))
val merged7 = m7 merge m8
merged7.entries("a") should be(Set("A"))
merged7.entries("b") should be(Set("B4"))
merged7.entries("d") should be(Set("D"))
val merged8 = m7 mergeDelta m8.delta.get
merged8.entries("a") should be(Set("A"))
merged8.entries("b") should be(Set("B4"))
merged8.entries("d") should be(Set("D"))
val m9 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m10 = m9.resetDelta.addBinding(node2, "b", "B3").addBinding(node2, "b", "B4")
val merged9 = m9 merge m10
merged9.entries("a") should be(Set("A"))
merged9.entries("b") should be(Set("B", "B3", "B4"))
val merged10 = m9 mergeDelta m10.delta.get
merged10.entries("a") should be(Set("A"))
merged10.entries("b") should be(Set("B", "B3", "B4"))
val m11 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B", "B1"))
.remove(node1, "b")
val m12 = m11.resetDelta.addBinding(node2, "b", "B2").addBinding(node2, "b", "B3")
val merged11 = m11 merge m12
merged11.entries("a") should be(Set("A"))
merged11.entries("b") should be(Set("B2", "B3"))
val merged12 = m11 mergeDelta m12.delta.get
merged12.entries("a") should be(Set("A"))
merged12.entries("b") should be(Set("B2", "B3"))
val m13 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B", "B1"))
.remove(node1, "b")
val m14 = m13.resetDelta.addBinding(node2, "b", "B2").put(node2, "b", Set("B3"))
val merged13 = m13 merge m14
merged13.entries("a") should be(Set("A"))
merged13.entries("b") should be(Set("B3"))
val merged14 = m13 mergeDelta m14.delta.get
merged14.entries("a") should be(Set("A"))
merged14.entries("b") should be(Set("B3"))
val m15 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B", "B1"))
.put(node1, "c", Set("C"))
val m16 = m15.resetDelta.addBinding(node2, "b", "B2").addBinding(node2, "c", "C1")
val merged15 = m15 merge m16
merged15.entries("a") should be(Set("A"))
merged15.entries("b") should be(Set("B", "B1", "B2"))
merged15.entries("c") should be(Set("C", "C1"))
val merged16 = m15 mergeDelta m16.delta.get
merged16.entries("a") should be(Set("A"))
merged16.entries("b") should be(Set("B", "B1", "B2"))
merged16.entries("c") should be(Set("C", "C1"))
// somewhat artificial setup
val m17 = ORMultiMap.emptyWithValueDeltas[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B", "B1"))
val m18 = m17.resetDelta.addBinding(node2, "b", "B2")
val m19 = ORMultiMap.emptyWithValueDeltas[String, String].resetDelta.put(node2, "b", Set("B3"))
val merged17 = m17 merge m18 merge m19
merged17.entries("a") should be(Set("A"))
merged17.entries("b") should be(Set("B", "B1", "B3"))
val merged18 = m17 mergeDelta m18.delta.get.merge(m19.delta.get)
merged18.entries("a") should be(Set("A"))
merged18.entries("b") should be(Set("B", "B1", "B3"))
}
"work with delta-coalescing scenario 2" in {
val m1 = ORMultiMap.empty[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m2 = m1.resetDelta.put(node2, "b", Set("B2")).addBinding(node2, "b", "B3")
val merged1 = m1 merge m2
merged1.entries("a") should be(Set("A"))
merged1.entries("b") should be(Set("B2", "B3"))
val merged2 = m1 mergeDelta m2.delta.get
merged2.entries("a") should be(Set("A"))
merged2.entries("b") should be(Set("B2", "B3"))
val m3 = ORMultiMap.empty[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m4 = m3.resetDelta.put(node2, "b", Set("B2")).put(node2, "b", Set("B3"))
val merged3 = m3 merge m4
merged3.entries("a") should be(Set("A"))
merged3.entries("b") should be(Set("B3"))
val merged4 = m3 mergeDelta m4.delta.get
merged4.entries("a") should be(Set("A"))
merged4.entries("b") should be(Set("B3"))
val m5 = ORMultiMap.empty[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m6 = m5.resetDelta.put(node2, "b", Set("B2")).addBinding(node2, "b", "B3").addBinding(node2, "b", "B4")
val merged5 = m5 merge m6
merged5.entries("a") should be(Set("A"))
merged5.entries("b") should be(Set("B2", "B3", "B4"))
val merged6 = m5 mergeDelta m6.delta.get
merged6.entries("a") should be(Set("A"))
merged6.entries("b") should be(Set("B2", "B3", "B4"))
val m7 = ORMultiMap.empty[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m8 = m7.resetDelta.put(node2, "d", Set("D")).addBinding(node2, "b", "B3").put(node2, "b", Set("B4"))
val merged7 = m7 merge m8
merged7.entries("a") should be(Set("A"))
merged7.entries("b") should be(Set("B4"))
merged7.entries("d") should be(Set("D"))
val merged8 = m7 mergeDelta m8.delta.get
merged8.entries("a") should be(Set("A"))
merged8.entries("b") should be(Set("B4"))
merged8.entries("d") should be(Set("D"))
val m9 = ORMultiMap.empty[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B"))
val m10 = m9.resetDelta.addBinding(node2, "b", "B3").addBinding(node2, "b", "B4")
val merged9 = m9 merge m10
merged9.entries("a") should be(Set("A"))
merged9.entries("b") should be(Set("B", "B3", "B4"))
val merged10 = m9 mergeDelta m10.delta.get
merged10.entries("a") should be(Set("A"))
merged10.entries("b") should be(Set("B", "B3", "B4"))
val m11 = ORMultiMap.empty[String, String].put(node1, "a", Set("A")).put(node1, "b", Set("B", "B1"))
.remove(node1, "b")
val m12 = ORMultiMap.empty[String, String].addBinding(node2, "b", "B2").addBinding(node2, "b", "B3")
val merged11 = m11 merge m12
merged11.entries("a") should be(Set("A"))
merged11.entries("b") should be(Set("B2", "B3"))
val merged12 = m11 mergeDelta m12.delta.get
merged12.entries("a") should be(Set("A"))
merged12.entries("b") should be(Set("B2", "B3"))
}
"have unapply extractor" in { "have unapply extractor" in {
val m1 = ORMultiMap.empty.put(node1, "a", Set(1L, 2L)).put(node2, "b", Set(3L)) val m1 = ORMultiMap.empty.put(node1, "a", Set(1L, 2L)).put(node2, "b", Set(3L))
val m2: ORMultiMap[String, Long] = m1 val m2: ORMultiMap[String, Long] = m1

View file

@ -263,6 +263,10 @@ class ReplicatedDataSerializerSpec extends TestKit(ActorSystem(
val m1 = ORMultiMap.empty[String, String].addBinding(address1, "a", "A1").addBinding(address2, "a", "A2") val m1 = ORMultiMap.empty[String, String].addBinding(address1, "a", "A1").addBinding(address2, "a", "A2")
val m2 = ORMultiMap.empty[String, String].put(address2, "b", Set("B1", "B2", "B3")) val m2 = ORMultiMap.empty[String, String].put(address2, "b", Set("B1", "B2", "B3"))
checkSameContent(m1.merge(m2), m2.merge(m1)) checkSameContent(m1.merge(m2), m2.merge(m1))
checkSerialization(ORMultiMap.empty[String, String].addBinding(address1, "a", "A1").addBinding(address1, "a", "A2").delta.get)
val m3 = ORMultiMap.empty[String, String].addBinding(address1, "a", "A1")
val d3 = m3.resetDelta.addBinding(address1, "a", "A2").addBinding(address1, "a", "A3").delta.get
checkSerialization(d3)
} }
"be compatible with old ORMultiMap serialization" in { "be compatible with old ORMultiMap serialization" in {