/**
 * Arborescent inode log implementation
 *
 * This implements the inode log interface on top of the persistified
 * B-tree implementation.
 */

#ifndef ARBORESCENTINODELOG_H
#define ARBORESCENTINODELOG_H

#include "inodelog.h"
#include "persibplustree.h"
#include "bplustree.h"

/**
 * The default branching for the inode map
 */
static const unsigned long IMAP_BRANCHT = 1024;

class arborescentInodeLog : public inodeLog
{
private:
  typedef PersiBPlusTree<inumber, inode> imapTree;
  typedef BPlusTree<timestamp, treeTimestamp> tmapTree;
  inumber nextInumber;

public:
  /**
   * Create an empty inode log if filename does not exist.  Otherwise,
   * use the file in filename for the inode log.  This is a factory
   * function.
   */
  static void create(str imapfilename, str imapRootMapFilename,
                     unsigned long imapCacheSize, str tmapfilename,
                     callback<void, ref<inodeLog> >::ref cb, cbe error,
                     unsigned long branchT = IMAP_BRANCHT);

  void put(inode node,
           callback<void, timestamp>::ref cb, cbe error);
  void del(inumber num,
           callback<void, timestamp>::ref cb, cbe error);
  void get(timestamp ts, inumber num,
           callback<void, inode>::ref cb, cbe error);
  void newInumber(callback<void, inumber>::ref cb, cbe error);
  void setRootInumber(inumber num, callback<void>::ref cb, cbe error);
  void getRootInumber(callback<void, inumber>::ref cb, cbe error);
  unsigned long blockTransfers();
  void resetBlockTransfers();
  
protected:
  arborescentInodeLog(ref<imapTree> imap, ref<tmapTree> tmap);
  ~arborescentInodeLog();

  static
  void create_after_imap(str tmapfilename,
                         callback<void, ref<inodeLog> >::ref cb, cbe error,
                         ref<imapTree> imap);
  static
  void create_after_tmap(ref<imapTree> imap,
                         callback<void, ref<inodeLog> >::ref cb, cbe error,
                         ref<tmapTree> tmap);
  
private:
  ref<imapTree> imap;
  ref<tmapTree> tmap;

  void get_after_tmap(inumber num,
                      callback<void, inode>::ref cb, cbe error,
                      timestamp realTS, treeTimestamp treeTS);
  void get_after_imap(inumber realNum,
                      callback<void, inode>::ref cb, cbe error,
                      inumber num, inode node);
};

#endif // ARBORESCENTINODELOG_H
