<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -26,4 +26,14 @@ D = (blocksize-5)/16
 
 key file:
 
-[key\0,key\0,key\0]
\ No newline at end of file
+[key\0,key\0,key\0]
+
+keys allocation
+
+l = 2**4
+
+m = 2**64
+
+
+
+header size = 85 + (&#8730;blocksize - 4)*8
\ No newline at end of file</diff>
      <filename>BTREEFORMAT</filename>
    </modified>
    <modified>
      <diff>@@ -18,7 +18,11 @@ task :default =&gt; [:build_deps] do
   # end
 end
 
-task :clean do
+task :clean_test do
+  sh &quot;rm -rf etest/log/*&quot;
+end
+
+task :clean =&gt; [:clean_test] do
   sh &quot;rm -f ebin/*.beam&quot;
   sh &quot;rm -f etest/*.beam&quot;
 end</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -245,19 +245,19 @@ code_change(_OldVsn, State, _Extra) -&gt;
 %% Internal functions
 %%====================================================================
 delete(KeyHash, Key, Parent, Node = #node{children=Children,keys=Keys}, Tree) -&gt;
-  % error_logger:info_msg(&quot;delete key ~p keyhash ~p from node ~p~n&quot;, [Key, KeyHash, Node]),
+  error_logger:info_msg(&quot;delete key ~p keyhash ~p from node ~p~n&quot;, [Key, KeyHash, Node]),
   {WhatItDo, DeleteNode} = case find_child_adj(KeyHash, Keys, Children) of
     {FoundKey, {{LeftHash, LeftPointer}, {RightHash, RightPointer}}} -&gt;
       LeftNode = dmtree:read(LeftPointer, Tree),
       RightNode = dmtree:read(RightPointer, Tree),
-      % ?infoFmt(&quot;delete_merge foundkey ~p~nLeftPointer ~p~nrightpointer ~p~nparent ~p~nnode ~p~nleftnode ~p~nrightnode ~p~n&quot;, [FoundKey, LeftPointer, RightPointer, Parent, Node, LeftNode, RightNode]),
+      ?infoFmt(&quot;delete_merge foundkey ~p~nLeftPointer ~p~nrightpointer ~p~nparent ~p~nnode ~p~nleftnode ~p~nrightnode ~p~n&quot;, [FoundKey, LeftPointer, RightPointer, Parent, Node, LeftNode, RightNode]),
       delete_merge(FoundKey, dmtree:d(Tree), Parent, Node, LeftNode, RightNode, Tree);
     {FoundKey, {{LeftHash, LeftPointer}, undefined}} -&gt;
       {nothing, dmtree:read(LeftPointer, Tree)}
   end,
-  % ?infoMsg(&quot;recursing into delete~n&quot;),
+  ?infoMsg(&quot;recursing into delete~n&quot;),
   ReturnNode = delete(KeyHash, Key, Node, DeleteNode, Tree),
-  % ?infoFmt(&quot;reduced from delete ~p~n&quot;, [ReturnNode]),
+  ?infoFmt(&quot;reduced from delete ~p~n&quot;, [ReturnNode]),
   Eqls = ref_equals(ReturnNode, Node),
   case WhatItDo of
     wamp_wamp -&gt; ReturnNode;
@@ -266,22 +266,22 @@ delete(KeyHash, Key, Parent, Node = #node{children=Children,keys=Keys}, Tree) -&gt;
   end;
 
 delete(KeyHash, Key, Parent, Leaf = #leaf{values=Values}, Tree) -&gt;
-  % error_logger:info_msg(&quot;delete key ~p keyhash ~p from ~p~n&quot;, [Key, KeyHash, Leaf]),
+  error_logger:info_msg(&quot;delete key ~p keyhash ~p from ~p~n&quot;, [Key, KeyHash, Leaf]),
   case lists:keytake(KeyHash, 1, Values) of
     {value, {KeyHash,Pointer,ValHash}, NewValues} -&gt;
       NewLeaf = Leaf#leaf{values=NewValues,m=length(NewValues)},
-      % ?infoFmt(&quot;new leaf ~p~n&quot;, [NewLeaf]),
+      ?infoFmt(&quot;new leaf ~p~n&quot;, [NewLeaf]),
       dmtree:delete_key(Pointer, Key, Tree),
       dmtree:write(NewLeaf, Tree);
     false -&gt; 
-      % ?infoFmt(&quot;couldnt find ~p in ~p~n&quot;, [KeyHash, Leaf]),
+      ?infoFmt(&quot;couldnt find ~p in ~p~n&quot;, [KeyHash, Leaf]),
       Leaf
   end.
 
 update_hash(Hash, Pointer, Node = #node{children=Children}, Tree) -&gt;
-  % ?infoFmt(&quot;updating hash,ptr ~p for ~p~n&quot;, [{Hash,Pointer}, Node]),
+  ?infoFmt(&quot;updating hash,ptr ~p for ~p~n&quot;, [{Hash,Pointer}, Node]),
   NewNode = Node#node{children=lists:keyreplace(Pointer, 2, Children, {Hash,Pointer})},
-  % ?infoFmt(&quot;updated node ~p~n&quot;, [NewNode]),
+  ?infoFmt(&quot;updated node ~p~n&quot;, [NewNode]),
   dmtree:write(NewNode, Tree).
 
 % delete_merge(FoundKey,
@@ -295,7 +295,7 @@ delete_merge(FoundKey, D,
              LeftLeaf = #leaf{values=LeftValues,m=LeftM},
              RightLeaf = #leaf{values=RightValues,m=RightM},
              Tree) when (LeftM+RightM) =&lt; D, PM == 1 -&gt;
-  % ?infoMsg(&quot;Replacing root merging leaves~n&quot;),
+  ?infoMsg(&quot;Replacing root merging leaves~n&quot;),
   dmtree:delete(Root#node.offset, Tree),
   dmtree:delete(RightLeaf#leaf.offset, Tree),
   NewLeaf = dmtree:write(LeftLeaf#leaf{m=LeftM+RightM,values=LeftValues++RightValues}, Tree),
@@ -308,12 +308,12 @@ delete_merge(FoundKey, D,
              LeftLeaf = #leaf{values=LeftValues,m=LeftM},
              RightLeaf = #leaf{values=RightValues,m=RightM},
              Tree) when (LeftM+RightM) =&lt; D, length(PKeys) == 1 -&gt;
-  % ?infoMsg(&quot;Replacing node merging leaves~n&quot;),
+  ?infoMsg(&quot;Replacing node merging leaves~n&quot;),
   dmtree:delete(Parent#node.offset, Tree),
   dmtree:delete(RightLeaf#leaf.offset, Tree),
   NewLeaf = dmtree:write(LeftLeaf#leaf{m=LeftM+RightM,values=LeftValues++RightValues}, Tree),
   NP = dmtree:write(SuperParent#node{children=lists:keyreplace(offset(Parent), 2, PChildren, {hash(NewLeaf),offset(NewLeaf)})}, Tree),
-  % ?infoFmt(&quot;replaced ~p in super parent ~p~n&quot;, [{hash(Parent),offset(Parent)}, NP]),
+  ?infoFmt(&quot;replaced ~p in super parent ~p~n&quot;, [{hash(Parent),offset(Parent)}, NP]),
   {wamp_wamp, NewLeaf};
   
 delete_merge(FoundKey, D,
@@ -323,16 +323,16 @@ delete_merge(FoundKey, D,
              RightLeaf = #leaf{values=RightValues,m=RightM}, 
              Tree) when (LeftM+RightM) =&lt; D -&gt;
   %we can merge within reqs gogogo
-  % ?infoMsg(&quot;Merging leaves~n&quot;),
+  ?infoMsg(&quot;Merging leaves~n&quot;),
   N = if
     FoundKey == last -&gt; length(PKeys);
     true -&gt; lib_misc:position(FoundKey, PKeys)
   end,
-  % ?infoFmt(&quot;FoundKey ~p~nPKeys ~p~nPChildren ~p~nN ~p~nLeftM ~p~nRightM ~p~nD ~p~n&quot;, [FoundKey, PKeys, PChildren, N, LeftM, RightM, D]),
+  ?infoFmt(&quot;FoundKey ~p~nPKeys ~p~nPChildren ~p~nN ~p~nLeftM ~p~nRightM ~p~nD ~p~n&quot;, [FoundKey, PKeys, PChildren, N, LeftM, RightM, D]),
   NP = dmtree:write(remove_nth(Parent, N), Tree),
   dmtree:write(LeftLeaf#leaf{m=LeftM+RightM,values=LeftValues++RightValues}, Tree),
   dmtree:delete(RightLeaf#leaf.offset, Tree),
-  % ?infoFmt(&quot;new parent: ~p~n&quot;, [NP]),
+  ?infoFmt(&quot;new parent: ~p~n&quot;, [NP]),
   { merge, NP};
   
 %merging nodes
@@ -342,7 +342,7 @@ delete_merge(FoundKey, D,
              LeftNode = #node{m=LeftM},
              RightNode = #node{m=RightM},
              Tree) when (LeftM+RightM) &lt; D, length(PKeys) == 1 -&gt;
-  % ?infoMsg(&quot;replacing root merging nodes~n&quot;),
+  ?infoMsg(&quot;replacing root merging nodes~n&quot;),
   NC = dmtree:write(merge_nodes(FoundKey, PKeys, LeftNode, RightNode), Tree),
   dmtree:delete(offset(Root), Tree),
   dmtree:delete(offset(RightNode), Tree),
@@ -355,14 +355,14 @@ delete_merge(FoundKey, D,
              LeftNode = #node{m=LeftM,keys=LeftKeys,children=LeftChildren},
              RightNode = #node{m=RightM,keys=RightKeys,children=RightChildren},
              Tree) when (LeftM+RightM) &lt; D, length(PKeys) == 1 -&gt;
-  % ?infoMsg(&quot;Replacing node merging nodes~n&quot;),
+  ?infoMsg(&quot;Replacing node merging nodes~n&quot;),
   dmtree:delete(offset(RightNode), Tree),
   dmtree:delete(offset(Parent), Tree),
   ParentPointer = offset(Parent),
   ParentHash = hash(Parent),
   NN = merge_nodes(FoundKey, PKeys, LeftNode, RightNode),
   NP = dmtree:write(SuperParent#node{children=lists:keyreplace(offset(Parent), 2, PChildren, {hash(NN),offset(NN)})}, Tree),
-  % ?infoFmt(&quot;NN: ~p~n&quot;, [NN]),
+  ?infoFmt(&quot;NN: ~p~n&quot;, [NN]),
   NewNode = dmtree:write(NN, Tree),
   {wamp_wamp, NewNode};
 
@@ -372,26 +372,26 @@ delete_merge(FoundKey, D,
              LeftNode = #node{keys=LeftKeys,children=LeftChildren,m=LM},
              RightNode = #node{keys=RightKeys,children=RightChildren,m=RM},
              Tree)  when (LM+RM) &lt; D -&gt;
-  % ?infoMsg(&quot;merging nodes~n&quot;),
+  ?infoMsg(&quot;merging nodes~n&quot;),
   N = if
     FoundKey == last -&gt; length(PKeys) -1;
     true -&gt; lib_misc:position(FoundKey, PKeys)
   end,
-  % ?infoFmt(&quot;FoundKey ~p~nPKeys ~p~nPChildren ~p~nN ~p~nLeftM ~p~nRightM ~p~nD ~p~n&quot;, [FoundKey, PKeys, PChildren, N, LM, RM, D]),
+  ?infoFmt(&quot;FoundKey ~p~nPKeys ~p~nPChildren ~p~nN ~p~nLeftM ~p~nRightM ~p~nD ~p~n&quot;, [FoundKey, PKeys, PChildren, N, LM, RM, D]),
   NP = dmtree:write(remove_nth(Parent, N), Tree),
   NC = dmtree:write(merge_nodes(FoundKey, PKeys, LeftNode, RightNode), Tree),
   dmtree:delete(RightNode#node.offset, Tree),
-  % ?infoFmt(&quot;new child: ~p~n&quot;, [NC]),
-  % ?infoFmt(&quot;new parent: ~p~n&quot;, [NP]),
+  ?infoFmt(&quot;new child: ~p~n&quot;, [NC]),
+  ?infoFmt(&quot;new parent: ~p~n&quot;, [NP]),
   {merge, NP};
   
 delete_merge(last, _, _, _, _, Right, Tree) -&gt;
-  % ?infoMsg(&quot;not merging~n&quot;),
+  ?infoMsg(&quot;not merging~n&quot;),
   {nothing, Right};
   
 delete_merge(_, _, _, _, Left, _, Tree) -&gt;
   %merged leaf is too large, do not merge
-  % ?infoMsg(&quot;not merging~n&quot;),
+  ?infoMsg(&quot;not merging~n&quot;),
   {nothing, Left}.
     
 merge_nodes(FoundKey, PKeys, LeftNode = #node{m=LeftM,keys=LeftKeys,children=LeftChildren}, RightNode = #node{m=RightM,keys=RightKeys,children=RightChildren}) -&gt;</diff>
      <filename>elibs/dmerkle.erl</filename>
    </modified>
    <modified>
      <diff>@@ -24,7 +24,7 @@
 -include(&quot;common.hrl&quot;).
 -include_lib(&quot;kernel/include/file.hrl&quot;).
 
--record(dmtree, {file, size=0, virtsize=0, d, blocksize, headersize=0, filename, ops=[], opdict=dict:new(), freepointer=0, rootpointer=0, kfpointers=[]}).
+-record(dmtree, {file, size=0, virtsize=0, d, blocksize, headersize=0, filename, ops=[], opdict=dict:new(), freepointer=0, rootpointer=0, kfpointers=[], bigkfpointer=0}).
 
 -ifdef(TEST).
 -include(&quot;etest/dmtree_test.erl&quot;).
@@ -143,8 +143,8 @@ handle_call(tx_rollback, _From, State = #dmtree{}) -&gt;
 handle_call(d, _From, State = #dmtree{d=D}) -&gt;
   {reply, D, State};
   
-handle_call(root, _From, State = #dmtree{rootpointer=Ptr}) -&gt;
-  {reply, int_read(Ptr, State), State};
+handle_call(root, _From, State = #dmtree{rootpointer=Ptr,blocksize=BlockSize}) -&gt;
+  {reply, int_read(Ptr, BlockSize, State), State};
   
 handle_call(block_size, _From, State = #dmtree{blocksize=BlockSize}) -&gt;
   {reply, BlockSize, State};
@@ -152,15 +152,15 @@ handle_call(block_size, _From, State = #dmtree{blocksize=BlockSize}) -&gt;
 handle_call({update_root, Node}, _From, State = #dmtree{}) -&gt;
   {reply, self(), write_header(State#dmtree{rootpointer=offset(Node)})};
   
-handle_call({write, Node}, _From, State = #dmtree{}) -&gt;
-  {N, T} = int_write(Node, State),
+handle_call({write, Node}, _From, State = #dmtree{blocksize=BlockSize}) -&gt;
+  {N, T} = int_write(Node, BlockSize, State),
   {reply, N, T};
   
 handle_call({delete, Offset}, _From, State = #dmtree{}) -&gt;
   {reply, self(), int_delete(Offset, State)};
   
-handle_call({read, Offset}, _From, State = #dmtree{}) -&gt;
-  {reply, int_read(Offset, State), State};
+handle_call({read, Offset}, _From, State = #dmtree{blocksize=BlockSize}) -&gt;
+  {reply, int_read(Offset, BlockSize, State), State};
   
 handle_call({read_key, Offset}, _From, State = #dmtree{}) -&gt;
   {reply, int_read_key(Offset, State), State};
@@ -237,21 +237,26 @@ read_header(File) -&gt;
     {error, Msg} -&gt; {error, Msg}
   end.
   
-int_read(0, Tree) -&gt;
+int_read(0, _, Tree) -&gt;
   {error, &quot;tried to read a node from the null pointer&quot;};
 
-int_read(Offset, #dmtree{file=File,d=D,blocksize=BlockSize}) -&gt;
+int_read(Offset, BlockSize, #dmtree{file=File,d=D}) -&gt;
     case file:pread(File, Offset, BlockSize) of
       {ok, Bin} -&gt; deserialize(Bin, D, Offset);
       eof -&gt; 
         error_logger:info_msg(&quot;hit an eof for offset ~p&quot;, [Offset]),
         undefined;
       {error, Reason} -&gt; 
-        error_logger:info_msg(&quot;error ~p at offset&quot;, [Reason, Offset]),
+        error_logger:info_msg(&quot;error ~p at offset ~p&quot;, [Reason, Offset]),
         undefined
     end.
   
-int_write(Node, Tree = #dmtree{file=File,blocksize=BlockSize}) -&gt;
+int_write(Node = #free{}, BlockSize, Tree = #dmtree{size=Size,file=File}) -&gt;
+  Offset = offset(Node),
+  {_, Tree2} = add_operation(Offset, serialize(Node, BlockSize), Tree),
+  {Node, Tree2};
+  
+int_write(Node, BlockSize, Tree = #dmtree{file=File}) -&gt;
   % ?infoFmt(&quot;int_write ~p~n&quot;, [Node]),
   Offset = offset(Node),
   Bin = serialize(Node, BlockSize),
@@ -260,49 +265,131 @@ int_write(Node, Tree = #dmtree{file=File,blocksize=BlockSize}) -&gt;
   {offset(Node, Offset3), Tree3}.
   
 int_delete(Offset, Tree = #dmtree{file=File,blocksize=BlockSize,freepointer=Pointer}) -&gt;
-  {_, Tree2} = int_write(#free{offset=Offset,pointer=Pointer}, Tree),
+  {_, Tree2} = int_write(#free{offset=Offset,pointer=Pointer}, BlockSize, Tree),
   write_header(Tree2#dmtree{freepointer=Offset}).
   
 %this gotta change at some point
-int_read_key(Offset, #dmtree{file=File}) -&gt;
-  file:position(File, Offset),
-  int_read_key(File, []);
-  
-int_read_key(Keys, [0 | Key]) -&gt;
-  K = lists:reverse(Key),
-  % ?infoFmt(&quot;int_read_key ~p~n&quot;, [K]),
-  K;
-
-int_read_key(Keys, Key) -&gt;
-  case file:read(Keys, 1) of
-    {ok, &lt;&lt;Char:8&gt;&gt;} -&gt; int_read_key(Keys, [Char|Key]);
-    Other -&gt; Other
+int_read_key(Offset, Tree = #dmtree{file=File,blocksize=BlockSize}) -&gt;
+  case file:pread(File, Offset, BlockSize) of
+    {ok, Bin} -&gt; 
+      case lib_misc:zero_split(Bin) of
+        {Key, _} -&gt; binary_to_list(Key);
+        _ -&gt; binary_to_list(Bin) ++ int_read_key(Offset+BlockSize, Tree)
+      end;
+    eof -&gt; eof;
+    {error, Reason} -&gt; {error, Reason}
   end.
   
-% int_write_key(eof, Key, Tree = #dmtree{blocksize=BlockSize}) when length(Key) &lt; BlockSize -&gt;
-%   
+int_write_key(eof, Key, Tree = #dmtree{size=Size,blocksize=BlockSize,kfpointers=Pointers}) when length(Key) &lt; BlockSize -&gt;
+  N = ?pointer_for_size(length(Key)+1, BlockSize),
+  % ?infoFmt(&quot;int_write_key ~p~nN ~p~nsize ~p~n&quot;, [Key, N, ?size_for_pointer(N)]),
+  case find_free_keypointer(?size_for_pointer(N), N, lists:nthtail(N-1, Pointers), Tree) of
+    not_found -&gt;
+      {Ptr, Tree2} = split_freespace(?size_for_pointer(N), BlockSize, Size, Tree),
+      % ?infoFmt(&quot;writing key to ~p~n tree~p~n&quot;, [Ptr, Tree2]),
+      add_operation(Ptr, [Key,0], Tree2);
+    {Ptr, Tree2} -&gt; add_operation(Ptr, [Key,0], Tree2)
+  end;
   
 int_write_key(Offset, Key, Tree) -&gt;
   add_operation(Offset, [Key,0], Tree).
   
-int_delete_key(Offset, Key, Tree = #dmtree{}) -&gt;
-  
-  Tree.
+int_delete_key(Offset, Key, Tree = #dmtree{blocksize=BlockSize,kfpointers=Pointers}) when length(Key) &lt; BlockSize -&gt;
+  FirstN = ?pointer_for_size(length(Key)+1, BlockSize),
+  % ?debugHere,
+  {N, Tree2} = merge_freespace(FirstN, ?size_for_pointer(FirstN), Offset, Tree),
+  % ?debugHere,
+  {_, Tree3} = int_write(#free{pointer=lists:nth(N, Pointers),offset=Offset}, ?size_for_pointer(N), Tree2),
+  % ?debugHere,
+  write_header(replace_kfpointer(N, Offset, Tree3)).
   
 %%--------------------------------
 %% ============SUPPORT FUNCTIONS
 %%--------------------------------
 flush(File, Ops) -&gt;
   file:pwrite(File, lists:reverse(Ops)).
+  
+find_free_keypointer(Size, N, [], Tree) -&gt;
+  % ?infoMsg(&quot;find_free_keypointer not found ~n&quot;),
+  not_found;
+  
+find_free_keypointer(Size, N, [0|Pointers], Tree) -&gt;
+  % ?infoFmt(&quot;find_free_keypointer Size ~p N ~p [0 | Pointers]~n&quot;, [Size, N]),
+  find_free_keypointer(Size, N+1, Pointers, Tree);
+
+find_free_keypointer(Size, N, [Ptr|Pointers], Tree) -&gt;
+  % ?infoFmt(&quot;find_free_keypointer found freespace Size ~p N ~p Ptr ~p~n&quot;, [Size, N, Ptr]),
+  Free = int_read(Ptr, Size, Tree),
+  % ?infoFmt(&quot;Free was ~p~n&quot;, Free),
+  {Ptr, Tree2} = split_freespace(Size, ?size_for_pointer(N), Ptr, Tree),
+  {Ptr, write_header(replace_kfpointer(N, Free#free.pointer, Tree2))}.
+  
+replace_kfpointer(N, Ptr, Tree = #dmtree{kfpointers=Pointers}) -&gt;
+  Tree#dmtree{kfpointers=lib_misc:nthreplace(N, Ptr, Pointers)}. 
+  
+merge_freespace(N, BlockSize, Offset, Tree = #dmtree{blocksize=BlockSize}) -&gt; 
+  % ?infoMsg(&quot;merge_freespace got whole block~n&quot;),
+  {N, Tree};
+
+merge_freespace(N, Size, Offset, Tree = #dmtree{file=File,blocksize=BlockSize,headersize=HeaderSize}) when Size &lt; BlockSize, ?block(Offset, HeaderSize, BlockSize) == ?block((Offset+Size), HeaderSize, BlockSize) -&gt;
+  % ?infoFmt(&quot;merge_freespace N ~p Size ~p Offset ~p~n&quot;, [N, Size, Offset]),
+  case file:pread(File, Offset+Size, Size) of
+    {ok, &lt;&lt;3:8, _/binary&gt;&gt;} -&gt; 
+      Tree2 = remove_free_pointer(Offset+Size, N, Tree),
+      merge_freespace(N+1, Size * 2, Offset, Tree2);
+    {ok, Bin} -&gt; {N, Tree};
+    eof -&gt; {N, Tree}
+  end;
+  
+merge_freespace(N, _, _, Tree) -&gt; {N, Tree}.
+  
+remove_free_pointer(Ptr, N, Tree = #dmtree{file=File,kfpointers=Pointers}) -&gt;
+  Head = lists:nth(N, Pointers),
+  Size = ?size_for_pointer(N),
+  Free = int_read(Head, Size, Tree),
+  ToReplace = int_read(Ptr, Size, Tree),
+  if
+    Head == Ptr -&gt; write_header(replace_kfpointer(N, ToReplace#free.pointer, Tree));
+    true -&gt; remove_free_pointer(Free, ToReplace, Size, Tree)
+  end.
+  
+remove_free_pointer(Free = #free{pointer=Ptr}, ToReplace = #free{offset=Ptr,pointer=Next}, Size, Tree = #dmtree{file=File}) -&gt;
+  {_, Tree2} = int_write(Free#free{pointer=Next}, Size, Tree),
+  Tree2;
+  
+remove_free_pointer(Free = #free{pointer=0}, _, _, Tree) -&gt; Tree;
+
+remove_free_pointer(Free = #free{pointer=Ptr}, ToReplace, Size, Tree = #dmtree{file=File}) -&gt;
+  remove_free_pointer(int_read(Ptr, Size, Tree), ToReplace, Size, Tree).
+  
+split_freespace(ReqSize, ReqSize, Ptr, Tree) -&gt;
+  {Ptr, Tree};
+  
+%this is ok because writing past the end fills with zeroes
+split_freespace(ReqSize, FreeSize, Ptr, Tree = #dmtree{file=File,blocksize=BlockSize,kfpointers=Pointers}) when FreeSize &gt; ReqSize -&gt;
+  % ?infoFmt(&quot;split_freespace reqsize ~p freesize ~p ptr ~p~n&quot;, [ReqSize, FreeSize, Ptr]),
+  N = ?pointer_for_size(FreeSize div 2, BlockSize),
+  NxtPtr = lists:nth(N, Pointers),
+  % ?infoFmt(&quot;split_freespace writing free cell of size ~p to ~p~n&quot;, [FreeSize div 2, Ptr+(FreeSize div 2)]),
+  {FreeNode, Tree2} = int_write(#free{pointer=NxtPtr,offset=Ptr+(FreeSize div 2)}, FreeSize div 2, Tree),
+  % ?infoFmt(&quot;file size after free write ~p~n&quot;, [Tree2#dmtree.size]),
+  FreePtr = offset(FreeNode),
+  Tree3 = write_header(replace_kfpointer(N, FreePtr, Tree2)),
+  split_freespace(ReqSize, FreeSize div 2, Ptr, Tree3).
 
 add_operation(eof, Bin, Tree = #dmtree{file=File,size=Size}) -&gt;
   BinSize = iolist_size(Bin),
   ok = file:pwrite(File, Size, Bin),
   {Size, Tree#dmtree{size=Size+BinSize}};
 
-add_operation(Offset, Bin, Tree = #dmtree{file=File}) -&gt;
+add_operation(Offset, Bin, Tree = #dmtree{file=File,size=Size}) -&gt;
+  BinSize = iolist_size(Bin),
   ok = file:pwrite(File, Offset, Bin),
-  {Offset, Tree}.
+  if
+    Offset == Size -&gt; {Offset, Tree#dmtree{size=Size+iolist_size(Bin)}};
+    Offset &gt; Size -&gt; {Offset, Tree#dmtree{size=Offset+iolist_size(Bin)}};
+    true -&gt; {Offset, Tree}
+  end.
 
 % add_operation(eof, Bin, Tree = #dmtree{size=Size,virtsize=VirtSize,ops=Ops,opdict=Dict}) -&gt;
 %   BinSize = true_size(Bin),
@@ -321,7 +408,7 @@ true_size(Bin) when is_binary(Bin) -&gt;
 true_size(_) -&gt; 1.
 
 create_or_read_root(Tree = #dmtree{file=File,blocksize=BlockSize,headersize=HeaderSize,rootpointer=0}) -&gt;
-  {Root, Tree2} = int_write(#leaf{offset=HeaderSize}, Tree),
+  {Root, Tree2} = int_write(#leaf{offset=HeaderSize}, BlockSize, Tree),
   % ?infoFmt(&quot;wrote root ~p~n&quot;, [Root]),
   write_header(Tree2#dmtree{rootpointer=offset(Root)});
   
@@ -330,27 +417,27 @@ create_or_read_root(Tree = #dmtree{file=File,blocksize=BlockSize,rootpointer=Ptr
 
 take_free_offset(eof, Tree = #dmtree{file=File,blocksize=BlockSize,freepointer=FreePtr}) when FreePtr &gt; 0 -&gt;
   Offset = FreePtr,
-  #free{pointer=NewFreePointer} = int_read(FreePtr, Tree),
+  #free{pointer=NewFreePointer} = int_read(FreePtr, BlockSize, Tree),
   {Offset, write_header(Tree#dmtree{freepointer=NewFreePointer})};
 
 take_free_offset(Offset, Tree) -&gt;
   {Offset, Tree}.
 
-serialize_header(#dmtree{blocksize=BlockSize, freepointer=FreePtr, rootpointer=RootPtr, kfpointers=Pointers}) -&gt;
-  Preamble = &lt;&lt;?VERSION:8, BlockSize:32, FreePtr:64, RootPtr:64&gt;&gt;,
+serialize_header(#dmtree{blocksize=BlockSize, freepointer=FreePtr, bigkfpointer=BKFPointer, rootpointer=RootPtr, kfpointers=Pointers}) -&gt;
+  Preamble = &lt;&lt;?VERSION:8, BlockSize:32, FreePtr:64, RootPtr:64, BKFPointer:64&gt;&gt;,
   FreeSpace = (?STATIC_HEADER - byte_size(Preamble))*8,
   PtrBin = &lt;&lt; &lt;&lt;Ptr:64&gt;&gt; || Ptr &lt;- Pointers &gt;&gt;,
   % ?infoFmt(&quot;pointers: ~p~nptrbin~p~nfreespace~p~n&quot;, [Pointers, PtrBin, FreeSpace]),
   &lt;&lt;Preamble/binary, PtrBin/binary, 0:FreeSpace&gt;&gt;.
 
 %this will try and match the current version, if it doesn't then we gotta punch out
-deserialize_header(&lt;&lt;?VERSION:8, BlockSize:32, FreePtr:64, RootPtr:64, Rest/binary&gt;&gt;) -&gt;
+deserialize_header(&lt;&lt;?VERSION:8, BlockSize:32, FreePtr:64, RootPtr:64, BKFPointer:64, Rest/binary&gt;&gt;) -&gt;
   PointerSize = ?pointers_from_blocksize(BlockSize),
   &lt;&lt;PBin:PointerSize/binary, _/binary&gt;&gt; = Rest,
   Pointers = [Ptr || &lt;&lt;Ptr:64&gt;&gt; &lt;= PBin],
   HeaderSize = ?headersize_from_blocksize(BlockSize),
   D = ?d_from_blocksize(BlockSize),
-  {ok, #dmtree{blocksize=BlockSize,d=D,headersize=HeaderSize,freepointer=FreePtr,rootpointer=RootPtr,kfpointers=Pointers}};
+  {ok, #dmtree{blocksize=BlockSize,d=D,headersize=HeaderSize,freepointer=FreePtr,rootpointer=RootPtr,kfpointers=Pointers, bigkfpointer=BKFPointer}};
 
 %hit the canopy
 deserialize_header(BinHeader) -&gt;</diff>
      <filename>elibs/dmtree.erl</filename>
    </modified>
    <modified>
      <diff>@@ -4,17 +4,31 @@
 -define(OFFSET_BASIS, 2166136261).
 -define(FNV_PRIME, 16777619).
 
--export([pmap/3, hash/1, nthdelete/2, rand_str/1, position/2, shuffle/1, floor/1, ceiling/1, time_to_epoch_int/1, time_to_epoch_float/1, now_int/0, now_float/0, byte_size/1, listify/1, reverse_bits/1]).
+-export([pmap/3, hash/1, nthdelete/2, zero_split/1, nthreplace/3, rand_str/1, position/2, shuffle/1, floor/1, ceiling/1, time_to_epoch_int/1, time_to_epoch_float/1, now_int/0, now_float/0, byte_size/1, listify/1, reverse_bits/1]).
 
 -ifdef(TEST).
 -include(&quot;etest/lib_misc_test.erl&quot;).
 -endif.
 
+zero_split(Bin) -&gt;
+  zero_split(0, Bin).
+
+zero_split(N, Bin) when N &gt; byte_size(Bin) -&gt; Bin;
+  
+zero_split(N, Bin) -&gt;
+  case Bin of
+    &lt;&lt;_:N/binary, 0:8, _/binary&gt;&gt; -&gt; split_binary(Bin, N);
+    _ -&gt; zero_split(N+1, Bin)
+  end.
+
 rand_str(N) -&gt;
   lists:map(fun(I) -&gt;
       random:uniform(26) + $a - 1
     end, lists:seq(1,N)).
 
+nthreplace(N, E, List) -&gt;
+  lists:sublist(List, N-1) ++ [E] ++ lists:nthtail(N, List).
+
 nthdelete(N, List) -&gt;
   nthdelete(N, List, []).
   </diff>
      <filename>elibs/lib_misc.erl</filename>
    </modified>
    <modified>
      <diff>@@ -205,6 +205,32 @@ live_test_() -&gt;
     KeyDiff = LeafDiff
   end}]}.
   
+insert_variable_keys_under_block_size_test() -&gt;
+  test_cleanup(),
+  {ok, Pid} = open(data_file(), 256),
+  Keys = lists:map(fun(N) -&gt;
+      lists:duplicate(N, $a)
+    end, lists:seq(1,255)),
+  lists:foreach(fun(Key) -&gt; 
+      update(Key, &quot;value&quot;, Pid)
+    end, Keys),
+  {LK, _} = lists:unzip(leaves(Pid)),
+  ?assertEqual(Keys, lists:sort(LK)),
+  close(Pid).
+  
+insert_variable_keys_over_a_block_size_test() -&gt;
+  test_cleanup(),
+  {ok, Pid} = open(data_file(), 256),
+  Keys = lists:map(fun(N) -&gt;
+      lists:duplicate(N, $a)
+    end, lists:seq(1,512)),
+  lists:foreach(fun(Key) -&gt; 
+      update(Key, &quot;value&quot;, Pid)
+    end, Keys),
+  {LK, _} = lists:unzip(leaves(Pid)),
+  ?assertEqual(Keys, lists:sort(LK)),
+  close(Pid).
+  
 simple_deletion_test() -&gt;
   test_cleanup(),
   {ok, Pid} = open(data_file(), 256),
@@ -308,6 +334,25 @@ partial_deletion_and_rebuild_test() -&gt;
   ?assertEqual(IdxSize, filelib:file_size(data_file())),
   close(Pid).
 
+partial_delete_and_rebuild_var_keysize_small_test() -&gt;
+  test_cleanup(),
+  {ok, Pid} = open(data_file(), 256),
+  Keys = lists:map(fun(N) -&gt;
+      lists:duplicate(N, $a)
+    end, lists:seq(1,255)),
+  lists:foreach(fun(Key) -&gt;
+      update(Key, &quot;value&quot;, Pid)
+    end, Keys),
+  Size = filelib:file_size(data_file()),
+  lists:foreach(fun(Key) -&gt;
+      delete(Key, Pid)
+    end, lists:sublist(Keys, 50)),
+  lists:foreach(fun(Key) -&gt;
+      update(Key, &quot;Value&quot;, Pid)
+    end, lists:sublist(Keys, 50)),
+  ?assertEqual(Size, filelib:file_size(data_file())),
+  close(Pid).
+
 open_and_insert_n(N) -&gt;
   test_cleanup(),
   {ok, Pid} = open(data_file(), 256),</diff>
      <filename>etest/dmerkle_test.erl</filename>
    </modified>
    <modified>
      <diff>@@ -57,3 +57,12 @@ leaf_round_trip_test() -&gt;
     offset=0
   },
   Leaf = deserialize(serialize(Leaf, 81), 4, 0).
+
+pointers_for_blocksize_test() -&gt;
+  ?assertEqual(5, ?pointers_from_blocksize(256)),
+  ?assertEqual(1, ?pointers_from_blocksize(16)).
+  
+size_for_pointer_test() -&gt;
+  ?assertEqual(16, ?size_for_pointer(1)),
+  ?assertEqual(256, ?size_for_pointer(5)).
+  </diff>
      <filename>etest/dmtree_test.erl</filename>
    </modified>
    <modified>
      <diff>@@ -22,4 +22,10 @@ nthdelete_test() -&gt;
   ?assertEqual([1,2,3,4,5], nthdelete(0, A)),
   ?assertEqual([1,2,3,4,5], nthdelete(6, A)),
   ?assertEqual([2,3,4,5], nthdelete(1, A)),
-  ?assertEqual([1,2,4,5], nthdelete(3, A)).
\ No newline at end of file
+  ?assertEqual([1,2,4,5], nthdelete(3, A)).
+  
+zero_split_test() -&gt;
+  ?assertEqual({&lt;&lt;&quot;&quot;&gt;&gt;, &lt;&lt;0,&quot;abcdefg&quot;&gt;&gt;}, zero_split(&lt;&lt;0, &quot;abcdefg&quot;&gt;&gt;)),
+  ?assertEqual({&lt;&lt;&quot;abd&quot;&gt;&gt;, &lt;&lt;0, &quot;efg&quot;&gt;&gt;}, zero_split(&lt;&lt;&quot;abd&quot;, 0, &quot;efg&quot;&gt;&gt;)),
+  ?assertEqual({&lt;&lt;&quot;abcdefg&quot;&gt;&gt;, &lt;&lt;0&gt;&gt;}, zero_split(&lt;&lt;&quot;abcdefg&quot;,0&gt;&gt;)),
+  ?assertEqual(&lt;&lt;&quot;abcdefg&quot;&gt;&gt;, zero_split(&lt;&lt;&quot;abcdefg&quot;&gt;&gt;)).
\ No newline at end of file</diff>
      <filename>etest/lib_misc_test.erl</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,13 @@
 -define(VERSION, 1).
--define(STATIC_HEADER, 85).
+-define(STATIC_HEADER, 93).
 
 -define(d_from_blocksize(BlockSize), trunc((BlockSize - 17)/16)).  
--define(pointers_from_blocksize(BlockSize), (trunc(math:sqrt(BlockSize)) - 4)).
+-define(pointers_from_blocksize(BlockSize), (lib_misc:ceiling(math:log(BlockSize)/math:log(2)) - 3)).
+-define(pointer_for_size(Size, BlockSize), (if Size =&lt; 16 -&gt; 1; Size =&lt; BlockSize -&gt; ?pointers_from_blocksize(Size); true -&gt; last end)).
+-define(size_for_pointer(N), (2 bsl (N+2))).
 -define(headersize_from_blocksize(BlockSize), (?STATIC_HEADER + ?pointers_from_blocksize(BlockSize) * 8)).
+-define(aligned(Ptr, HeaderSize, BlockSize), (((Ptr - (HeaderSize)) rem BlockSize) == 0)).
+-define(block(Ptr, HeaderSize, BlockSize), ((Ptr - (HeaderSize)) div BlockSize)).
 
 -record(node, {m=0, keys=[], children=[], offset=eof}).
 -record(leaf, {m=0, values=[], offset=eof}).</diff>
      <filename>include/dmerkle.hrl</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>72b77c3c81c55de4796acc5b8ca5e28343dfe61e</id>
    </parent>
  </parents>
  <author>
    <name>Cliff Moon</name>
    <email>cliff@moonpolysoft.com</email>
  </author>
  <url>http://github.com/cliffmoon/dynomite/commit/2ab74d4560ec89bda3d3a40a7ee1ea1f62d8f32f</url>
  <id>2ab74d4560ec89bda3d3a40a7ee1ea1f62d8f32f</id>
  <committed-date>2009-01-26T21:19:35-08:00</committed-date>
  <authored-date>2009-01-26T21:19:35-08:00</authored-date>
  <message>refactoring complete for now</message>
  <tree>f38b69e79453db3de4e0c3703982c4dc984d98c2</tree>
  <committer>
    <name>Cliff Moon</name>
    <email>cliff@moonpolysoft.com</email>
  </committer>
</commit>
