     @head.next      = @head
     @head.previous  = @head
     @nextAddress    = 0
+    @length         = 1024
 
   # Pages are identified by an integer page address. The page address is a number
   # that is incremented as new pages are created. A page file has a file name that

        # exclusive and shared locks to clear.
        key = tierOrAddress.cache[address] = @key address, 0, _
      key

  # TODO Consider: can't I always just rewrite and link?
  rewriteBranches: (tier, _) ->
    @writeBranches(tier, ".new", _)

  # TODO Ensure that you close the current tier I/O. Also, you must also be very
  # much locked before you use this, but I'm sure you know that.
  
  # Compact a leaf tier file by writing it to a temporary file that will become
  # the permanent file. All of records referenced by the current address array a
  # appended to a new leaf tier file using insert objects. An address array
  # object is appended to the end of new leaf tier file. The new file will load
  # quickly, because the address array object will be found immediately.
  rewriteLeaves: (tier, _) ->
    io = new LeafIO @filename(tier.address, ".new")
    addresses = []
    cache = {}
    for i in [0...tier.addresses.length]
      object = @object tier, i, _
      address = io.writeInsert(object, i, _)
      addresses.push address
      cache[address] = object
    io.writeAddresses(tier.right, addresses, _)
    io.close(_)
    extend tier, { addresses, cache }

  readLeaves: (tier, _) ->
    filename = @filename tier.address
    stat = fs.stat filename, _
    fd = fs.open filename, "r+", _

    # Obviously, while all this is going on, I could end up writing to the
    # leaf, because it is not actually locked. First lock, then load. The
    # entry object needs to be linked, then loaded.
    line      = ""
    offset    = -1
    end       = stat.size
    eol       = stat.size
    splices   = []
    addresses = []
    cache     = {}
    buffer    = new Buffer(1024)
    while end
      end     = eol
      start   = end - buffer.length
      start   = 0 if start < 0
      read    = fs.read fd, buffer, 0, buffer.length, start, _
      end    -= read
      offset  = read
      if buffer[--read] isnt 0x0A
        throw new Error "corrupt leaves"
      eos     = read + 1
      stop    = if start is 0 then 0 else -1
      while read != 0
        read = read - 1
        if buffer[read] is 0x0A or read is stop
          record = JSON.parse buffer.toString("utf8", read, eos)
          eos   = read + 1
          index = record.shift()
          if index is 0
            [ addresses, end ] = [ record, 0 ]
            break
          else
            splices.push [ index, start + read ]
            if index > 0
              cache[start + read] = record.shift()
      eol = start + eos
    splices.reverse()
    for splice in splices
      [ index, address ] = splice
      if index > 0
        addresses.splice(index - 1, 0, address)
      else
        addresses.splice(-(index + 1), 1)
    fs.close fd, _
    loaded = true
    io = new LeafIO @filename tier.address
    tier = extend tier, { addresses, cache, loaded, io }

  # TODO Move down, bring read and write up.
  lock: (exclusive, address, leaf, callback) ->
    if not tier = @cache[address]
      @cache[address] = tier =
        @link({ leaf, address, cache: {}, addresses: [], locks: [[]] })
    locks = tier.locks
    if tier.loaded
      lock = callback
    else
      lock = (error, tier) =>
        if error
          callback error
        else if tier.loaded
          callback null, tier
        else if leaf
          @readLeaves tier, callback
        else
          @readBranches tier, callback
    if exclusive
      throw new Error "already locked" unless locks.length % 2
      locks.push [ lock ]
      locks.push []
      if locks[0].length is 0
        locks.shift()
        lock(null, tier)
    else
      locks[locks.length - 1].push lock
      if locks.length is 1
        lock(null, tier)

  resume: (tier, continuations) ->
    process.nextTick =>
      for callback in continuations
        callback(null, tier)

  # Remove the lock callback from the callback list..
  release: (tier) ->
    locks = tier.locks
    running = locks[0]
    running.shift()
    say { locks }
    if running.length is 0 and locks.length isnt 1
      locks.shift()
      @resume tier, locks[0] if locks[0].length
      
  upgrade: (tier, _) ->
    @release tier
    @lock true, tier.address, false, _

# Glossary:
# 
#  * Descent - What we call an attempt to move from a parent node to a child
#              node in  the tree, which may be paused because it encounters a
#              lock on a tier.
#  * Record - A JSON object stored in the b-tree.
#  * Object - JavaScript objects are referred to as objects in this
#             documentation and are not to be confused with actual records.

#              
class Mutation
  # The constructor always felt like a dangerous place to be doing anything
  # meaningful in C++ or Java.
  constructor: (@strata, @object, @key, @operation) ->
    @io         = @strata._io
    @options    = @strata._options

    @parent     = { operations: [], locks: [] }
    @child      = { operations: [], locks: [] }
    @exclusive  = []
    @shared     = []
    @pivots     = []

    { @extractor, @comparator } = @options

    @key        = @extractor @object if @object? and not key?
  
  # Descend the tree, optionally starting an exclusive descent. Once the descent
  # is exclusive, all subsequent descents are exclusive.


  #
  rewriteBranches: (page, _) ->
    filename = @filename page.address, ".new"
    record = [ page.penultimate, page.next?.address, page.addresses ]
    json = JSON.stringify(record) + "\n"
