@chapsummary
IO and cache for boxm2 data structures.  
@endchapsummary

The @code{boxm2_io} sub library has been designed to simplify disk io when 
running @code{boxm2} algorithms.  

@section Disk IO
There are two methods of reading and writing blocks to disk, synchronous and 
asynchronous.  Synchronously reading and writing will block and wait for 
the read to finish, while asynchronous reading and writing will return 
immediately, and allow for processing on other data.  

@subsection Synchronous IO
The @code{boxm2_sio_mgr} provides synchronous reading and writing of @code{boxm2_block}s
and @code{boxm2_data_base}s, as well as @code{boxm2_data<T>}s.  The following static methods  
are implemented: 

@example
@itemize
@item boxm2_block* load_block(vcl_string dir, boxm2_block_id block_id)
@item boxm2_data_base* load_block_data_generic(vcl_string dir, boxm2_block_id id, vcl_string data_type);
@item boxm2_data<T>* load_block_data<T>(vcl_string dir, boxm2_block_id block_id)
@end itemize
@end example

as well as their writing counterparts:
@example
@itemize
@item void save_block(vcl_string dir, boxm2_block* block)
@item void save_block_data_base(vcl_string dir, boxm2_block_id block_id, boxm2_data_base* data, vcl_string prefix)
@item void save_block_data<T>(vcl_string dir, boxm2_block_id block_id, boxm2_data<T> * block_data )
@end itemize
@end example

@subsection Asynchronous IO
The asynchronous manager handles asynchronous requests, which take the form 
of @code{baio} objects (located in @code{src/contrib/brl/bbas/baio/}).  
These @code{baio} objects are implemented in a system-dependent manner.  Currently 
linux and windows @code{baio} objects have been implemented and tested.  The 
mac os x @code{baio} implementation remains untested.  


@section Boxm2 Cache
The pure virtual @code{boxm2_cache} class provides the following interface:

@example
  //: returns block pointer to block specified by ID
  virtual boxm2_block* get_block(boxm2_block_id id) = 0;

  //: returns data_base pointer
  virtual boxm2_data_base* get_data_base(boxm2_block_id, vcl_string type) = 0;

  //: returns data pointer to data specified by ID and data_type
  template <boxm2_data_type T>
  boxm2_data<T>* get_data(boxm2_block_id id);
@end example

Different realizations of this abstract class provide different methods of 
caching @code{boxm2_block}s and @code{boxm2_data_base}s.  Below is an example of
the nearest neighbor cache that we have implemented.  

@subsection Example: boxm2_nn_cache
The @code{boxm2_nn_cache} maintains two maps, one for @code{boxm2_block}s, and
a map of @code{boxm2_data_base}s.  It also maintains an asynchronous io 
manager.  When a call to @code{get_block} or @code{get_data_base} 
is made, the nearest neighbor cache loads any finished asynch requests, 
searches its cache for the appropriate block, updates its cache by sending out 
asynchronous requests for any missing neighbors, and then returns the block. 
The following is its @code{get_block} procedure:

@example
boxm2_block* boxm2_nn_cache::get_block(boxm2_block_id id)
{
  //first thing to do is to load all async requests into the cache
  this->finish_async_blocks();

  //then look for the block you're requesting
  if ( cached_blocks_.find(id) != cached_blocks_.end() )
  {
    //vcl_cout<<"CACHE HIT!"<<vcl_endl;
    this->update_block_cache(cached_blocks_[id]);
    return cached_blocks_[id];
  }

  //vcl_cout<<"Cache miss"<<vcl_endl;
  boxm2_block* loaded = boxm2_sio_mgr::load_block(scene_dir_, id);
  
  //if the block is null then initialize an empty one
  if(!loaded && scene_->block_exists(id)) {
    vcl_cout<<"boxm2_nn_cache::initializing empty block "<<id<<vcl_endl;
    boxm2_block_metadata data = scene_->get_block_metadata(id); 
    loaded = new boxm2_block(data);
  }
  
  this->update_block_cache(loaded);
  return loaded;
}
@end example
