#include "persifs.h"
#include "inodelog.h"
#include "memsuperblob.h"
#include <list.h>

struct event
{
  inumber num;
  timestamp ts;
  timestamp batchTS;
  int batchNum;
  tailq_entry<event> link;
};

void setup();
void setup_after_superblob(ref<memSuperblob> blob);
void setup_after_chunkable(ref<superblob> blob, ref<chunkable> chunk);
void setup_after_marshal(ref<superblob> blob, chunkable::marshalled m);
void doBench(int bench, ref<superblob> blob, inode node);
void after_create(inode node, callback<void>::ref cb, ref<inodeLog> log);
void doBatch(inode node, ref<inodeLog> log, int i, callback<void>::ref next);
void putInode(inode node, ref<inodeLog> log,
              callback<void>::ref next);
void putInode_after_newInumber(inode node, ref<inodeLog> log,
                               callback<void>::ref next,
                               inumber num);
void putInode_after_put(inumber num, callback<void>::ref next,
                        timestamp ts);
void foreach(event *e, callback<void, event*, callback<void>::ref>::ref cb,
             callback<void>::ref done);
void foreach_next(event *e, callback<void, event*, callback<void>::ref>::ref cb,
                  callback<void>::ref done);
void doBatch_after_putInodes(ref<inodeLog> log, int i, callback<void>::ref next);
void readInode(ref<inodeLog> log, timestamp ts,
               event *e, callback<void>::ref next);
void readInode_after_get(callback<void>::ref next,
                         inode node);
void doBatch_after_readInodes(ref<inodeLog> log, int i, callback<void>::ref next);
void readPastInode(ref<inodeLog> log, int curBatch,
                   event *e, callback<void>::ref next);
void readPastInode_after_get(callback<void>::ref next,
                             inode node);
void doBatch_after_readPastInodes(ref<inodeLog> log, int i,
                                  callback<void>::ref next);
void readInodeAtTS(ref<inodeLog> log,
                   event *e, callback<void>::ref next);
void readInodeAtTS_after_get(ref<inodeLog> log, callback<void>::ref next,
                             inode node);
void doBatch_after_readRecentInodesRandomly(ref<inodeLog> log, int i,
                                            callback<void>::ref next);
void benchDone();
unsigned long blockTransfers(ref<inodeLog> log);

void addEvent(inumber num, timestamp ts);
void clearRecentEvents();
void clearAllEvents();

void iterate(int i, int end,
             callback<void, callback<void>::ref>::ref p,
             callback<void>::ref done);
void iterate_next(callback<void, callback<void>::ref>::ref p,
                  callback<void>::ref next);
void iterate2(int i, int end,
              callback<void, int, callback<void>::ref>::ref p,
              callback<void>::ref done);
void iterate2_next(int i,
                   callback<void, int, callback<void>::ref>::ref p,
                   callback<void>::ref next);


inline const strbuf &
strbuf_cat(const strbuf &sb, const double d)
{
  // This is just stupid.
  char buf[100];
  sprintf(buf, "%g", d);
  sb << buf;
  return sb;
}
