/* ***************************************************************** *
 * Copyright 1998 International Business Machines Corporation. All   *
 * Rights Reserved.                                                  *
 *                                                                   *
 * Please read this carefully.  Your use of this reference           *
 * implementation of certain of the IETF public-key infrastructure   *
 * specifications ("Software") indicates your acceptance of the      *
 * following.  If you do not agree to the following, do not install  *
 * or use any of the Software.                                       *
 *                                                                   *
 * Permission to use, reproduce, distribute and create derivative    *
 * works from the Software ("Software Derivative Works"), and to     *
 * distribute such Software Derivative Works is hereby granted to    *
 * you by International Business Machines Corporation ("IBM").  This *
 * permission includes a license under the patents of IBM that are   *
 * necessarily infringed by your use of the Software as provided by  *
 * IBM.                                                              *
 *                                                                   *
 * IBM licenses the Software to you on an "AS IS" basis, without     *
 * warranty of any kind.  IBM HEREBY EXPRESSLY DISCLAIMS ALL         *
 * WARRANTIES OR CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING,   *
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OR CONDITIONS OF       *
 * MERCHANTABILITY, NON INFRINGEMENT AND FITNESS FOR A PARTICULAR    *
 * PURPOSE.  You are solely responsible for determining the          *
 * appropriateness of using this Software and assume all risks       *
 * associated with the use of this Software, including but not       *
 * limited to the risks of program errors, damage to or loss of      *
 * data, programs or equipment, and unavailability or interruption   *
 * of operations.                                                    *
 *                                                                   *
 * IBM WILL NOT BE LIABLE FOR ANY DIRECT DAMAGES OR FOR ANY SPECIAL, *
 * INCIDENTAL, OR  INDIRECT DAMAGES OR FOR ANY ECONOMIC              *
 * CONSEQUENTIAL DAMAGES (INCLUDING LOST PROFITS OR SAVINGS), EVEN   *
 * IF IBM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.  IBM  *
 * will not be liable for the loss of, or damage to, your records or *
 * data, or any damages claimed by you based on a third party claim. *
 *                                                                   *
 * IBM wishes to obtain your feedback to assist in improving the     *
 * Software.  You grant IBM a world-wide, royalty-free right to use, *
 * copy, distribute, sublicense and prepare derivative works based   *
 * upon any feedback, including materials, error corrections,        *
 * Software Derivatives, enhancements, suggestions and the like that *
 * you provide to IBM relating to the Software (this does not        *
 * include products for which you charge a royalty and distribute to *
 * IBM under other terms and conditions).                            *
 *                                                                   *
 * You agree to distribute the Software and any Software Derivatives *
 * under a license agreement that: 1) is sufficient to notify all    *
 * licensees of the Software and Software Derivatives that IBM       *
 * assumes no liability for any claim that may arise regarding the   *
 * Software or Software Derivatives, and 2) that disclaims all       *
 * warranties, both express and implied, from IBM regarding the      *
 * Software and Software Derivatives.  (If you include this          *
 * Agreement with any distribution of the Software or Software       *
 * Derivatives you will have met this requirement.)  You agree that  *
 * you will not delete any copyright notices in the Software.        *
 *                                                                   *
 * This Agreement is the exclusive statement of your rights in the   *
 * Software as provided by IBM.   Except for the rights granted to   *
 * you in the second paragraph above, You are not granted any other  *
 * patent rights, including but not limited to the right to make     *
 * combinations of the Software with products that infringe IBM      *
 * patents. You agree to comply with all applicable laws and         *
 * regulations, including all export and import laws and regulation. *
 * This Agreement is governed by the laws of the State of New York.  *
 * This Agreement supersedes all other communications,               *
 * understandings or agreements we may have had prior to this        *
 * Agreement.                                                        *
 * ***************************************************************** */

#include <index.h>
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sockets.h>
#endif

typedef struct {
  char ident[32];
  char indexName[16];
  uint32 keySize;
  char dataFileName[256];
} index_header_val_t;

typedef struct {
  index_header_val_t val;
  unsigned char padding[512-sizeof(index_header_val_t)];
} index_header_t;

int index_t::keycmp(const unsigned char * k1, const unsigned char * k2) const {
  return memcmp(k1, k2, keySize);
}

