     catch e
       throw e unless e.code is "ENOENT"
     fs.rename replacement, permanent, _
+
+  # 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, _
 
 class exports.Strata
   # Construct the Strata from the options.

    fs.close(@fd, _) if @fd
    @position = @fd = null

# ### Branch Tier Files
#
# A branch tier file contains an array of object addresses 

#
class IO

    previous.next = next
    entry

  # Generate a file name for a tier file with an optional suffix for temporary
  # rewrite files. Tier file names are generated from the tier address.
  filename: (address, suffix) ->
    suffix or= ""
    padding = "00000000".substring(0, 8 - String(address).length)
