void readHeader() throws Exception {
   byte[] header = new byte[this.headersize];
   // this.fromfile.Seek(this.seekStart, System.IO.SeekOrigin.Begin);
   this.fromfile.seek(this.seekStart);
   // this.fromfile.Read(header, 0, this.headersize);
   this.fromfile.read(header, 0, this.headersize);
   int index = 0;
   // check prefix
   // foreach (byte b in HEADERPREFIX)
   for (int i = 0; i < HEADERPREFIX.length; i++) {
     byte b = HEADERPREFIX[i];
     if (header[index] != b) {
       throw new LinkedFileException("invalid header prefix");
     }
     index++;
   }
   // skip version (for now)
   index++;
   // read buffersize
   this.buffersize = BufferFile.Retrieve(header, index);
   index += BufferFile.INTSTORAGE;
   this.FreeListHead = BufferFile.RetrieveLong(header, index);
   this.sanityCheck();
   this.headerDirty = false;
 }
 public byte[] makeHeader() throws Exception {
   byte[] result = new byte[this.headersize];
   // HEADERPREFIX.CopyTo(result, 0);
   for (int i = 0; i < HEADERPREFIX.length; i++) {
     result[i] = HEADERPREFIX[i];
   }
   result[HEADERPREFIX.length] = VERSION;
   int index = HEADERPREFIX.length + 1;
   BufferFile.Store(this.buffersize, result, index);
   index += BufferFile.INTSTORAGE;
   BufferFile.Store(this.FreeListHead, result, index);
   return result;
 }
 public static LinkedFile SetupFromExistingStream(
     java.io.RandomAccessFile fromfile, long StartSeek) throws Exception {
   LinkedFile result = new LinkedFile(100, StartSeek); // dummy buffer size for now
   result.fromfile = fromfile;
   result.readHeader();
   result.buffers = BufferFile.SetupFromExistingStream(fromfile, StartSeek + result.headersize);
   return result;
 }
 public long StoreNewChunk(byte[] fromArray, int startingAt, int length) throws Exception {
   // get the first buffer as result value
   long currentBufferNumber = this.AllocateBuffer();
   // System.Diagnostics.Debug.WriteLine(" allocating chunk starting at "+currentBufferNumber);
   long result = currentBufferNumber;
   if (length < 0 || startingAt < 0) {
     throw new LinkedFileException(
         "cannot store negative length chunk (" + startingAt + "," + length + ")");
   }
   int endingAt = startingAt + length;
   // special case: zero length chunk
   if (endingAt > fromArray.length) {
     throw new LinkedFileException("array doesn't have this much data: " + endingAt);
   }
   int index = startingAt;
   // store header with length information
   byte[] buffer = new byte[this.buffersize];
   BufferFile.Store(length, buffer, 0);
   int fromIndex = startingAt;
   int firstLength = this.buffersize - BufferFile.INTSTORAGE;
   int stored = 0;
   if (firstLength > length) {
     firstLength = length;
   }
   // Array.Copy(fromArray, fromIndex, buffer, BufferFile.INTSTORAGE, firstLength);
   for (int i = 0; i < firstLength; i++) {
     buffer[BufferFile.INTSTORAGE + i] = fromArray[i];
   }
   stored += firstLength;
   fromIndex += firstLength;
   byte CurrentBufferType = HEAD;
   // store any remaining buffers (no length info)
   while (stored < length) {
     // store current buffer and get next block number
     long NextBufferNumber = this.AllocateBuffer();
     this.SetBuffer(
         currentBufferNumber, CurrentBufferType, buffer, 0, buffer.length, NextBufferNumber);
     currentBufferNumber = NextBufferNumber;
     CurrentBufferType = BODY;
     int nextLength = this.buffersize;
     if (stored + nextLength > length) {
       nextLength = length - stored;
     }
     // Array.Copy(fromArray, fromIndex, buffer, 0, nextLength);
     for (int i = 0; i < nextLength; i++) {
       buffer[i] = fromArray[fromIndex + i];
     }
     stored += nextLength;
     fromIndex += nextLength;
   }
   // store final buffer
   this.SetBuffer(
       currentBufferNumber, CurrentBufferType, buffer, 0, buffer.length, NULLBUFFERPOINTER);
   return result;
 }
 public static LinkedFile InitializeLinkedFileInStream(
     java.io.RandomAccessFile fromfile, int buffersize, long StartSeek) throws Exception {
   LinkedFile result = new LinkedFile(buffersize, StartSeek);
   result.fromfile = fromfile;
   result.setHeader();
   // buffersize should be increased by overhead...
   result.buffers =
       BufferFile.InitializeBufferFileInStream(
           fromfile, buffersize + BUFFEROVERHEAD, StartSeek + result.headersize);
   return result;
 }
 public ParseBuffer(long bufferNumber) throws Exception {
   byte[] thebuffer = new byte[LinkedFile.this.buffersize];
   byte[] fullbuffer = new byte[LinkedFile.this.buffersize + LinkedFile.BUFFEROVERHEAD];
   LinkedFile.this.buffers.getBuffer(bufferNumber, fullbuffer, 0, fullbuffer.length);
   this.type = fullbuffer[0];
   this.NextBufferNumber = BufferFile.RetrieveLong(fullbuffer, 1);
   for (int i = 0; i < LinkedFile.this.buffersize; i++) {
     thebuffer[i] = fullbuffer[i + LinkedFile.BUFFEROVERHEAD];
   }
   this.payload = thebuffer;
 }
 public byte[] GetChunk(long HeadBufferNumber) throws Exception {
   // get the head, interpret the length
   // byte buffertype;
   // long NextBufferNumber;
   // byte[] buffer = this.ParseBuffer(HeadBufferNumber, out buffertype, out NextBufferNumber);
   ParseBuffer P = new ParseBuffer(HeadBufferNumber);
   byte buffertype = P.type;
   long NextBufferNumber = P.NextBufferNumber;
   byte[] buffer = P.payload;
   int length = BufferFile.Retrieve(buffer, 0);
   if (length < 0) {
     throw new LinkedFileException("negative length block? must be garbage: " + length);
   }
   if (buffertype != HEAD) {
     throw new LinkedFileException("first buffer not marked HEAD");
   }
   byte[] result = new byte[length];
   // read in the data from the first buffer
   int firstLength = this.buffersize - BufferFile.INTSTORAGE;
   if (firstLength > length) {
     firstLength = length;
   }
   // Array.Copy(buffer, BufferFile.INTSTORAGE, result, 0, firstLength);
   for (int i = 0; i < firstLength; i++) {
     result[i] = buffer[BufferFile.INTSTORAGE + i];
   }
   int stored = firstLength;
   while (stored < length) {
     // get the next buffer
     long thisBufferNumber = NextBufferNumber;
     // buffer = this.ParseBuffer(thisBufferNumber, out buffertype, out NextBufferNumber);
     P = new ParseBuffer(thisBufferNumber);
     buffer = P.payload;
     buffertype = P.type;
     NextBufferNumber = P.NextBufferNumber;
     int nextLength = this.buffersize;
     if (length - stored < nextLength) {
       nextLength = length - stored;
     }
     // Array.Copy(buffer, 0, result, stored, nextLength);
     for (int i = 0; i < nextLength; i++) {
       result[stored + i] = buffer[i];
     }
     stored += nextLength;
   }
   return result;
 }
 void SetBuffer(
     long buffernumber, byte type, byte[] thebuffer, int start, int length, long NextBufferNumber)
     throws Exception {
   // System.Diagnostics.Debug.WriteLine(" storing chunk type "+type+" at "+buffernumber);
   if (this.buffersize < length) {
     throw new LinkedFileException("buffer size too small " + this.buffersize + "<" + length);
   }
   byte[] fullbuffer = new byte[length + BUFFEROVERHEAD];
   fullbuffer[0] = type;
   BufferFile.Store(NextBufferNumber, fullbuffer, 1);
   if (thebuffer != null) {
     // Array.Copy(thebuffer, start, fullbuffer, BUFFEROVERHEAD, length);
     for (int i = 0; i < length; i++) {
       fullbuffer[BUFFEROVERHEAD + i] = thebuffer[i];
     }
   }
   this.buffers.setBuffer(buffernumber, fullbuffer, 0, fullbuffer.length);
 }