<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -30,7 +30,7 @@
 -define(debugmsg(Message), noop).
 -define(debug(Message, Stuff), noop).
 -endif.
--record(xhash, {data,index,head,capacity,size,idx_cache}).
+-record(xhash, {data,index,head,capacity,size,idx_cache,node_cache}).
 -record(node, {key=nil, data=nil, node_header}).
 -record(node_header, {keyhash=0,keysize=0,datasize=0,nextptr=0}).
 
@@ -80,7 +80,7 @@ get(Key, XHash = #xhash{capacity=Capacity,data=Data,index=Index,size=Size,head=H
       if
         Pointer == 0 -&gt; {ok, not_found};
         true -&gt;
-          case find_node(Pointer, Key, KeyHash, Data) of
+          case find_node(Pointer, Key, KeyHash, XHash) of
             not_found -&gt; {ok, not_found};
             {NewPointer, Header} -&gt; 
               {Key, Context, Values} = read_node_data(NewPointer, Header, Data),
@@ -114,7 +114,7 @@ has_key(Key, XHash = #xhash{capacity=Capacity,data=Data}) -&gt;
   if
     Pointer == 0 -&gt; {ok, false};
     true -&gt;
-      case find_node(Pointer, Key, KeyHash, Data) of
+      case find_node(Pointer, Key, KeyHash, XHash) of
         not_found -&gt; {ok, false};
         {NewPointer, Header} -&gt; {ok, true}
       end
@@ -157,14 +157,14 @@ dump_index(Pointer, Bucket, List, XHash = #xhash{index=Index,capacity=Capacity})
 dump_data(XHash = #xhash{head=0}) -&gt; [];
   
 dump_data(XHash = #xhash{data=Data,head=Head}) -&gt;
-  Header = read_node_header(Head, Data),
+  Header = read_node_header(Head, XHash),
   dump_data(Head, Header, [], XHash).
   
 dump_data(LastPointer, LastHeader = #node_header{nextptr=0}, List, XHash) -&gt;
   lists:reverse([{node,LastHeader#node_header.keyhash,LastPointer,lib_misc:reverse_bits(LastHeader#node_header.keyhash)}|List]);
   
 dump_data(LastPtr, LastHeader = #node_header{nextptr=NextPointer}, List, XHash = #xhash{data=Data}) -&gt;
-  Header = read_node_header(NextPointer, Data),
+  Header = read_node_header(NextPointer, XHash),
   dump_data(NextPointer, Header, [{node,LastHeader#node_header.keyhash,LastPtr,lib_misc:reverse_bits(LastHeader#node_header.keyhash)}|List], XHash).
 
 interleave_dump(IndexList, DataList) -&gt;
@@ -180,17 +180,6 @@ interleave_dump(Results, IndexList, [{node,KH,Ptr,RevKey}|DataList]) -&gt;
   {LTE, GT} = lists:partition(fun({index,Bucket,Ptr,Hash}) -&gt; Hash =&lt; KH end, IndexList),
   interleave_dump([{node,KH,Ptr,RevKey},LTE|Results], GT, DataList).
 
-count_nodes_between(Start, End, Data) -&gt;
-  count_nodes_between(0, Start, End, Data).
-  
-count_nodes_between(Count, 0, _, _) -&gt; Count;
-  
-count_nodes_between(Count, End, End, Data) -&gt; Count;
-  
-count_nodes_between(Count, Start, End, Data) -&gt;
-  Header = read_node_header(Start, Data),
-  count_nodes_between(Count+1, Header#node_header.nextptr, End, Data).
-
 next_bucket(Bucket, Capacity, XHash) when Bucket == Capacity - 1 -&gt;
   eof;
 
@@ -203,7 +192,7 @@ next_bucket(Bucket, Capacity, XHash) -&gt;
 int_fold(Fun, 0, XHash, AccIn) -&gt; AccIn;
 
 int_fold(Fun, Pointer, XHash = #xhash{data=Data}, AccIn) -&gt;
-  NodeHeader = read_node_header(Pointer, Data),
+  NodeHeader = read_node_header(Pointer, XHash),
   if 
     NodeHeader#node_header.keysize == 0 -&gt; 
       int_fold(Fun, NodeHeader#node_header.nextptr, XHash, AccIn);
@@ -256,7 +245,7 @@ walk_to_initialize(0, Bucket, XHash = #xhash{}) -&gt;
 
 walk_to_initialize(Ptr, Bucket, XHash = #xhash{index=Index,data=Data}) -&gt;
   ?debug(&quot;walk_to_initialize(~w, ~w, XHash)&quot;, [Ptr, Bucket]),
-  Header = read_node_header(Ptr, Data),
+  Header = read_node_header(Ptr, XHash),
   walk_to_initialize(Ptr, Header, Bucket, XHash).
   
 walk_to_initialize(0, Header, Bucket, XHash) -&gt;
@@ -277,16 +266,16 @@ walk_to_initialize(Pointer, Header = #node_header{nextptr=Ptr,keyhash=KeyHash},
     UnrevHash rem Capacity == Bucket -&gt; {Pointer, write_bucket(Bucket, Pointer, XHash)};
     BucketHash &lt; KeyHash -&gt; {Pointer, write_bucket(Bucket, Pointer, XHash)};
     true -&gt;
-      NextHeader = read_node_header(Ptr, Data),
+      NextHeader = read_node_header(Ptr, XHash),
       walk_to_initialize(Ptr, NextHeader, Bucket, XHash)
   end.
   
 initialize_bucket(0, XHash = #xhash{index=Index,data=Data,head=0}) -&gt;
-  {ok, Pointer} = write_node_header(#node_header{}, eof, Data),
-  XHash1 = write_bucket(0, Pointer, XHash),
-  XHash2 = XHash#xhash{head=Pointer},
+  {ok, Pointer, XHash1} = write_node_header(#node_header{}, eof, XHash),
+  XHash2 = write_bucket(0, Pointer, XHash1),
+  XHash3 = XHash2#xhash{head=Pointer},
   write_head_pointer(Pointer, Data),
-  {Pointer, XHash2};
+  {Pointer, XHash3};
 
 initialize_bucket(0, XHash = #xhash{index=Index,data=Data}) -&gt;
   {read_pointer(0, XHash), XHash};
@@ -307,35 +296,35 @@ initialize_bucket(Bucket, XHash = #xhash{index=Index,data=Data}) -&gt;
 % the list is empty
 insert_node(Pointer, Header, KeyBin, DataBin, XHash = #xhash{data=Data,head=0}) -&gt;
   ?debug(&quot;insert_node(~w, ~w, KeyBin, DataBin, ~w) -&gt; empty list&quot;, [Pointer, Header, XHash]),
-  {ok, NewPointer} = write_node_header(Header, eof, Data),
+  {ok, NewPointer, XHash1} = write_node_header(Header, eof, XHash),
   ok = write_node_data(KeyBin, DataBin, eof, Data),
-  XHash1 = increment_size(Header, XHash),
+  XHash2 = increment_size(Header, XHash1),
   write_head_pointer(NewPointer,Data),
-  XHash2 = write_bucket(0, NewPointer, XHash1),
-  {NewPointer, XHash2#xhash{head=NewPointer}, 0};
+  XHash3 = write_bucket(0, NewPointer, XHash2),
+  {NewPointer, XHash3#xhash{head=NewPointer}, 0};
 
 insert_node(0, Header, KeyBin, DataBin, XHash) -&gt;
   insert_node(0, nil, Header, KeyBin, DataBin, XHash, 0);
 
 insert_node(Pointer, Header, KeyBin, DataBin, XHash = #xhash{index=Index,data=Data}) -&gt;
-  ReadHeader = read_node_header(Pointer, Data),
+  ReadHeader = read_node_header(Pointer, XHash),
   insert_node(Pointer, ReadHeader, Header, KeyBin, DataBin, XHash, 0).
   
 insert_node(Pointer, LastHeader = #node_header{keyhash=LastKH}, Header = #node_header{keyhash=KeyHash}, KeyBin, DataBin, XHash = #xhash{index=Index,data=Data,size=Size,head=Pointer}, Depth) when KeyHash =&lt; LastKH -&gt;
   ?debug(&quot;insert_node(~w, ~w, ~w, KeyBin, DataBin, XHash, ~w) -&gt; start of the list&quot;, [Pointer, LastHeader, Header, Depth]),
-  {ok, NewPointer} = write_node_header(Header#node_header{nextptr=Pointer}, eof, Data),
+  {ok, NewPointer, XHash1} = write_node_header(Header#node_header{nextptr=Pointer}, eof, XHash),
   ok = write_node_data(KeyBin, DataBin, eof, Data),
   write_head_pointer(NewPointer, Data),
-  XHash1 = write_bucket(0, NewPointer, XHash),
-  {NewPointer, increment_size(Header, XHash1#xhash{head=NewPointer}), Depth};
+  XHash2 = write_bucket(0, NewPointer, XHash1),
+  {NewPointer, increment_size(Header, XHash2#xhash{head=NewPointer}), Depth};
   
 insert_node(0, nil, Header = #node_header{keyhash=KeyHash}, KeyBin, DataBin, XHash = #xhash{index=Index,data=Data,size=Size,head=Pointer}, Depth) -&gt;
   ?debug(&quot;insert_node(~w, ~w, ~w, KeyBin, DataBin, XHash, ~w) -&gt; start of the list&quot;, [0, nil, Header, Depth]),
-  {ok, NewPointer} = write_node_header(Header#node_header{nextptr=Pointer}, eof, Data),
+  {ok, NewPointer, XHash1} = write_node_header(Header#node_header{nextptr=Pointer}, eof, XHash),
   ok = write_node_data(KeyBin, DataBin, eof, Data),
   write_head_pointer(NewPointer, Data),
-  XHash1 = write_bucket(0, NewPointer, XHash),
-  {NewPointer, increment_size(Header, XHash1#xhash{head=NewPointer}), Depth};
+  XHash2 = write_bucket(0, NewPointer, XHash1),
+  {NewPointer, increment_size(Header, XHash2#xhash{head=NewPointer}), Depth};
   
 insert_node(Pointer, LastHeader = #node_header{keyhash=LastKH}, Header = #node_header{keyhash=KeyHash}, KeyBin, DataBin, XHash = #xhash{index=Index,data=Data}, Depth) when KeyHash =&lt; LastKH -&gt;
   ?debug(&quot;insert_node(~w, ~w, ~w, KeyBin, DataBin, XHash) -&gt; before bucket&quot;, [Pointer, LastHeader, Header]),
@@ -343,24 +332,24 @@ insert_node(Pointer, LastHeader = #node_header{keyhash=LastKH}, Header = #node_h
   
 insert_node(Pointer, LastHeader = #node_header{nextptr=0}, Header = #node_header{}, KeyBin, DataBin, XHash = #xhash{index=Index,data=Data,size=Size}, Depth) -&gt;
   ?debug(&quot;insert_node(~w, ~w, ~w, KeyBin, DataBin, XHash, ~w) -&gt; end of the list&quot;, [Pointer, LastHeader, Header, Depth]),
-  {ok, NewPointer} = write_node_header(Header#node_header{}, eof, Data),
+  {ok, NewPointer, XHash1} = write_node_header(Header#node_header{}, eof, XHash),
   ok = write_node_data(KeyBin, DataBin, eof, Data),
-  {ok, _} = write_node_header(LastHeader#node_header{nextptr=NewPointer}, Pointer, Data),
-  XHash1 = increment_size(Header, XHash),
-  {NewPointer, XHash1, Depth};
+  {ok, _, XHash2} = write_node_header(LastHeader#node_header{nextptr=NewPointer}, Pointer, XHash1),
+  XHash3 = increment_size(Header, XHash2),
+  {NewPointer, XHash3, Depth};
   
 insert_node(Pointer, LastHeader, Header = #node_header{keyhash=KeyHash}, KeyBin, DataBin, XHash = #xhash{index=Index,data=Data,size=Size,capacity=Capacity}, Depth) -&gt;
   ?debug(&quot;insert_node(~w, ~w, ~w, KeyBin, DataBin, XHash, ~w)&quot;, [Pointer, LastHeader, Header, Depth]),
-  NextHeader = read_node_header(LastHeader#node_header.nextptr, Data),
+  NextHeader = read_node_header(LastHeader#node_header.nextptr, XHash),
   UnrevHash = lib_misc:reverse_bits(LastHeader#node_header.keyhash),
   if
     KeyHash =&lt; NextHeader#node_header.keyhash -&gt;
-      {ok, NewPointer} = write_node_header(Header#node_header{nextptr=LastHeader#node_header.nextptr}, eof, Data),
+      {ok, NewPointer, XHash1} = write_node_header(Header#node_header{nextptr=LastHeader#node_header.nextptr}, eof, XHash),
       ok = write_node_data(KeyBin, DataBin, eof, Data),
-      {ok, _} = write_node_header(LastHeader#node_header{nextptr=NewPointer}, Pointer, Data),
+      {ok, _, XHash2} = write_node_header(LastHeader#node_header{nextptr=NewPointer}, Pointer, XHash1),
       % {ok, _} = write_node_header(NextHeader#node_header{lastptr=NewPointer}, Pointer, Data),
-      XHash1 = increment_size(Header, XHash),
-      {NewPointer, XHash1, Depth+1};
+      XHash3 = increment_size(Header, XHash2),
+      {NewPointer, XHash3, Depth+1};
     true -&gt; insert_node(LastHeader#node_header.nextptr, NextHeader, Header, KeyBin, DataBin, XHash, Depth+1)
   end.
 
@@ -370,26 +359,27 @@ read_node_data(Pointer, #node_header{keysize=KeySize,datasize=DataSize}, Data) -
   {Context, Values} = binary_to_term(DataBin),
   {Key, Context, Values}.
 
-find_node(0, Key, KeyHash, Data) -&gt;
+find_node(0, Key, KeyHash, _) -&gt;
   not_found;
 
-find_node(Pointer, Key, KeyHash, Data) -&gt;
-  Header = read_node_header(Pointer, Data),
+find_node(Pointer, Key, KeyHash, XHash) -&gt;
+  Header = read_node_header(Pointer, XHash),
   ?debug(&quot;find_node(~p, ~p, ~p, Data, _) -&gt; ~p&quot;, [Pointer, Key, KeyHash, Header#node_header.keyhash]),
   if
     KeyHash == Header#node_header.keyhash -&gt; {Pointer, Header};
-    KeyHash &gt; Header#node_header.keyhash -&gt; find_node(Header#node_header.nextptr, Key, KeyHash, Data);
+    KeyHash &gt; Header#node_header.keyhash -&gt; find_node(Header#node_header.nextptr, Key, KeyHash, XHash);
     true -&gt; not_found
   end.
 
-write_node_header(Header, eof, Data) -&gt;
+write_node_header(Header, eof, XHash = #xhash{data=Data}) -&gt;
   {ok, Pointer} = file:position(Data, eof),
-  write_node_header(Header, Pointer, Data);
+  write_node_header(Header, Pointer, XHash);
 
-write_node_header(Header = #node_header{keyhash=KeyHash,nextptr=NextPointer,keysize=KeySize,datasize=DataSize}, Pointer, Data) -&gt;
+write_node_header(Header = #node_header{keyhash=KeyHash,nextptr=NextPointer,keysize=KeySize,datasize=DataSize}, Pointer, XHash = #xhash{data=Data}) -&gt;
+  XHash1 = node_cache_set(Pointer, Header, XHash),
   ?debug(&quot;write_node_header(~p,~p,Data)&quot;, [Header, Pointer]),
   ok = file:pwrite(Data, Pointer, &lt;&lt;KeyHash:32, NextPointer:64, KeySize:16, DataSize:32&gt;&gt;),
-  {ok, Pointer}.
+  {ok, Pointer, XHash1}.
   
 write_node_data(KeyBin, DataBin, Pointer, Data) -&gt;
   file:position(Data, Pointer),
@@ -398,16 +388,20 @@ write_node_data(KeyBin, DataBin, Pointer, Data) -&gt;
 read_node_header(0, Data) -&gt;
   nil;
 
-read_node_header(Pointer, Data) -&gt;
-  {ok, &lt;&lt;KeyHash:32/integer, NextPointer:64/integer, KeySize:16/integer, DataSize:32/integer&gt;&gt;} = file:pread(Data, Pointer, 18),
-  Header = #node_header{keyhash=KeyHash,nextptr=NextPointer,keysize=KeySize,datasize=DataSize},
+read_node_header(Pointer, XHash = #xhash{data=Data}) -&gt;
+  Header = case node_cache_get(Pointer, XHash) of
+    not_found -&gt; 
+      {ok, &lt;&lt;KeyHash:32/integer, NextPointer:64/integer, KeySize:16/integer, DataSize:32/integer&gt;&gt;} = file:pread(Data, Pointer, 18),
+      #node_header{keyhash=KeyHash,nextptr=NextPointer,keysize=KeySize,datasize=DataSize};
+    Val -&gt; Val
+  end,
   ?debug(&quot;read_node_header(~p, Data) -&gt; ~p&quot;, [Pointer, Header]),
   Header.
 
 find_start(0, XHash = #xhash{data=Data}) -&gt;
   ?debugmsg(&quot;find_start(0, XHash)&quot;),
   Pointer = read_pointer(0, XHash),
-  Header = read_node_header(Pointer, Data),
+  Header = read_node_header(Pointer, XHash),
   {Pointer, Header, false};
   
 find_start(Bucket, XHash = #xhash{}) -&gt;
@@ -417,7 +411,7 @@ find_start(Bucket, XHash = #xhash{data=Data}, IsParent) -&gt;
   ?debug(&quot;find_start(~w, XHash)&quot;, [Bucket]),
   case read_pointer(Bucket, XHash) of
     0 -&gt; find_start(?PARENT(Bucket), XHash, true);
-    Pointer -&gt; {Pointer, read_node_header(Pointer,Data), IsParent}
+    Pointer -&gt; {Pointer, read_node_header(Pointer,XHash), IsParent}
   end.
 
 read_bucket(0, XHash) -&gt;
@@ -449,6 +443,15 @@ read_pointer(Bucket, XHash = #xhash{index=Index}) -&gt;
     Pointer -&gt; Pointer
   end.
     
+node_cache_get(Pointer, XHash = #xhash{node_cache=Cache}) -&gt;
+  case dict:find(Pointer, Cache) of
+    {ok, Header} -&gt; Header;
+    error -&gt; not_found
+  end.
+  
+node_cache_set(Pointer, Header, XHash = #xhash{node_cache=Cache}) -&gt;
+  XHash#xhash{node_cache=dict:store(Pointer, Header, Cache)}.
+    
 index_cache_get(Bucket, XHash = #xhash{idx_cache=Cache,index=Index}) -&gt;
   N = (Bucket * 8) div ?CHUNK_SIZE,
   BytePos = (Bucket * 8) rem ?CHUNK_SIZE,
@@ -533,13 +536,13 @@ initialize(Hash = #xhash{data=Data,index=Index}) -&gt;
   case file:pwrite(Data, 0, &lt;&lt;&quot;XD&quot;, ?VERSION:16, Size:32, Head:64, 0:256&gt;&gt;) of
     ok -&gt;
       case file:pwrite(Index, 0, &lt;&lt;&quot;XI&quot;, ?VERSION:16, Capacity:32, 0:256, 0:TableSize&gt;&gt;) of
-        ok -&gt; {ok, init_cache(Hash#xhash{head=Head,capacity=Capacity,size=Size})};
+        ok -&gt; {ok, init_node_cache(init_index_cache(Hash#xhash{head=Head,capacity=Capacity,size=Size}))};
         Failure -&gt; Failure
       end;
     Failure -&gt; Failure
   end.
 
-init_cache(XHash = #xhash{capacity=Capacity,index=Index}) -&gt;
+init_index_cache(XHash = #xhash{capacity=Capacity,index=Index}) -&gt;
   Dict = dict:new(),
   Dict1 = lists:foldl(fun(N, D) -&gt;
       Chunk = N * ?CHUNK_SIZE,
@@ -553,4 +556,7 @@ init_cache(XHash = #xhash{capacity=Capacity,index=Index}) -&gt;
       end
     end, Dict, lists:seq(0,?MAX_CHUNKS-1)),
   XHash#xhash{idx_cache=Dict1}.
-  
\ No newline at end of file
+  
+init_node_cache(XHash) -&gt;
+  Dict = dict:new(),
+  XHash#xhash{node_cache=Dict}.
\ No newline at end of file</diff>
      <filename>elibs/xhash_storage.erl</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>a25009c05a0fedc99ea38efd31df55acf68c595c</id>
    </parent>
  </parents>
  <author>
    <name>Cliff Moon</name>
    <email>cliff@moonpolysoft.com</email>
  </author>
  <url>http://github.com/cliffmoon/dynomite/commit/09869eb77c5fbb8f1548430817e232fc838dc440</url>
  <id>09869eb77c5fbb8f1548430817e232fc838dc440</id>
  <committed-date>2008-11-26T10:04:28-08:00</committed-date>
  <authored-date>2008-11-26T10:04:28-08:00</authored-date>
  <message>node header cache</message>
  <tree>acbb2bf559500ab0e0dd0a12f39e72a0e59db58d</tree>
  <committer>
    <name>Cliff Moon</name>
    <email>cliff@moonpolysoft.com</email>
  </committer>
</commit>
