/* Copyright (C) 2014 InfiniDB, Inc.

   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; version 2 of
   the License.

   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; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   MA 02110-1301, USA. */

//  $Id: we_dbfileop.h 4726 2013-08-07 03:38:36Z bwilkinson $

/** @file */

#ifndef _WE_DBFILEOP_H_
#define _WE_DBFILEOP_H_

#include "we_type.h"
#include "we_fileop.h"
#include "we_blockop.h"
#include "we_cache.h"

#if defined(_MSC_VER) && defined(WRITEENGINE_DLLEXPORT)
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif

/** Namespace WriteEngine */
namespace WriteEngine
{
// forward reference
class ChunkManager;

/** Class DbFileOp */
class DbFileOp : public FileOp
{
 public:
  /**
   * @brief Constructor
   */
  EXPORT DbFileOp();

  /**
   * @brief Default Destructor
   */
  EXPORT virtual ~DbFileOp();

  EXPORT virtual int flushCache();

  /**
   * @brief Get an entry within a subblock
   */
  EXPORT void getSubBlockEntry(unsigned char* blockBuf, const int sbid, const int entryNo, const int width,
                               void* pStruct);

  /**
   * @brief Get an entry within a subblock using block information
   */
  void getSubBlockEntry(DataBlock* block, const int sbid, const int entryNo, const int width, void* pStruct)
  {
    getSubBlockEntry(block->data, sbid, entryNo, width, pStruct);
  }

  /**
   * @brief Read DB file to a buffer
   */
  EXPORT virtual int readDBFile(IDBDataFile* pFile, unsigned char* readBuf, const uint64_t lbid,
                                const bool isFbo = false);
  EXPORT int readDBFile(CommBlock& cb, unsigned char* readBuf, const uint64_t lbid);

  EXPORT int readDBFile(IDBDataFile* pFile, DataBlock* block, const uint64_t lbid, const bool isFbo = false);
  int readDBFile(CommBlock& cb, DataBlock* block, const uint64_t lbid)
  {
    return readDBFile(cb, block->data, lbid);
  }

  /**
   * @brief Get an entry within a subblock and also populate block buffer
   *
   */
  EXPORT int readSubBlockEntry(IDBDataFile* pFile, DataBlock* block, const uint64_t lbid, const int sbid,
                               const int entryNo, const int width, void* pStruct);

  EXPORT int readSubBlockEntry(CommBlock& cb, DataBlock* block, const uint64_t lbid, const int sbid,
                               const int entryNo, const int width, void* pStruct);

  /**
   * @brief Set an entry within a subblock
   */
  EXPORT void setSubBlockEntry(unsigned char* blockBuf, const int sbid, const int entryNo, const int width,
                               const void* pStruct);

  /**
   * @brief Set an entry within a subblock using block information
   */
  void setSubBlockEntry(DataBlock* block, const int sbid, const int entryNo, const int width,
                        const void* pStruct)
  {
    block->dirty = true;
    setSubBlockEntry(block->data, sbid, entryNo, width, pStruct);
  }

  /**
   * @brief Lbid Write a buffer to a DB file
   */
  EXPORT virtual int writeDBFile(IDBDataFile* pFile, const unsigned char* writeBuf, const uint64_t lbid,
                                 const int numOfBlock = 1);
  EXPORT int writeDBFile(CommBlock& cb, const unsigned char* writeBuf, const uint64_t lbid,
                         const int numOfBlock = 1);

  /**
   * @brief Write designated block(s) w/o writing to Version Buffer or cache.
   */
  EXPORT int writeDBFileNoVBCache(CommBlock& cb, const unsigned char* writeBuf, const int fbo,
                                  const int numOfBlock = 1);
  EXPORT virtual int writeDBFileNoVBCache(IDBDataFile* pFile, const unsigned char* writeBuf, const int fbo,
                                          const int numOfBlock = 1);

  int writeDBFile(IDBDataFile* pFile, DataBlock* block, const uint64_t lbid)
  {
    block->dirty = false;
    return writeDBFile(pFile, block->data, lbid);
  }
  int writeDBFile(CommBlock& cb, DataBlock* block, const uint64_t lbid)
  {
    return writeDBFile(cb, block->data, lbid);
  }

  EXPORT virtual int writeDBFileFbo(IDBDataFile* pFile, const unsigned char* writeBuf, const uint64_t fbo,
                                    const int numOfBlock);

  int writeDBFileNoVBCache(CommBlock& cb, DataBlock* block, const int fbo)
  {
    return writeDBFileNoVBCache(cb, block->data, fbo);
  }

  /**
   * @brief Write a sub block entry directly to a DB file
   */
  EXPORT int writeSubBlockEntry(IDBDataFile* pFile, DataBlock* block, const uint64_t lbid, const int sbid,
                                const int entryNo, const int width, void* pStruct);

  EXPORT int writeSubBlockEntry(CommBlock& cb, DataBlock* block, const uint64_t lbid, const int sbid,
                                const int entryNo, const int width, void* pStruct);

  /**
   * @brief Write to version buffer
   */
  EXPORT int writeVB(IDBDataFile* pFile, const OID oid, const uint64_t lbid);

  EXPORT virtual int readDbBlocks(IDBDataFile* pFile, unsigned char* readBuf, uint64_t fbo, size_t n);

  EXPORT virtual int restoreBlock(IDBDataFile* pFile, const unsigned char* writeBuf, uint64_t fbo);

  EXPORT virtual IDBDataFile* getFilePtr(const Column& column, bool useTmpSuffix);

  virtual void chunkManager(ChunkManager* ptr)
  {
    m_chunkManager = ptr;
  }
  virtual ChunkManager* chunkManager()
  {
    return m_chunkManager;
  }

 protected:
  ChunkManager* m_chunkManager;

 private:
};

}  // namespace WriteEngine

#undef EXPORT

#endif  // _WE_DBFILEOP_H_
