package dovetaildb.apiservice;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import dovetaildb.bytes.ArrayBytes;
import dovetaildb.bytes.Bytes;
import dovetaildb.coordinator.Coordinator;
import dovetaildb.dbservice.AbstractIter;
import dovetaildb.dbservice.BufferedData;
import dovetaildb.dbservice.CommitFailedException;
import dovetaildb.dbservice.DbService;
import dovetaildb.dbservice.DbServiceUtil;
import dovetaildb.iter.Iter;
import dovetaildb.iter.IterUtil;
import dovetaildb.iter.MergeIter;
import dovetaildb.util.Util;
public class ChangesetBuffer implements ApiService {
/**
* Remembers edits within a transaction.
* Bridges an ApiService to a DbService.
*/
protected DbService db;
protected Coordinator coordinator;
protected Map<String,ApiBuffer> buffer;
protected long readTxnId;
public ChangesetBuffer(DbService db, Coordinator coordinator){
this.db = db;
this.coordinator = coordinator;
this.readTxnId = coordinator.getHighestCompletedTxnId();
this.buffer = new HashMap<String,ApiBuffer>();
}
public void commit() throws CommitFailedException {
long txnId = coordinator.reserveTxnId();
db.commit(readTxnId, txnId, buffer);
rollback();
}
public void rollback() {
this.buffer = new HashMap<String,ApiBuffer>();
this.readTxnId = coordinator.getHighestCompletedTxnId();
}
private ApiBuffer getDataForBag(String bag) {
ApiBuffer data = buffer.get(bag);
if (data == null) {
data = db.createBufferedData(bag);
buffer.put(bag, data);
}
return data;
}
public void insert(String bag, Map entry) {
ApiBuffer data = getDataForBag(bag);
String id = (String)entry.get("id");
if (id == null) {
throw new RuntimeException("No ID member in this entry: "+entry);
}
data.getEntries().put(id, entry);
}
public Iter query(String bag, Object query, Map<String,Object> options) {
ApiBuffer data = getDataForBag(bag);
Iter i1 = data.query(query, options);
List idList = new ArrayList();
idList.add("|");
idList.addAll(data.getDeletions());
idList.addAll(data.getEntries().keySet());
List notClause = Util.literalList().a("!").a(Util.literalMap().put("id", idList));
query = Util.literalList().a("&").a(query).a(notClause);
Iter i2 = this.db.query(bag, this.readTxnId, query, options);
return new MergeIter(i1, i2);
}
public void remove(String bag, String id) {
ApiBuffer data = getDataForBag(bag);
data.getDeletions().add(id);
}
public void update(String bag, String id, Map entry) {
if (entry.containsKey("id")) {
if (entry.get("id") != id) throw new RuntimeException("object's ID field (\""+entry.get("id")+"\") does not match the given ID(\""+id+"\")");
} else {
entry.put("id", id);
}
ApiBuffer data = getDataForBag(bag);
data.put(id, entry);
}
}