|
|
|
@ -7,7 +7,7 @@
|
|
|
|
|
// $LastChangedBy$
|
|
|
|
|
//
|
|
|
|
|
// LICENSE
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
|
|
@ -37,7 +37,7 @@ public class Stack {
|
|
|
|
|
|
|
|
|
|
private final Heap stack;
|
|
|
|
|
private long lastHandle;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* create a new stack object.
|
|
|
|
|
* a stack object is backed by a blob file that contains the stack entries.
|
|
|
|
@ -45,7 +45,7 @@ public class Stack {
|
|
|
|
|
* represented as b256-encoded byte[] as key in the blob.
|
|
|
|
|
* The handle is created using the current time. That means that the top
|
|
|
|
|
* element on the stack has the maximum time as key handle and the element
|
|
|
|
|
* at the bottom of the stack has the minimum time as key handle
|
|
|
|
|
* at the bottom of the stack has the minimum time as key handle
|
|
|
|
|
* @param stackFile
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
@ -53,7 +53,15 @@ public class Stack {
|
|
|
|
|
this.stack = new Heap(stackFile, 8, NaturalOrder.naturalOrder, 0);
|
|
|
|
|
this.lastHandle = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* clear the stack content
|
|
|
|
|
* @throws IOException
|
|
|
|
|
*/
|
|
|
|
|
public void clear() throws IOException {
|
|
|
|
|
this.stack.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* create a new time handle. In case that the method is called
|
|
|
|
|
* within a single millisecond twice, a new handle is created using
|
|
|
|
@ -63,11 +71,11 @@ public class Stack {
|
|
|
|
|
*/
|
|
|
|
|
private long nextHandle() {
|
|
|
|
|
long h = System.currentTimeMillis();
|
|
|
|
|
if (h <= this.lastHandle) h = lastHandle + 1;
|
|
|
|
|
lastHandle = h;
|
|
|
|
|
if (h <= this.lastHandle) h = this.lastHandle + 1;
|
|
|
|
|
this.lastHandle = h;
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Iterate all handles from the stack as Long numbers
|
|
|
|
|
* @return an iterator of all handles of the stack
|
|
|
|
@ -76,7 +84,7 @@ public class Stack {
|
|
|
|
|
public synchronized Iterator<Long> handles() throws IOException {
|
|
|
|
|
return NaturalOrder.LongIterator(this.stack.keys(true, false));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* get the size of a stack
|
|
|
|
|
* @return the number of entries on the stack
|
|
|
|
@ -84,20 +92,20 @@ public class Stack {
|
|
|
|
|
public synchronized int size() {
|
|
|
|
|
return this.stack.size();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* push a new element on the top of the stack
|
|
|
|
|
* @param b the new stack element
|
|
|
|
|
* @return the handle used to store the new element
|
|
|
|
|
* @throws IOException
|
|
|
|
|
* @throws RowSpaceExceededException
|
|
|
|
|
* @throws RowSpaceExceededException
|
|
|
|
|
*/
|
|
|
|
|
public synchronized long push(final byte[] b) throws IOException, RowSpaceExceededException {
|
|
|
|
|
long handle = nextHandle();
|
|
|
|
|
this.stack.insert(NaturalOrder.encodeLong(handle, 8), b);
|
|
|
|
|
return handle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* push a new element on the top of the stack using a entry object
|
|
|
|
|
* this is only useful for internal processes where a special handle
|
|
|
|
@ -105,19 +113,19 @@ public class Stack {
|
|
|
|
|
* @param b the new stack element
|
|
|
|
|
* @return the handle used to store the new element
|
|
|
|
|
* @throws IOException
|
|
|
|
|
* @throws RowSpaceExceededException
|
|
|
|
|
* @throws RowSpaceExceededException
|
|
|
|
|
*/
|
|
|
|
|
protected synchronized void push(final Entry e) throws IOException, RowSpaceExceededException {
|
|
|
|
|
this.stack.insert(NaturalOrder.encodeLong(e.h, 8), e.b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* get an element from the stack using the handle
|
|
|
|
|
* @param handle
|
|
|
|
|
* @return the object that belongs to the handle
|
|
|
|
|
* or null if no such element exists
|
|
|
|
|
* @throws IOException
|
|
|
|
|
* @throws RowSpaceExceededException
|
|
|
|
|
* @throws RowSpaceExceededException
|
|
|
|
|
*/
|
|
|
|
|
public synchronized byte[] get(final long handle) throws IOException, RowSpaceExceededException {
|
|
|
|
|
byte[] k = NaturalOrder.encodeLong(handle, 8);
|
|
|
|
@ -125,13 +133,13 @@ public class Stack {
|
|
|
|
|
if (b == null) return null;
|
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* remove an element from the stack using the entry handle
|
|
|
|
|
* @param handle
|
|
|
|
|
* @return the removed element
|
|
|
|
|
* @throws IOException
|
|
|
|
|
* @throws RowSpaceExceededException
|
|
|
|
|
* @throws RowSpaceExceededException
|
|
|
|
|
*/
|
|
|
|
|
public synchronized byte[] remove(final long handle) throws IOException, RowSpaceExceededException {
|
|
|
|
|
byte[] k = NaturalOrder.encodeLong(handle, 8);
|
|
|
|
@ -140,7 +148,7 @@ public class Stack {
|
|
|
|
|
this.stack.delete(k);
|
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* remove the top element from the stack
|
|
|
|
|
* @return the top element or null if the stack is empty
|
|
|
|
@ -149,7 +157,7 @@ public class Stack {
|
|
|
|
|
public synchronized Entry pop() throws IOException {
|
|
|
|
|
return po(this.stack.lastKey(), true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* return the top element of the stack.
|
|
|
|
|
* The element is not removed from the stack.
|
|
|
|
@ -160,7 +168,7 @@ public class Stack {
|
|
|
|
|
public synchronized Entry top() throws IOException {
|
|
|
|
|
return po(this.stack.lastKey(), false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* remove the bottom element from the stack
|
|
|
|
|
* @return the bottom element or null if the stack is empty
|
|
|
|
@ -169,7 +177,7 @@ public class Stack {
|
|
|
|
|
public synchronized Entry pot() throws IOException {
|
|
|
|
|
return po(this.stack.firstKey(), true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* return the bottom element of the stack.
|
|
|
|
|
* The element is not removed from the stack.
|
|
|
|
@ -180,7 +188,7 @@ public class Stack {
|
|
|
|
|
public synchronized Entry bot() throws IOException {
|
|
|
|
|
return po(this.stack.firstKey(), false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Entry po(final byte[] k, final boolean remove) throws IOException {
|
|
|
|
|
if (k == null) return null;
|
|
|
|
|
assert k.length == 8;
|
|
|
|
@ -196,12 +204,12 @@ public class Stack {
|
|
|
|
|
if (remove) this.stack.delete(k);
|
|
|
|
|
return new Entry(k, b);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public class Entry {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long h;
|
|
|
|
|
byte[] b;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* create a new entry object using a long handle
|
|
|
|
|
* @param h
|
|
|
|
@ -211,7 +219,7 @@ public class Stack {
|
|
|
|
|
this.h = h;
|
|
|
|
|
this.b = b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* create a new entry object using the byte[] encoded handle
|
|
|
|
|
* @param k
|
|
|
|
@ -221,31 +229,31 @@ public class Stack {
|
|
|
|
|
this.h = NaturalOrder.decodeLong(k);
|
|
|
|
|
this.b = b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* get the handle
|
|
|
|
|
* @return the handle
|
|
|
|
|
*/
|
|
|
|
|
public long handle() {
|
|
|
|
|
return h;
|
|
|
|
|
return this.h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* get the blob entry
|
|
|
|
|
* @return the blob
|
|
|
|
|
*/
|
|
|
|
|
public byte[] blob() {
|
|
|
|
|
return b;
|
|
|
|
|
return this.b;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* close the stack file and write a handle index
|
|
|
|
|
*/
|
|
|
|
|
public synchronized void close() {
|
|
|
|
|
this.stack.close(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void finalize() {
|
|
|
|
|
this.close();
|
|
|
|
|