Permalink
Browse files

Record freed pages into the transaction object

  • Loading branch information...
justinsb committed Dec 10, 2013
1 parent 81a2ba6 commit 1c9e6d2c26653760491652a22e9060c142311769
@@ -147,13 +147,13 @@ public int writePage(Page page) {
public void commitTransaction(TransactionPage transactionPage) {
// Shouldn't need to be synchronized, but harmless...
synchronized (this) {
transactionPage.setPreviousTransactionPage(currentTransactionPage);
transactionPage.setPreviousTransactionPageId(currentTransactionPage);
long transactionId = transactionPage.getTransactionId();
int transactionPageId = writePage(transactionPage);
int newRootPage = transactionPage.getRootPage();
int newRootPage = transactionPage.getRootPageId();
int slot = transactionPageId % MASTERPAGE_SLOTS;
@@ -2,54 +2,130 @@
import java.io.PrintStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.cloudata.keyvalue.KeyValueProto.KvAction;
import com.google.common.collect.Lists;
public class TransactionPage extends Page {
public static final byte PAGE_TYPE = 'T';
public static final int SIZE = 20;
private static final int OFFSET_FORMAT_VERSION = 0;
private static final int OFFSET_TRANSACTION_ID = 16;
private static final int OFFSET_ROOT_PAGE_ID = 24;
private static final int OFFSET_PREVIOUS_TRANSACTION_PAGE_ID = 28;
private static final int OFFSET_FREELIST_SIZE = 32;
private static final int HEADER_SIZE = 36;
private static final short VERSION_1 = 1;
static class Mutable {
long transactionId;
List<Integer> freelist = Lists.newArrayList();
int rootPageId;
int previousTransactionPageId;
public Mutable(TransactionPage transactionPage) {
this.transactionId = transactionPage.getTransactionId();
this.rootPageId = transactionPage.getRootPageId();
this.previousTransactionPageId = transactionPage.getPreviousTransactionPageId();
int freelistSize = transactionPage.getFreelistSize();
this.freelist = new ArrayList<Integer>(freelistSize);
}
public void write(ByteBuffer dest) {
dest.putShort(VERSION_1);
// Padding
dest.putShort((short) 0);
dest.putInt(0);
dest.putLong(0);
dest.putLong(this.transactionId);
dest.putInt(this.rootPageId);
dest.putInt(this.previousTransactionPageId);
dest.putInt(freelist.size());
Collections.sort(freelist);
for (int i = 0; i < freelist.size(); i++) {
dest.putInt(freelist.get(i));
}
}
public boolean isDirty() {
return true;
}
public void setPreviousTransactionPageId(int previousTransactionPageId) {
this.previousTransactionPageId = previousTransactionPageId;
}
public int getSerializedSize() {
return HEADER_SIZE + (freelist.size() * 4);
}
public void setRootPageId(int rootPageId) {
this.rootPageId = rootPageId;
}
public long getTransactionId() {
return transactionId;
}
public int getRootPageId() {
return rootPageId;
}
long transactionId;
int freelistPage;
int rootPage;
int previousTransactionPage;
public void addToFreelist(List<Integer> c) {
freelist.addAll(c);
}
boolean dirty;
}
Mutable mutable;
TransactionPage(Page parent, int pageNumber, ByteBuffer buffer) {
super(parent, pageNumber, buffer);
if (parent != null) {
throw new IllegalArgumentException();
}
}
this.transactionId = buffer.getLong(0);
this.rootPage = buffer.getInt(8);
this.freelistPage = buffer.getInt(12);
this.previousTransactionPage = buffer.getInt(16);
this.dirty = false;
int getFreelistSize() {
assert mutable == null;
return buffer.getInt(OFFSET_FREELIST_SIZE);
}
int getPreviousTransactionPageId() {
assert mutable == null;
return buffer.getInt(OFFSET_PREVIOUS_TRANSACTION_PAGE_ID);
}
@Override
public void write(ByteBuffer dest) {
dest.putLong(this.transactionId);
dest.putInt(this.rootPage);
dest.putInt(this.freelistPage);
dest.putInt(this.previousTransactionPage);
assert mutable != null;
mutable.write(dest);
}
public static TransactionPage createNew(int pageNumber, long transactionId) {
ByteBuffer data = ByteBuffer.allocate(SIZE);
data.putLong(transactionId);
data.putInt(0);
data.putInt(0);
data.putInt(0);
ByteBuffer empty = ByteBuffer.allocate(HEADER_SIZE);
empty.putShort(VERSION_1);
data.flip();
// Padding
empty.putShort((short) 0);
empty.putInt(0);
empty.putLong(0);
return new TransactionPage(null, pageNumber, data);
empty.putLong(transactionId);
empty.putInt(0);
empty.putInt(0);
empty.putInt(0);
empty.flip();
return new TransactionPage(null, pageNumber, empty);
}
@Override
@@ -69,12 +145,17 @@ public ByteBuffer getKeyLbound() {
@Override
public boolean isDirty() {
return dirty;
if (mutable == null) {
return false;
}
return mutable.isDirty();
}
@Override
public int getSerializedSize() {
return SIZE;
assert mutable != null;
return mutable.getSerializedSize();
}
@Override
@@ -87,22 +168,33 @@ public void dump(PrintStream os) {
throw new UnsupportedOperationException();
}
public void setRootPageId(int newRootPage) {
this.rootPage = newRootPage;
this.dirty = true;
public void setRootPageId(int newRootPageId) {
getMutable().setRootPageId(newRootPageId);
}
private Mutable getMutable() {
if (mutable == null) {
mutable = new Mutable(this);
}
return mutable;
}
public int getRootPage() {
return rootPage;
public int getRootPageId() {
if (mutable != null) {
return mutable.getRootPageId();
}
return buffer.getInt(OFFSET_ROOT_PAGE_ID);
}
public long getTransactionId() {
return transactionId;
if (mutable != null) {
return mutable.getTransactionId();
}
return buffer.getLong(OFFSET_TRANSACTION_ID);
}
public void setPreviousTransactionPage(int previousTransactionPage) {
this.previousTransactionPage = previousTransactionPage;
this.dirty = true;
public void setPreviousTransactionPageId(int previousTransactionPageId) {
getMutable().setPreviousTransactionPageId(previousTransactionPageId);
}
@Override
@@ -115,4 +207,8 @@ public boolean shouldSplit() {
return false;
}
public void addToFreelist(List<Integer> freelist) {
getMutable().addToFreelist(freelist);
}
}
@@ -11,6 +11,8 @@
import org.slf4j.LoggerFactory;
import com.cloudata.keyvalue.KeyValueProto.KvAction;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Queues;
@@ -63,6 +65,8 @@ public Page getPage(Page parent, int pageNumber) {
}
public void commit() {
List<Integer> freed = Lists.newArrayList();
Queue<TrackedPage> ready = Queues.newArrayDeque();
for (Entry<Integer, TrackedPage> entry : trackedPages.entrySet()) {
@@ -126,6 +130,10 @@ public void commit() {
newRootPage = newPageNumber;
}
if (oldPageNumber > 0) {
freed.add(oldPageNumber);
}
}
if (trackedPage.parent != null) {
@@ -142,6 +150,9 @@ public void commit() {
long transactionId = pageStore.assignTransactionId();
TransactionPage transactionPage = TransactionPage.createNew(assignPageNumber(), transactionId);
transactionPage.setRootPageId(newRootPage);
transactionPage.addToFreelist(freed);
log.info("Freed pages: {}", Joiner.on(",").join(freed));
pageStore.commitTransaction(transactionPage);
}

0 comments on commit 1c9e6d2

Please sign in to comment.