index_t::index_t(const char * index_name) {
  keySize = 0;
  file = NULL;
  fileName = NULL;
  dataFileName = NULL;
  indexName = (char *)malloc(strlen(index_name)+1);
  strcpy(indexName, index_name);
  isOpen = false;
  allowCreate = false;
  created = false;
  header_size = sizeof(index_header_t);
}

static char s_ident[32] = "Jonah Index File V1.0\n";

index_t::~index_t() {
  close();
  if (file) fclose(file);
  file = NULL;
  if (fileName) free(fileName);
  if (dataFileName) free(dataFileName);
  if (indexName) free(indexName);
}


uint32 index_t::set_file(const char * file) {
  if (isOpen) return ISM_INDEX_ACTIVE;
  if (fileName) free(fileName);
  fileName = (char *)malloc(strlen(file) + 1);
  strcpy(fileName, file);
  return 0;
}

uint32 index_t::open(void) {
  index_header_t header;
  uint32 status = 0;

  if (isOpen) return ISM_INDEX_ACTIVE;

  if (fileName == NULL) return ISM_INDEX_FILE_NOT_SET;

  if ((file = fopen(fileName, "r+b")) == NULL) {
    if (!allowCreate) {
      status = ISM_FILE_NOT_FOUND;
      goto end;
    };
// We can create the file...
    if ((file = fopen(fileName, "w+b")) == NULL) {
      status = ISM_FILE_ERROR;
      goto end;
    };
    strncpy(header.val.ident, s_ident, sizeof(header.val.ident));
    strncpy(header.val.indexName, indexName, sizeof(header.val.indexName));
    header.val.indexName[sizeof(header.val.indexName)-1] = 0;
    header.val.keySize = htonl(keySize);
    strncpy(header.val.dataFileName, dataFileName, sizeof(header.val.dataFileName));
    header.val.dataFileName[sizeof(header.val.dataFileName)-1] = 0;
    fwrite(&header, sizeof(header), 1, file);
    created = true;
  } else {
    if (fread(&header, sizeof(header), 1, file) != 1) {
      status = ISM_DB_CORRUPT;
      goto end;
    };
    if (strncmp(s_ident, header.val.ident, sizeof(header.val.ident)) != 0) {
      status = ISM_DB_CORRUPT;
      goto end;
    };
    header.val.indexName[sizeof(header.val.indexName)-1] = 0;
    header.val.dataFileName[sizeof(header.val.dataFileName)-1] = 0;
    if (indexName != NULL) {
      if (strncmp(indexName, 
                  header.val.indexName, 
                  sizeof(header.val.indexName)) != 0) {
        status = ISM_WRONG_INDEX;
        goto end;
      };
    };
    if (dataFileName != NULL) {
      if (strncmp(dataFileName, 
                  header.val.dataFileName, 
                  sizeof(header.val.dataFileName)) != 0) {
        status = ISM_WRONG_DATAFILE;
        goto end;
      };
    };

    if (indexName) free(indexName);
    indexName = (char *)malloc(strlen(header.val.indexName) + 1);
    strcpy(indexName, header.val.indexName);

    if (dataFileName) free(dataFileName);
    dataFileName = (char *)malloc(strlen(header.val.dataFileName) + 1);
    strcpy(dataFileName, header.val.dataFileName);
    keySize = ntohl(header.val.keySize);
    created = false;
  };
  isOpen = true;

end:
  if (status) {
    if (file) fclose(file);
    isOpen = false;
  };
  return status;
}

uint32 index_t::define_index(uint32 keysize,
                             const char * data_file,
                             bool duplicates_allowed) {
  if (isOpen) return ISM_INDEX_ACTIVE;
  keySize = keysize;
  if (dataFileName) free(dataFileName);
  dataFileName = (char *)malloc(strlen(data_file)+1);
  strcpy(dataFileName, data_file);
  allowCreate = true;
  duplicatesAllowed = duplicates_allowed;
  return 0;
}

uint32 index_t::close(void) {
  if (file) fclose(file);
  file = NULL;
  isOpen = false;
  created = false;
  return 0;
}

uint32 index_t::remove(const unsigned char * key) {
  return ISM_OPERATION_NOT_SUPPORTED;
}

