org.infinispan.commands.functional.TxReadOnlyManyCommand Maven / Gradle / Ivy
package org.infinispan.commands.functional;
import static org.infinispan.functional.impl.EntryViews.snapshot;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.infinispan.functional.EntryView;
import org.infinispan.container.entries.MVCCEntry;
import org.infinispan.context.InvocationContext;
import org.infinispan.functional.impl.EntryViews;
import org.infinispan.functional.impl.Params;
public class TxReadOnlyManyCommand extends ReadOnlyManyCommand {
public static final byte COMMAND_ID = 65;
// These mutations must have the same order of iteration as keys. We can guarantee that because the mutations
// are set only when replicating the command to other nodes where we have already narrowed the key set
private List>> mutations;
public TxReadOnlyManyCommand() {
}
public TxReadOnlyManyCommand(Collection extends K> keys, List>> mutations) {
super(keys, null, Params.create());
this.mutations = mutations;
}
public TxReadOnlyManyCommand(ReadOnlyManyCommand c, List>> mutations) {
super(c);
this.mutations = mutations;
}
@Override
public byte getCommandId() {
return COMMAND_ID;
}
@Override
public void writeTo(ObjectOutput output) throws IOException {
super.writeTo(output);
// TODO: if the marshaller does not support object counting we could marshall the same functions many times
// This encoding is optimized for mostly-empty inner lists but is as efficient as regular collection
// encoding from MarshallUtil if all the inner lists are non-empty
int emptyLists = 0;
for (List> list : mutations) {
if (list.isEmpty()) {
emptyLists++;
} else {
if (emptyLists > 0) output.writeInt(-emptyLists);
output.writeInt(list.size());
for (Mutation mut : list) {
Mutations.writeTo(output, mut);
}
emptyLists = 0;
}
}
if (emptyLists > 0) output.writeInt(-emptyLists);
}
@Override
public void readFrom(ObjectInput input) throws IOException, ClassNotFoundException {
super.readFrom(input);
int numMutations = keys.size();
mutations = new ArrayList<>(numMutations);
for (int i = 0; i < numMutations; ++i) {
int length = input.readInt();
if (length < 0) {
i -= length;
while (length < 0) {
mutations.add(Collections.emptyList());
++length;
}
if (i >= numMutations) {
break;
}
length = input.readInt();
}
List> list = new ArrayList<>(length);
for (int j = 0; j < length; ++j) {
list.add(Mutations.readFrom(input));
}
mutations.add(list);
}
}
@Override
public Object perform(InvocationContext ctx) throws Throwable {
if (mutations == null) {
return super.perform(ctx);
}
ArrayList retvals = new ArrayList<>(keys.size());
Iterator>> mutIt = mutations.iterator();
for (K k : keys) {
List> mutations = mutIt.next();
MVCCEntry entry = (MVCCEntry) lookupCacheEntry(ctx, k);
EntryView.ReadEntryView ro;
Object ret = null;
if (mutations.isEmpty()) {
ro = entry.isNull() ? EntryViews.noValue(k) : EntryViews.readOnly(entry);
} else {
EntryView.ReadWriteEntryView rw = EntryViews.readWrite(entry);
for (Mutation mutation : mutations) {
ret = mutation.apply(rw);
entry.updatePreviousValue();
}
ro = rw;
}
if (f != null) {
ret = f.apply(ro);
}
retvals.add(snapshot((R) ret));
}
return retvals.stream();
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("TxReadOnlyManyCommand{");
sb.append("keys=").append(keys);
sb.append(", f=").append(f);
sb.append(", mutations=").append(mutations);
sb.append('}');
return sb.toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy