/* Pepito v1.59  -- file: btree.h --
   Copyright (c) 2000-01 Carlos del Cacho

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYING.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.

   Contact the author: guggenjaimito@yahoo.com
*/

#ifndef BTREE_H
#define BTREE_H
#include "skipl.h"

typedef char int8;
typedef unsigned char uint8;

typedef short int16;
typedef unsigned short uint16;

typedef int int32;
typedef unsigned int uint32;

#ifdef LINUX

    typedef long long int64;
    typedef unsigned long long uint64;

#   define PACKED __attribute__ ((packed))

#else

    typedef __int64 int64;
    typedef unsigned __int64 uint64;

#   define PACKED

#endif


typedef uint32 offset_t;

#ifndef LINUX
#pragma pack(push, old_alignment)
#pragma pack(1)
#endif

typedef struct {

    uint32 version;
    uint8  file_type;
    uint8  key_size;
    uint32 data_size;
    uint32 nentries;
    uint32 page_size;
    offset_t root_off;
    offset_t file_size;

} file_header PACKED;


typedef struct {

    offset_t data_off;
    uint32 nentries;
    uint8 is_leaf;

} page_header PACKED;


#ifndef LINUX
#pragma pack(pop, old_alignment)
#endif

typedef struct {

    page_header info;
    void *keys;
    offset_t *childs;
    offset_t *data_off;
    offset_t *data_size;
    offset_t page_off;
} db_page;

typedef struct {

    db_page *page;
    uint8 dirty;

} cache_entry;


//-------------------------------
typedef struct file_run_struct{

  char *fname;
  FILE *fp;
  uint8 *buffer, *pbuffer;
  uint32 nbuffer;
  struct file_run_struct *next, *prev;

} file_run;

//-------------------------------
typedef struct {

    int nruns;
    int key_size;
    int data_size;
    skip_list buffer;
    sl_entry *last_written;
    file_run *current_run;

} bulk_load_info;
//-------------------------------
typedef struct {

    file_header fheader;
    FILE *fp, *fdata;
    offset_t data_off;
    uint32 cache_pipe_size;
    uint32 npipes;
    cache_entry **cache;
    skip_list data_cache;
    bulk_load_info bload;

} db_handle;


//-----------------------------------------------------------------

unsigned long FileSize(char *fname);

db_handle *CreateDatabase(char *file,
                          int key_size,
                          int data_size,
                          int cache_size
                         );

db_handle *OpenDatabase(char *file,
                        int cache_size
                       );

void CloseDatabase(db_handle *dbh);

db_page *AllocPage(db_handle *dbh);

void FreePage(db_page *p);

void LoadPage (db_handle    *dbh,
               db_page      *p,
               uint32       offset);

void FillPage (db_handle    *dbh,
               db_page      *p,
               int          key_size,
               void         *keys,
               offset_t     *data_off,
               offset_t     *data_size,
               int          nkeys,
               offset_t     *childs);

void ClonePage (db_handle    *dbh,
                db_page      *dst,
                db_page      *src);

uint32 BinarySearch (db_page      *p,
                     uint32       page_size,
                     void         *key,
                     int32        key_size);

offset_t SeekEntry(db_handle    *dbh,
                   void         *key,
                   void *data);

void DataBufferInsert(db_handle *dbh,
                      offset_t data_off,
                      void *data,
                      int data_size);

void DataBufferFlush(db_handle *dbh);

offset_t InsertEntry(db_handle  *dbh,
                     void       *key,
                     void       *data,
                     uint32     data_size,
                     void       (*pfun)(void *, int, void *, int)
                     );

offset_t DeleteEntry(db_handle  *dbh,
                     void       *key);

void StorePage(db_handle  *dbh,
               db_page    *p);

void WritePageToDisk(db_handle  *dbh,
                     db_page    *p);

void PrintTreeStats(db_handle *dbh);

void PrintInPreOrder(db_handle *dbh,
                     db_page *p);

void InitCache(db_handle *dbh,
               int cache_size,
               int npipes
              );

void CloseCache(db_handle *dbh);

file_run *AllocNewRun(bulk_load_info *info,
                      int nrun
                     );

void FreeRun(file_run *fr);

int InitBulkLoad(bulk_load_info *info,
                 int key_size
                );

void CloseCurrentRun(bulk_load_info *info,
                     int alloc_new
                    );

int MergeTempFiles(bulk_load_info *info,
                   void (*pfun)(void *, int, void *, int),
                   int (*confirm_pfun)(void *data, int data_size)
                  );

offset_t GenerateRun(bulk_load_info *info,
                     void       *key,
                     void       *data,
                     uint32     data_size,
                     void       (*pfun)(void *, int, void *, int)
                    );

int BulkLoadTree(db_handle *dbh,
                 char *fname
                );

offset_t GenerateSubTreeNonRoot(db_handle *dbh,
                                FILE *fp,
                                unsigned int num_ele,
                                unsigned int height
                               );
#endif
