public void checkStructure(Hashtable ChunksInUse, bool FixErrors)
{
Hashtable buffernumberToType = new Hashtable();
Hashtable buffernumberToNext = new Hashtable();
Hashtable visited = new Hashtable();
long LastBufferNumber = this.buffers.nextBufferNumber();
for (long buffernumber=0; buffernumber<LastBufferNumber; buffernumber++)
{
byte buffertype;
long nextBufferNumber;
this.ParseBuffer(buffernumber, out buffertype, out nextBufferNumber);
buffernumberToType[buffernumber] = buffertype;
buffernumberToNext[buffernumber] = nextBufferNumber;
}
// traverse the freelist
long thisFreeBuffer = this.FreeListHead;
while (thisFreeBuffer!=NULLBUFFERPOINTER)
{
if (visited.ContainsKey(thisFreeBuffer))
{
throw new LinkedFileException("cycle in freelist "+thisFreeBuffer);
}
visited[thisFreeBuffer] = thisFreeBuffer;
byte thetype = (byte) buffernumberToType[thisFreeBuffer];
long nextbuffernumber = (long) buffernumberToNext[thisFreeBuffer];
if (thetype!=FREE)
{
throw new LinkedFileException("free list element not marked free "+thisFreeBuffer);
}
thisFreeBuffer = nextbuffernumber;
}
// traverse all nodes marked head
Hashtable allchunks = new Hashtable();
for (long buffernumber=0; buffernumber<LastBufferNumber; buffernumber++)
{
byte thetype = (byte) buffernumberToType[buffernumber];
if (thetype==HEAD)
{
if (visited.ContainsKey(buffernumber))
{
throw new LinkedFileException("head buffer already visited "+buffernumber);
}
allchunks[buffernumber] = buffernumber;
visited[buffernumber] = buffernumber;
long bodybuffernumber = (long) buffernumberToNext[buffernumber];
while (bodybuffernumber!=NULLBUFFERPOINTER)
{
byte bodytype = (byte) buffernumberToType[bodybuffernumber];
long nextbuffernumber = (long) buffernumberToNext[bodybuffernumber];
if (visited.ContainsKey(bodybuffernumber))
{
throw new LinkedFileException("body buffer visited twice "+bodybuffernumber);
}
visited[bodybuffernumber] = bodytype;
if (bodytype!=BODY)
{
throw new LinkedFileException("body buffer not marked body "+thetype);
}
bodybuffernumber = nextbuffernumber;
}
// check retrieval
this.GetChunk(buffernumber);
}
}
// make sure all were visited
for (long buffernumber=0; buffernumber<LastBufferNumber; buffernumber++)
{
if (!visited.ContainsKey(buffernumber))
{
throw new LinkedFileException("buffer not found either as data or free "+buffernumber);
}
}
// check against in use list
if (ChunksInUse!=null)
{
ArrayList notInUse = new ArrayList();
foreach (DictionaryEntry d in ChunksInUse)
{
long buffernumber = (long)d.Key;
if (!allchunks.ContainsKey(buffernumber))
{
//System.Diagnostics.Debug.WriteLine("\r\n<br>allocated chunks "+allchunks.Count);
//foreach (DictionaryEntry d1 in allchunks)
//{
// System.Diagnostics.Debug.WriteLine("\r\n<br>found "+d1.Key);
//}
throw new LinkedFileException("buffer in used list not found in linked file "+buffernumber+" "+d.Value);
}
}
foreach (DictionaryEntry d in allchunks)
{
long buffernumber = (long)d.Key;
if (!ChunksInUse.ContainsKey(buffernumber))
{
if (!FixErrors)
{
throw new LinkedFileException("buffer in linked file not in used list "+buffernumber);
}
notInUse.Add(buffernumber);
}
}
notInUse.Sort();
notInUse.Reverse();
foreach (object thing in notInUse)
{
long buffernumber = (long)thing;
this.ReleaseBuffers(buffernumber);
}
}
}