#include "persifs.h"
#include "diskblobindex.h"

#define DEBUG 0

const unsigned long BRANCHING_FACTOR = 16;

void
diskBlobIndex::create(str filename,
                      callback<void, ref<diskBlobIndex> >::ref cb,
                      cbe error)
{
  BPlusTree<blockFingerprint, blockAddress>::create(
    filename,
    BRANCHING_FACTOR,
    wrap(create_after_bptreeCreate, cb, error), error);
}

void
diskBlobIndex::create_after_bptreeCreate(
  callback<void, ref<diskBlobIndex> >::ref cb,
  cbe error,
  ref<BPlusTree<blockFingerprint, blockAddress> > bpt)
{
  cb(New refcounted<diskBlobIndex>(bpt));  
}


void
diskBlobIndex::get(blockFingerprint fp,
                   callback<void, blockAddress>::ref cb,
                   cbe error)
{
  entries->search(fp,
                  wrap(this, &diskBlobIndex::get_after_search, fp, cb, error),
                  wrap(this, &diskBlobIndex::get_after_error, fp, cb, error));
}

void
diskBlobIndex::get_after_search(blockFingerprint fp,
                                callback<void, blockAddress>::ref cb,
                                cbe error,
                                blockFingerprint k, blockAddress v)
  
{
  if (k != fp) {
    fatal << "BPlusTree search returned wrong key: expected " << fp
          << " got " << k << "\n";
  }

#if DEBUG
    warn << "diskBlobIndex: get: fp=" << fp << " addr=" << *a << "\n";
#endif

  cb(v);
}

void
diskBlobIndex::get_after_error(blockFingerprint fp,
                               callback<void, blockAddress>::ref cb,
                               cbe error, pStat stat)
{
  if (stat == PERR_NOENT) {
#if DEBUG
    warn << "diskBlobIndex: get: fp=" << fp << " not in index\n";
#endif
    cb(0);
  } else {
    error(stat);
  }
}

                          
void
diskBlobIndex::put(blockFingerprint fp, blockAddress addr,
                  callback<void>::ref cb, cbe error)
{
// XXX Should really implement this check.
//   if (entries[fp] != NULL) {
// #if DEBUG
//     warn << "diskBlobIndex: attempted put: fp=" << fp << ", addr=" << addr
//          << "but already exists\n";
// #endif
//     error(PERR_EXISTS);
//   } else {

  entries->insert(fp, addr);
#if DEBUG    
    warn << "diskBlobIndex: put: fp=" << fp << ", addr=" << addr << "\n";
#endif

  cb();
}


diskBlobIndex::~diskBlobIndex()
{
}


diskBlobIndex::diskBlobIndex(ref<BPlusTree<blockFingerprint,
                                           blockAddress> > bpt)
  : entries(bpt)
{
}
 
