/* * Galaxy * Copyright (c) 2012-2014, Parallel Universe Software Co. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 3.0 * as published by the Free Software Foundation. */ package co.paralleluniverse.galaxy.core; import co.paralleluniverse.common.collection.LongCompoundCollection; import co.paralleluniverse.common.collection.LongObjectProcedure; import co.paralleluniverse.galaxy.StoreTransaction; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.LongCollection; import it.unimi.dsi.fastutil.longs.LongIterator; import it.unimi.dsi.fastutil.longs.LongLists; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongSet; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; /** * * @author pron */ public class Transaction extends StoreTransaction { private LongCollection lines; private LongSet ls; private List<Op> ops; private final Long2ObjectOpenHashMap<RollbackInfo> rollbackLog; Transaction(boolean rollback) { rollbackLog = rollback ? new Long2ObjectOpenHashMap<RollbackInfo>() : null; } synchronized void add(long id) { if (ls == null) ls = new LongOpenHashSet(); ls.add(id); if (lines == null) lines = ls; else if (lines != ls) ((LongCompoundCollection) lines).addCollection(ls); } synchronized void add(LongCollection c) { if (lines == null) lines = new LongCompoundCollection(); else if (lines == ls) { lines = new LongCompoundCollection(); ((LongCompoundCollection) lines).addCollection(ls); } ((LongCompoundCollection) lines).addCollection(c); } synchronized void add(Op op) { if (ops == null) ops = new ArrayList<Op>(); ops.add(op); } synchronized boolean isRecorded(long id) { return rollbackLog.containsKey(id); } synchronized void recordRollback(long id, long version, boolean modified, byte[] data) { assert rollbackLog.get(id) == null; rollbackLog.put(id, new RollbackInfo(version, modified, data)); } synchronized LongCollection getLines() { return lines != null ? lines : LongLists.EMPTY_LIST; } synchronized List<Op> getOps() { return ops == null ? Collections.<Op>emptyList() : ops; } synchronized void forEachRollback(LongObjectProcedure<RollbackInfo> proc) { for (Long2ObjectMap.Entry<RollbackInfo> entry : rollbackLog.long2ObjectEntrySet()) proc.execute(entry.getLongKey(), entry.getValue()); } @Override public synchronized Iterator<Long> iterator() { if (lines == null) return Collections.emptyIterator(); final LongIterator it = lines.iterator(); return new Iterator<Long>() { @Override public boolean hasNext() { return it.hasNext(); } @Override public Long next() { return it.next(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } @Override public synchronized boolean contains(long id) { if (lines == null) return false; return lines.contains(id); } public static class RollbackInfo { public final long version; public final boolean modified; public final byte[] data; public RollbackInfo(long version, boolean modified, byte[] data) { this.version = version; this.modified = modified; this.data = data; } } }