ftss index queue file format

The index queue is a linked list with extra fields for error recovery. Each item in the list is a fixed width field. The file is structured so that O(1) complexity is possible for push, pop, peek, and count operations. All file pointers (not FILE* but actual locations in the file) are platform dependent and are stored in machine byte order. File pointers are written to disk as the type long int, which, at the time of this writing, are 32 bits on some platforms and 64 on others.

The file is organized according to Figure 1. Each entry is given by Figure 2. The head pointer is the first entry in the queue, that is, the next entry to be removed from the queue. The tail pointer is the last entry in the queue. The free pointer is the last free entry in the queue. See Figure 3 for a graphical view of these pointers. The element count is the number of elements in the queue. This is necessary to determine when there are no more elements in the queue because head = tail is not enough. Head = tail is true when there is one element and when there is zero elements. The fields that begin with "last" are used for error recovery. They contain the values of their corresponding pointers at the time of the last successful operation.

------------------------------------------------------
| last operation (1 byte) | operation stage (1 byte) | 
------------------------------------------------------
| head ptr | tail ptr | free ptr | element count |
----------------------------------------------------------------------
| last head ptr | last tail ptr | last free ptr | last element count |
----------------------------------------------------------------------
| save ptr 1 |
-------------------------------------
| entry 1 | entry 2 | ... | entry N |
-------------------------------------
Figure 1 - Field order

---------------------------------------------------------------
| next entry ptr | filename (32 bytes) | user data (64 bytes) |
---------------------------------------------------------------
Figure 2 - Entry Format

Queue Pointers

Figure 3.

The last operation can have the following values:

The operation stage contains a value that corresponds to the stage an operation failed in.

Operation Stages

Add and remove operations have different operation stages. Following is a discussion of the stages for each operation.

Add Operation

To begin an add operation, set last operation = 1 and set OS (operation stage) = 1.

Stage 1

Set save ptr 1 to free->next if free is not 0. Otherwise set save ptr 1 to 0. Set OS = 2.

Stage 2

if free = tail then
  append new entry
  if free = 0 then
    set free = location of appended entry
    set free->next = 0
  else
    set free->next = location of appended entry
    set free = free->next
  end
else if tail != 0
  write entry at tail->next
else
  write entry at free
end

if tail then
  set tail = tail->next
else
  set head = free;
  set tail = free;
end

increment element count by 1

set OS = 3

Stage 3

Save last pointers. Set OS = 0. Set last operation = 0.

Remove operation

To begin a remove operation, set last operation = 2 and set OS = 1.

Stage 1

set save ptr 1 = free->next and set OS = 2.

Stage 2

if free != head then // If there is more than one queue item.
  set free->next = head
  set free = free->next
  if tail = head
    set tail = head->next
  end
  set head = head->next
  set free->next = 0
else
  set head = 0
  set tail = 0
end

decrement element count by 1

set OS = 3

Stage 3

Save last pointers. set last operation = 0 and set OS = 0.

Error Recovery

If an error occurs (power down, out of disk space, etc) while writing to the queue file then the last operation and the OS together will contain the enough information to restore the queue file to a consistent state.

Add Error Recovery

The OS indicates which stage to recover from.

Stage 1

Set save ptr 1 = 0, set last operation to 0, and set CS = 0.

Stage 2

Restore head, tail, free, element count, and last free->next with last head, last tail, last free, last element count, and save ptr 1, respectively. Then set last operation = 0 and set OS = 0. At this point the entry may have been created, so we will lose some space. But this will rarely happen, it if ever happens at all, and can be reset by deleting the queue file.

Stage 3

Set last head, last tail, last free, and element count with head, tail, free, and element count repsectively. Then set last operation = 0 and set CS = 0.

Remove Error Recovery

Stage 1

Retry remove.

Stage 2

Restore from last variables, set last free->next = save ptr 1, and then retry remove.

Stage 3

Set save pointers. Set last operation = 0 and set OS = 0.