You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ch...@apache.org on 2008/08/20 21:07:19 UTC
svn commit: r687427 - in
/activemq/sandbox/kahadb/src/main/java/org/apache/kahadb:
page/PageFile.java util/Sequence.java util/SequenceSet.java
Author: chirino
Date: Wed Aug 20 12:07:19 2008
New Revision: 687427
URL: http://svn.apache.org/viewvc?rev=687427&view=rev
Log:
PageFile can now allocate a sequencial set of pages.
Modified:
activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/page/PageFile.java
activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/Sequence.java
activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/SequenceSet.java
Modified: activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/page/PageFile.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/page/PageFile.java?rev=687427&r1=687426&r2=687427&view=diff
==============================================================================
--- activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/page/PageFile.java (original)
+++ activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/page/PageFile.java Wed Aug 20 12:07:19 2008
@@ -51,6 +51,8 @@
import org.apache.kahadb.util.IOHelper;
import org.apache.kahadb.util.IntrospectionSupport;
import org.apache.kahadb.util.LRUCache;
+import org.apache.kahadb.util.Sequence;
+import org.apache.kahadb.util.SequenceSet;
/**
* A PageFile provides you random access to fixed sized disk pages. This object is not thread safe and therefore access to it should
@@ -87,7 +89,7 @@
private byte[] readBuffer;
private long nextFreePageId;
- private LinkedList<Long> freeList = new LinkedList<Long>();
+ private SequenceSet freeList = new SequenceSet();
private AtomicBoolean loaded = new AtomicBoolean();
private LRUCache<Long, Page> pageCache;
@@ -287,7 +289,7 @@
lastTxId = redoRecoveryUpdates();
// Scan all to find the free pages.
- freeList.clear();
+ freeList = new SequenceSet();
long length = readFile.length();
Page page = new Page();
long offset = initialPageOffset;
@@ -373,7 +375,7 @@
/**
- * Gives you back a free page that you can write data to.
+ * Allocates a free page that you can write data to.
*
* @return a newly allocated page.
* @throws IOException
@@ -403,6 +405,48 @@
addToCache(page);
return page;
}
+
+ /**
+ * Allocates a block of free pages that you can write data to.
+ *
+ * @param count the number of sequential pages to allocate
+ * @return the first page of the sequential set.
+ * @throws IOException
+ * If an disk error occurred.
+ * @throws IllegalStateException
+ * if the PageFile is not loaded
+ */
+ public Page allocate(int count) throws IOException {
+ if( !loaded.get() ) {
+ throw new IllegalStateException("Cannot allocate a page when the page file is not loaded");
+ }
+
+ Page page = null;
+ Sequence seq = freeList.removeFirstSequence(count);
+ if(seq!=null) {
+ page = new Page();
+ page.setPageId(seq.getFirst());
+ page.setType(Page.FREE_TYPE);
+ } else {
+
+ // allocate the pages..
+ Page t = new Page();
+ while( count > 0 ) {
+ t.setPageId(nextFreePageId);
+ t.setType(Page.FREE_TYPE);
+ nextFreePageId ++;
+ write(t, null);
+ count--;
+
+ if( page == null ) {
+ page = t;
+ }
+ }
+
+ }
+ addToCache(page);
+ return page;
+ }
/**
* Frees up a previously allocated page so that it can be re-allocated again.
@@ -1008,10 +1052,7 @@
private void storeFreeList() throws IOException {
FileOutputStream os = new FileOutputStream(getFreeFile());
DataOutputStream dos = new DataOutputStream(os);
- dos.writeLong(freeList.size());
- for (Long offset : freeList) {
- dos.writeLong(offset);
- }
+ SequenceSet.Marshaller.INSTANCE.writePayload(freeList, dos);
dos.close();
}
@@ -1019,10 +1060,7 @@
freeList.clear();
FileInputStream is = new FileInputStream(getFreeFile());
DataInputStream dis = new DataInputStream(is);
- long size = dis.readLong();
- for ( long i=-0 ; i < size; i++) {
- freeList.add(dis.readLong());
- }
+ freeList = SequenceSet.Marshaller.INSTANCE.readPayload(dis);
dis.close();
}
Modified: activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/Sequence.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/Sequence.java?rev=687427&r1=687426&r2=687427&view=diff
==============================================================================
--- activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/Sequence.java (original)
+++ activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/Sequence.java Wed Aug 20 12:07:19 2008
@@ -55,4 +55,20 @@
return first == last ? "" + first : first + "-" + last;
}
+ public long getFirst() {
+ return first;
+ }
+
+ public void setFirst(long first) {
+ this.first = first;
+ }
+
+ public long getLast() {
+ return last;
+ }
+
+ public void setLast(long last) {
+ this.last = last;
+ }
+
}
\ No newline at end of file
Modified: activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/SequenceSet.java
URL: http://svn.apache.org/viewvc/activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/SequenceSet.java?rev=687427&r1=687426&r2=687427&view=diff
==============================================================================
--- activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/SequenceSet.java (original)
+++ activemq/sandbox/kahadb/src/main/java/org/apache/kahadb/util/SequenceSet.java Wed Aug 20 12:07:19 2008
@@ -16,8 +16,12 @@
*/
package org.apache.kahadb.util;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.NoSuchElementException;
/**
* Keeps track of a added long values. Collapses ranges of numbers using a
@@ -27,18 +31,61 @@
* @author chirino
*/
public class SequenceSet {
- LinkedNodeList<Sequence> sequences = new LinkedNodeList<Sequence>();
+
+ public static class Marshaller implements org.apache.kahadb.Marshaller<SequenceSet> {
+
+ public static final Marshaller INSTANCE = new Marshaller();
+
+ public Class<SequenceSet> getType() {
+ return SequenceSet.class;
+ }
+
+ public SequenceSet readPayload(DataInput in) throws IOException {
+ SequenceSet value = new SequenceSet();
+ int count = in.readInt();
+ for (int i = 0; i < count; i++) {
+ if( in.readBoolean() ) {
+ Sequence sequence = new Sequence(in.readLong(), in.readLong());
+ value.sequences.addLast(sequence);
+ } else {
+ Sequence sequence = new Sequence(in.readLong());
+ value.sequences.addLast(sequence);
+ }
+ }
+ return value;
+ }
+ public void writePayload(SequenceSet value, DataOutput out) throws IOException {
+ out.writeInt(value.sequences.size());
+ Sequence sequence = value.sequences.getHead();
+ while (sequence != null ) {
+ if( sequence.range() > 1 ) {
+ out.writeBoolean(true);
+ out.writeLong(sequence.first);
+ out.writeLong(sequence.last);
+ } else {
+ out.writeBoolean(false);
+ out.writeLong(sequence.first);
+ }
+ sequence = sequence.getNext();
+ }
+ }
+ }
+
+ LinkedNodeList<Sequence> sequences = new LinkedNodeList<Sequence>();
+ int size;
+
/**
*
* @param value
* the value to add to the list
* @return false if the value was a duplicate.
*/
- synchronized public boolean add(long value) {
+ public boolean add(long value) {
if (sequences.isEmpty()) {
sequences.addFirst(new Sequence(value));
+ size++;
return true;
}
@@ -57,6 +104,7 @@
next.unlink();
}
}
+ size++;
return true;
}
@@ -73,6 +121,7 @@
prev.unlink();
}
}
+ size++;
return true;
}
@@ -80,6 +129,7 @@
if (value < sequence.first) {
// Then insert a new entry before this sequence item.
sequence.linkBefore(new Sequence(value));
+ size++;
return true;
}
@@ -93,14 +143,59 @@
// Then the value is getting appended to the tail of the sequence.
sequences.addLast(new Sequence(value));
+ size++;
return true;
}
+
+ /**
+ * Removes and returns the first element from this list.
+ *
+ * @return the first element from this list.
+ * @throws NoSuchElementException if this list is empty.
+ */
+ public long removeFirst() {
+ if (sequences.isEmpty()) {
+ throw new NoSuchElementException();
+ }
+
+ Sequence rc = removeFirstSequence(1);
+ return rc.first;
+ }
+
+ /**
+ * Removes and returns the first sequence that is count range large.
+ *
+ * @return a sequence that is count range large, or null if no sequence is that large in the list.
+ */
+ public Sequence removeFirstSequence(long count) {
+ if (sequences.isEmpty()) {
+ return null;
+ }
+
+ Sequence sequence = sequences.getHead();
+ while (sequence != null ) {
+ if (sequence.range() == count ) {
+ sequence.unlink();
+ size--;
+ return sequence;
+ }
+ if (sequence.range() > count ) {
+ Sequence rc = new Sequence(sequence.first, sequence.first+count);
+ sequence.first+=count;
+ size--;
+ return rc;
+ }
+ sequence = sequence.getNext();
+ }
+ return null;
+ }
+
/**
* @return all the id Sequences that are missing from this set that are not
* in between the range provided.
*/
- synchronized public List<Sequence> getMissing(long first, long last) {
+ public List<Sequence> getMissing(long first, long last) {
ArrayList<Sequence> rc = new ArrayList<Sequence>();
if (first > last) {
throw new IllegalArgumentException("First cannot be more than last");
@@ -138,7 +233,7 @@
/**
* @return all the Sequence that are in this list
*/
- synchronized public List<Sequence> getReceived() {
+ public List<Sequence> getReceived() {
ArrayList<Sequence> rc = new ArrayList<Sequence>(sequences.size());
Sequence sequence = sequences.getHead();
while (sequence != null) {
@@ -147,4 +242,16 @@
}
return rc;
}
+
+ public boolean isEmpty() {
+ return sequences.isEmpty();
+ }
+
+ public long size() {
+ return size;
+ }
+
+ public void clear() {
+ sequences = new LinkedNodeList<Sequence>();
+ }
}
\ No newline at end of file