import javax.crypto.Mac;
import java.util.Arrays;
-class Slot {
- public static final int SLOT_SIZE=2048;
- public static final int HMAC_SIZE=32;
+class Slot implements Liveness {
+ static final int SLOT_SIZE=2048;
+ static final int RESERVED_SPACE=64;
+ static final int HMAC_SIZE=32;
private long seqnum;
private byte[] prevhmac;
private byte[] hmac;
private long machineid;
private Vector<Entry> entries;
+ private int livecount;
+ private boolean seqnumlive;
+ private int freespace;
- Slot(long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac, Vector<Entry> _entries) {
+ Slot(long _seqnum, long _machineid, byte[] _prevhmac, byte[] _hmac) {
seqnum=_seqnum;
machineid=_machineid;
prevhmac=_prevhmac;
hmac=_hmac;
- entries=_entries;
+ entries=new Vector<Entry>();
+ livecount=1;
+ seqnumlive=true;
+ freespace = SLOT_SIZE - getBaseSize();
}
-
- Slot(long _seqnum, byte[] _bytes) {
- seqnum=_seqnum;
+
+ Slot(long _seqnum, long _machineid, byte[] _prevhmac) {
+ this(_seqnum, _machineid, _prevhmac, null);
+ }
+
+ Slot(long _seqnum, long _machineid) {
+ this(_seqnum, _machineid, new byte[HMAC_SIZE], null);
}
byte[] getHMAC() {
return prevhmac;
}
+ void addEntry(Entry e) {
+ entries.add(e);
+ livecount++;
+ freespace -= e.getSize();
+ }
+
+ boolean hasSpace(Entry e) {
+ int newfreespace = freespace - e.getSize();
+ return newfreespace > RESERVED_SPACE;
+ }
+
+ boolean canFit(Entry e) {
+ int newfreespace = freespace - e.getSize();
+ return newfreespace >= 0;
+ }
+
Vector<Entry> getEntries() {
return entries;
}
-
+
static Slot decode(byte[] array, Mac mac) {
mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
byte[] realmac=mac.doFinal();
long seqnum=bb.getLong();
long machineid=bb.getLong();
int numentries=bb.getInt();
- Vector<Entry> entries=new Vector<Entry>();
- for(int i=0;i<numentries;i++) {
- entries.add(Entry.decode(bb));
+ Slot slot=new Slot(seqnum, machineid, prevhmac, hmac);
+
+ for(int i=0; i<numentries; i++) {
+ slot.addEntry(Entry.decode(slot, bb));
}
-
- return new Slot(seqnum, machineid, prevhmac, hmac, entries);
+
+ return slot;
}
byte[] encode(Mac mac) {
byte[] array=new byte[SLOT_SIZE];
ByteBuffer bb=ByteBuffer.wrap(array);
- bb.position(HMAC_SIZE); //Leave space for the HMACs
+ bb.position(HMAC_SIZE); //Leave space for the HMACs
bb.put(prevhmac);
bb.putLong(seqnum);
bb.putLong(machineid);
//Compute our HMAC
mac.update(array, HMAC_SIZE, array.length-HMAC_SIZE);
byte[] realmac=mac.doFinal();
+ hmac = realmac;
bb.position(0);
bb.put(realmac);
return array;
}
-
+
+ int getBaseSize() {
+ return 2*HMAC_SIZE+2*Long.BYTES+Integer.BYTES;
+ }
+
+ Vector<Entry> getLiveEntries() {
+ Vector<Entry> liveEntries=new Vector<Entry>();
+ for(Entry entry: entries)
+ if (entry.isLive())
+ liveEntries.add(entry);
+
+ if (seqnumlive)
+ liveEntries.add(new LastMessage(this, machineid, seqnum));
+
+ return liveEntries;
+ }
+
long getSequenceNumber() {
return seqnum;
}
long getMachineID() {
return machineid;
}
-
- byte[] getBytes() {
- return null;
+
+ void setDead() {
+ decrementLiveCount();
+ seqnumlive=false;
+ }
+
+ void decrementLiveCount() {
+ livecount--;
}
-
+
+ boolean isLive() {
+ return livecount > 0;
+ }
+
public String toString() {
- return "<"+getSequenceNumber()+", "+new String(getBytes())+">";
+ return "<"+getSequenceNumber()+">";
}
}