Source: types.js

/*-
 *
 *  This file is part of Oracle NoSQL Database
 *  Copyright (C) 2011, 2015 Oracle and/or its affiliates.  All rights reserved.
 *
 * If you have received this file as part of Oracle NoSQL Database the
 * following applies to the work as a whole:
 *
 *   Oracle NoSQL Database server software is free software: you can
 *   redistribute it and/or modify it under the terms of the GNU Affero
 *   General Public License as published by the Free Software Foundation,
 *   version 3.
 *
 *   Oracle NoSQL Database is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without 4n the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Affero General Public License for more details.
 *
 * If you have received this file as part of Oracle NoSQL Database Client or
 * distributed separately the following applies:
 *
 *   Oracle NoSQL Database client software is free software: you can
 *   redistribute it and/or modify it under the terms of the Apache License
 *   as published by the Apache Software Foundation, version 2.0.
 *
 * You should have received a copy of the GNU Affero General Public License
 * and/or the Apache License in the LICENSE file along with Oracle NoSQL
 * Database client or server distribution.  If not, see
 * <http://www.gnu.org/licenses/>
 * or
 * <http://www.apache.org/licenses/LICENSE-2.0>.
 *
 * An active Oracle commercial licensing agreement for this product supersedes
 * these licenses and in such case the license notices, but not the copyright
 * notice, may be removed by you in connection with your distribution that is
 * in accordance with the commercial licensing terms.
 *
 * For more information please contact:
 *
 * berkeleydb-info_us@oracle.com
 *
 */
'use strict';

/*global Logger*/
/*global Errors*/
/*global util*/

var Stringify = require('./stringify');
var Parse = require('./parse');
var ttypes = require('./thrift/ondb_types');

/**
 * A replicated environment makes it possible to increase the application's
 * transaction commit guarantees by committing changes to its replicas on the
 * network. ReplicaAckPolicy defines the policy for how such network commits
 * are handled.
 * @property {Number} ALL All replicas must acknowledge that they have
 *   committed the transaction.
 * @property {Number} NONE No transaction commit acknowledgments are required
 *   and the master will never wait for replica acknowledgments.
 * @property {Number} SIMPLE_MAJORITY A simple majority of replicas must
 *   acknowledge that they have committed the transaction.
 * @enum {Number}
 */
var ReplicaAckPolicy = {
  ALL : ttypes.TReplicaAckPolicy.ALL,
  NONE : ttypes.TReplicaAckPolicy.NONE,
  SIMPLE_MAJORITY : ttypes.TReplicaAckPolicy.SIMPLE_MAJORITY
};
exports.ReplicaAckPolicy = ReplicaAckPolicy;

/**
 * Defines the synchronization policy to be used when committing a transaction.
 * High levels of synchronization offer a greater guarantee that the
 * transaction is persistent to disk, but the tradeoff is lower performance.
 * @property {Number} NO_SYNC Do not write or synchronously flush the log on
 *   transaction commit.
 * @property {Number} SYNC Write and synchronously flush the log on transaction
 *   commit.
 * @property {Number} WRITE_NO_SYNC Write but do not synchronously flush the
 *   log on transaction commit.
 * @enum {Number}
 */
var SyncPolicy = {
  NO_SYNC : ttypes.TSyncPolicy.NO_SYNC,
  SYNC : ttypes.TSyncPolicy.SYNC,
  WRITE_NO_SYNC : ttypes.TSyncPolicy.WRITE_NO_SYNC
};
exports.SyncPolicy = SyncPolicy;

/**
 * Used to provide consistency guarantees for read operations.
 * In general, read operations may be serviced either at a Master or Replica
 * node. When serviced at the Master node, consistency is always absolute. If
 * absolute consistency is required, ABSOLUTE may be specified to force the
 * operation to be serviced at the Master. For other types of consistency, when
 * the operation is serviced at a Replica node, the transaction will not begin
 * until the consistency policy is satisfied. The Consistency is specified as
 * an argument to all read operations, for example, get.
 * @property {Number} ABSOLUTE A consistency policy that requires that a
 *   transaction be serviced on the Master so that consistency is absolute.
 * @property {Number} NONE_REQUIRED A consistency policy that lets a
 *   transaction on a replica using this policy proceed regardless of the state
 *   of the Replica relative to the Master.
 * @property {Number} NONE_REQUIRED_NO_MASTER A consistency policy that
 *   requires that a read operation be serviced on a replica; never the Master.
 * @enum {Number}
 */

var SimpleConsistency = {
  ABSOLUTE : ttypes.TSimpleConsistency.ABSOLUTE,
  NONE_REQUIRED : ttypes.TSimpleConsistency.NONE_REQUIRED,
  NONE_REQUIRED_NO_MASTER : ttypes.TSimpleConsistency.NONE_REQUIRED_NO_MASTER
};
exports.SimpleConsistency = SimpleConsistency;

function TimeConsistency(/*Number*/  permissibleLag, /*Number*/ timeoutMs) {
  ttypes.TTimeConsistency.call(this);
  if (permissibleLag !== null)
    this.permissibleLag = permissibleLag;
  if (timeoutMs !== null)
    this.timeoutMs = timeoutMs;
}
util.inherits(TimeConsistency, ttypes.TTimeConsistency);
exports.TimeConsistency = TimeConsistency;

function VersionConsistency(/*Version*/ version, /*Number*/ timeoutMs) {
  ttypes.TVersionConsistency.call(this);
  if (version != null)
    if (version.id !== undefined)
      this.version = version.id;
    else
      throw new Errors.ParameterError('version', 'Should be a valid version');

  this.timeoutMs = timeoutMs;
}
util.inherits(VersionConsistency, ttypes.TVersionConsistency);
exports.VersionConsistency = VersionConsistency;

function Consistency(/*Object*/ consistency) {
  ttypes.TConsistency.call(this);
  if ((consistency === ttypes.TSimpleConsistency.ABSOLUTE) ||
      (consistency === ttypes.TSimpleConsistency.NONE_REQUIRED) ||
      (consistency === ttypes.TSimpleConsistency.NONE_REQUIRED_NO_MASTER))
    this.simple = consistency;
  else if (consistency instanceof TimeConsistency)
    this.time = consistency;
  else if (consistency instanceof VersionConsistency) {
    this.version = consistency;
  } else {
    throw new Errors.ParameterError('consistency',
      'Error constructing Consistency object, this object must' +
      ' be build using one of the types: SimpleConsistency, TimeConsistency' +
      ' or VersionConsistency ');
  }
}
util.inherits(Consistency, ttypes.TConsistency);
exports.Consistency = Consistency;

/**
 * ReadOptions is passed to read-only store operations to specify arguments
 * that control non-default behavior related to consistency and operation
 * timeouts.
 * @property {Consistency} consistency Used to provide consistency guarantees
 *   for read operations.
 * @property {Number} timeoutMs Is the upper bound on the time interval for
 *   processing the operation.
 * @constructor
 * @returns {ReadOptions}
 */
function ReadOptions(/*Consistency*/ consistency,
                     /*Number*/ timeoutMs) {
  ttypes.TReadOptions.call(this);
  if (consistency !== null) {
    if ((consistency === SimpleConsistency.ABSOLUTE) ||
      (consistency === SimpleConsistency.NONE_REQUIRED) ||
      (consistency === SimpleConsistency.NONE_REQUIRED_NO_MASTER) ||
      (consistency instanceof TimeConsistency) ||
      (consistency instanceof VersionConsistency))
      this.consistency = new Consistency(consistency);
    else if (consistency instanceof Consistency)
      this.consistency = consistency;
    else
      throw new Errors.ParameterError('consistency',
        'Error constructing ReadOptions object, this object must' +
        ' be build using a valid Consistency Object');
  }
  if (timeoutMs !== null)
    this.timeoutMs = timeoutMs;
}
util.inherits(ReadOptions, ttypes.TReadOptions);
exports.ReadOptions = ReadOptions;

/**
 * Defines the durability characteristics associated with a standalone write
 * (put or update) operation, or in the case of KVStore.execute with a set of
 * operations performed in a single transaction. The overall durability is a
 * function of the SyncPolicy and ReplicaAckPolicy in effect for the Master,
 * and the Durability.SyncPolicy in effect for each Replica.
 * @property {SyncPolicy} masterSync The transaction synchronization policy to
 *   be used on the Master when committing a transaction.
 * @property {ReplicaAckPolicy} replicaAck The replica acknowledgment policy
 *   used by the master when committing changes to a replicated environment.
 * @property {SyncPolicy} replicaSync The transaction synchronization policy to
 *   be used by the replica as it replays a transaction that needs an
 *   acknowledgment.
 * @returns {Durability}
 * @constructor
 */
function Durability(/*SyncPolicy*/ masterSync,
                    /*ReplicaAckPolicy*/ replicaAck,
                    /*SyncPolicy*/ replicaSync) {
  ttypes.TDurability.call(this);
  if (masterSync !== null)
    this.masterSync = masterSync;
  if (replicaAck !== null)
    this.replicaAck = replicaAck;
  if (replicaSync !== null)
    this.replicaSync = replicaSync;
}
util.inherits(Durability, ttypes.TDurability);
exports.Durability = Durability;

/**
 * Specifies whether to return the row value, version, both or neither.
 * For best performance, it is important to choose only the properties that are
 * required. The store is optimized to avoid I/O when the requested properties
 * are in cache.
 * @property {Number} ALL Return both the value and the version.
 * @property {Number} NONE Do not return the value or the version.
 * @property {Number} VALUE Return the value only.
 * @property {Number} VERSION Return the version only.
 * @enum {Number}
 */
var ReturnChoice = {
  ALL : ttypes.TReturnChoice.ALL,
  NONE : ttypes.TReturnChoice.NONE,
  VALUE : ttypes.TReturnChoice.ONLY_VALUE,
  VERSION : ttypes.TReturnChoice.ONLY_VERSION
};
exports.ReturnChoice = ReturnChoice;

/**
 * WriteOptions is passed to store operations that can update the store to
 * specify non-default behavior relating to operation durability and timeouts.
 * @property {Durability} durability Defines the durability characteristics
 *   associated with a standalone write (put or update) operation
 * @property {ReturnChoice} returnChoice Specifies whether to return the row
 *   value, version, both or neither.
 * @property {Number} timeoutMs The upper bound on the time interval for
 *   processing the operation.
 * @returns {WriteOptions}
 * @constructor
 */

function WriteOptions(/*Durability*/ durability,
                      /*Number*/ timeoutMs,
                      /*ReturnChoice*/ returnChoice) {
  ttypes.TWriteOptions.call(this);
  if (durability !== null)
    this.durability = durability;
  if (timeoutMs !== null)
    this.timeoutMs = timeoutMs;
  if (returnChoice !== null)
    this.returnChoice = returnChoice;
}
util.inherits(WriteOptions, ttypes.TWriteOptions);
exports.WriteOptions = WriteOptions;

/**
 * FieldRange defines a range of values to be used in a table or index
 * iteration or multiGet operation. A FieldRange is used as the least
 * significant component in a partially specified PrimaryKey or IndexKey in
 * order to create a value range for an operation that returns multiple rows or
 * keys. The data types supported by FieldRange are limited to those which are
 * valid for primary keys and/or index keys.
 * @property {String} fieldName The name for the field used in the range.
 * @property {Object} startValue
 * @property {bool} startIsInclusive
 * @property {Object} endValue
 * @property {bool} endIsInclusive
 * @returns {FieldRange}
 * @constructor
 */
function FieldRange(/*String*/ fieldName,
                    /*Object*/ startValue,
                    /*bool*/ startIsInclusive,
                    /*Object*/ endValue,
                    /*bool*/ endIsInclusive) {
  ttypes.TFieldRange.call(this);
  if (fieldName !== null)
    this.fieldName = fieldName;
  if (startValue !== null)
    this.startValue = '' + startValue;
  if (startIsInclusive !== null)
    this.startIsInclusive = startIsInclusive;
  if (endValue !== null)
    this.endValue = '' + endValue;
  if (endIsInclusive !== null)
    this.endIsInclusive = endIsInclusive;
}
util.inherits(FieldRange, ttypes.TFieldRange);
exports.FieldRange = FieldRange;

var Direction = {
  FORWARD : ttypes.TDirection.FORWARD,
  REVERSE : ttypes.TDirection.REVERSE,
  UNORDERED : ttypes.TDirection.UNORDERED
};
exports.Direction = Direction;

var OperationType = {
  DELETE : ttypes.TOperationType.DELETE,
  DELETE_IF_VERSION : ttypes.TOperationType.DELETE_IF_VERSION,
  PUT : ttypes.TOperationType.PUT,
  PUT_IF_ABSENT : ttypes.TOperationType.PUT_IF_ABSENT,
  PUT_IF_PRESENT : ttypes.TOperationType.PUT_IF_PRESENT,
  PUT_IF_VERSION : ttypes.TOperationType.PUT_IF_VERSION
};
exports.OperationType = OperationType;

/**
 * Defines an update operation to be passed to Store.executeOperations().
 * @property {String} tableName The table name on which this operation is
 *   executed on.
 * @property {OperationType} type Determines which update operation to be
 *   executed.
 * @property {Row} row For put operations it represents the row to be stored.
 * For delete operations it represents the key of the row to be deleted.
 * @property {ReturnChoice} returnChoice Specifies whether to return the row
 *   value, version, both or neither.
 * @property {bool} abortIfUnsuccessful If true, this operation should cause the
 *   execute transaction to abort when the operation fails, where failure is
 *   the condition when the delete or put method returns null.
 * @property {Version} [matchVersion] The version to be matched for:
 *  PUT_IF_VERSION or DELETE_IF_VERSION.
 * @constructor
 */

function Operation(/*String*/ tableName,
                   /*OperationType*/ type,
                   /*Row*/ row,
                   /*ReturnChoice*/ returnChoice,
                   /*bool*/ abortIfUnsuccessful,
                   /*Version*/ matchVersion) {
  ttypes.TOperation.call(this);
  if (tableName !== null)
    this.tableName = tableName;
  if (type !== null)
      this.type = type;
  if (row !== null)
    this.row = row;
  if (returnChoice !== null)
    this.returnChoice = returnChoice;
  if (abortIfUnsuccessful !== null)
    this.abortIfUnsuccessful = abortIfUnsuccessful;
  if (matchVersion !== null)
    this.matchVersion = matchVersion;

  if ((type === OperationType.PUT_IF_VERSION) ||
    (type === OperationType.DELETE_IF_VERSION))
    if (! (matchVersion instanceof Version))
      Logger.warn('The operation contains an invalid Version.');

}
util.inherits(Operation, ttypes.TOperation);
exports.Operation = Operation;



/* ****
 * ****  RESULT STRUCTURES
 * ****
 */

/**
 * @class
 * This object contains data associated to the id of a plan from an execute
 * operation.
 */
function ExecutionId (/*Buffer*/ executionId) {
  this.executionId = null;
  if (executionId !== undefined)
    if (executionId !== null)
      this.executionId = executionId;
}
exports.ExecutionId = ExecutionId;

/**
 * @class
 * This object contains data associated to the version of a row.
 */
function Version (/*Buffer*/ version) {
  this.id = null;
  if (version !== undefined)
    if (version)
      this.id = version;
}
exports.Version = Version;

/**
 * @class
 * The result of a GET operation
 * @property {Row} currentRow The result row of the operation.
 * @property {Version} currentRowVersion The version object for the row.
 */
function GetResult(/*TGetResult*/ args) {
  this.currentRow = null;
  this.currentRowVersion = null;
  if (args) {

    if (args.currentRow !== undefined)
      if (args.currentRow)
        this.currentRow = Parse(args.currentRow.jsonRow);

    if (args.currentRowVersion !== undefined)
      if (args.currentRowVersion)
        this.currentRowVersion = new Version(args.currentRowVersion);

  }
}
exports.GetResult = GetResult;

/**
 * @class
 * A row is an object with data from a table in the form:
 * { field: value, field: value....}
 */
function Row() {}


/**
 * @class
 * This object contains a row result with metadata associated to the result.
 * @property {Row} row The result row.
 * @property {String} table The table name from the the row.
 * @property {Version} version An object that represents the row version.
 *
 */
function ReturnRow( /*TRowWithMetadata*/ args,
                    /*TIdToTableNames*/ idToTableNames) {
  this.row = null;
  this.table = null;
  this.version = null;

  if ((args.tableId !== undefined) && (idToTableNames !== undefined))
    if (args.tableId)
      if (idToTableNames[args.tableId])
       this.table = idToTableNames[args.tableId];

  if (args.rowVersion !== undefined)
    if (args.rowVersion)
      this.version = new Version(args.rowVersion);

  if (args) {
    if (args.jsonRow !== undefined)
      if (args.jsonRow)
        this.row = Parse(args.jsonRow);
  }
}

/**
 * This object contains an array with all row results from a call to a
 * multi* method.
 * @property {Array} returnRows The array with the rows.
 * @class
 */
function MultiGetResult(/*TMultiGetResult*/ args) {
  this.returnRows = null;

  if (args) {
    if (args.rowsWithMetadata !== undefined)
      if (args.rowsWithMetadata) {
        this.returnRows = [];

        for (var index = 0; index < args.rowsWithMetadata.length; index++)
          this.returnRows.push(
            new ReturnRow(
              args.rowsWithMetadata[index],
              args.idToTableNames));
      }
  }
}
exports.MultiGetResult = MultiGetResult;


/**
 * @class
 * This object contains a key result with metadata associated to the result.
 * @property {Row} key The result key.
 * @property {String} table The table name from the the row.
 * @property {Version} version An object that represents the row version.
 *
 */
function ReturnKey( /*TRowWithMetadata*/ args,
                    /*TIdToTableNames*/ idToTableNames) {
  this.key = null;
  this.table = null;
  this.version = null;
  if (args) {
    if (args.jsonRow !== undefined)
      if (args.jsonRow)
        this.key = Parse(args.jsonRow);

    if ((args.tableId !== undefined) && (idToTableNames !== undefined))
      if (args.tableId)
        if (idToTableNames[args.tableId])
          this.table = idToTableNames[args.tableId];

    if (args.rowVersion !== undefined)
      if (args.rowVersion)
        this.version = new Version(args.rowVersion);
  }
}

/**
 * This object contains an array with all row results from a call to a
 * multiGetKeys method.
 * @property {Array} returnRows The array with the keys.
 * @class
 */
function MultiGetKeyResult(/*TMultiGetResult*/ args) {
  this.returnRows = null;
  if (args)
    if (args.rowsWithMetadata !== undefined)
      if (args.rowsWithMetadata) {
        this.returnRows = [];

        for (var index = 0; index < args.rowsWithMetadata.length; index++)
          this.returnRows.push(
            new ReturnKey(
              args.rowsWithMetadata[index],
              args.idToTableNames));

      }
}
exports.MultiGetKeyResult = MultiGetKeyResult;

/**
 * This object contains the result of a PUT operation.
 * @property {Version} currentRowVersion The current version of the row.
 * @property {Row} previousRow The previous row.
 * @property {Version} previousRowVersion The previous version of the row.
 * @class
 */
function PutResult (/*TWriteResult*/ args) {
  this.currentRowVersion = null;
  this.previousRow = null;
  this.previousRowVersion = null;
  if (args) {

    if (args.currentRowVersion !== undefined)
      if (args.currentRowVersion)
        this.currentRowVersion = new Version(args.currentRowVersion);

    if (args.previousRow !== undefined)
      if (args.previousRow)
        this.previousRow = Parse(args.previousRow.jsonRow);

    if (args.previousRowVersion !== undefined)
      if (args.previousRowVersion)
        this.previousRowVersion = new Version(args.previousRowVersion);

  }
}
exports.PutResult = PutResult;

/**
 * This object contains the result of a DELETE operation.
 * @property {Row} previousRow The previous row.
 * @property {Version} previousRowVersion The previous version of the row.
 * @property {bool} wasDeleted True if the row was deleted.
 * @class
 */
function DeleteResult(args) {
  this.previousRow = null;
  this.previousRowVersion = null;
  this.wasDeleted = null;
  if (args) {

    if (args.previousRow !== undefined)
      if (args.previousRow)
        this.previousRow = Parse(args.previousRow.jsonRow);

    if (args.previousRowVersion !== undefined)
      if (args.previousRowVersion)
        this.previousRowVersion = new Version(args.previousRowVersion);

    if (args.wasDeleted !== undefined)
      if (args.wasDeleted !== null)
        this.wasDeleted = args.wasDeleted;

  }
}
exports.DeleteResult = DeleteResult;

/**
 * This object contains information about an executeUpdate process.
 * @property {Version} currentRowVersion The current version of the row.
 * @property {Row} previousRow The previous row.
 * @property {Version} previousRowVersion The previous version of the row.
 * @property {bool} wasDeleted True if the row was deleted.
 * @class
 */
function UpdateResult(args) {
  this.currentRowVersion = null;
  this.previousRow = null;
  this.previousRowVersion = null;
  this.wasDeleted = null;
  if (args) {
    if (args.currentRowVersion !== undefined)
      if (args.currentRowVersion)
        this.currentRowVersion = new Version(args.currentRowVersion);

    if (args.previousRow !== undefined)
      if (args.previousRow)
        this.previousRow = Parse(args.previousRow.jsonRow);

    if (args.previousRowVersion !== undefined)
      if (args.previousRowVersion)
        this.previousRowVersion = new Version(args.previousRowVersion);

    if (args.wasDeleted !== undefined)
      if (args.wasDeleted !== null)
        this.wasDeleted = args.wasDeleted;

  }
}
exports.UpdateResult = UpdateResult;

/**
 * This object contains information about an execute, executeBackground,
 * executeStatus or executeCancel process.
 * @class
 * @property {Number} planId The plan id number internally used to
 * identify the operation.
 * @property {ExecutionId} executionId The execution id internally used to
 * describe the operation.
 * @property {String} info Detailed information about the status of the command
 * execution in human readable form.
 * @property {String} infoExtended Detailed information about the status of the
 * command execution in a manipulable object.
 * @property {bool} isSuccessful True if this statement has finished and was
 * successful.
 * @property {String} errorMessage If the operation failed, and isSuccessful
 * is false, errorMsg will return a description of the problem.
 * @property {bool} isCancelled True if the operation was cancelled.
 * Not set by execute method.
 * @property {bool} true If the operation has been terminated. Always true for
 * execute method.
 */
function StatementResult(/*TStatementResultV2*/ args) {
  this.planId = null;
  this.executionId = null;
  this.info = null;
  this.infoExtended = null;
  this.isSuccessful = null;
  this.errorMessage = null;
  this.isCancelled = null;
  this.isDone = null;
  this.statement = null;
  this.result = null;
  if (args) {
    if (args.planId !== undefined)
      this.planId = args.planId;

    if (args.executionId !== undefined)
      this.executionId = new ExecutionId(args.executionId);

    if (args.info !== undefined)
      this.info = args.info;

    if (args.infoAsJson !== undefined)
      this.infoExtended = Parse(args.infoAsJson);

    if (args.isSuccessful !== undefined)
      this.isSuccessful = args.isSuccessful;

    if (args.errorMessage !== undefined)
      this.errorMessage = args.errorMessage;

    if (args.isCancelled !== undefined)
      this.isCancelled = args.isCancelled;

    if (args.isDone !== undefined)
      this.isDone = args.isDone;

    if (args.statement !== undefined)
      this.statement = args.statement;

    if (args.result !== undefined && args.result !== null)
      if (args.result.stringResult !== undefined) // from TResult
        this.result = args.result.stringResult;

  }
}
exports.StatementResult = StatementResult;

/**
 *@class
 * This object provides information about the background execution process
 * created by executeBackground object.
 * This object can be created using the executionId from other source, i.e.
 *
 * var otherFuture= new ExecutionFuture(otherExecutionId);
 *
 * @property {ExecutionId} executionId The execution id internally used to
 * describe the operation.
 * @property {StatementResult} statementResult The last known statement result.
 */
function ExecutionFuture(/*TStatementResultV2*/ args,
                         /*Store*/ store) {
  this.store = null;
  this.executionId = null;
  this.statementResult = null;
  if (args) {
    this.executionId = new ExecutionId(args.executionId);
    this.statementResult = new StatementResult(args);
  }
  if (store)
    this.store = store;
}
exports.ExecutionFuture = ExecutionFuture;

/**
 * Returns information about the execution of the statement. If the
 * statement is still executing, this call will result in communication
 * with the kvstore server to obtain up to date status, and the status
 * returned will reflect interim information.
 * @param {updateStatusCallback} [callback] A function that is called with
 * information about the process.
 */
ExecutionFuture.prototype.updateStatus =
  function updateStatus( /*updateStatusCallback*/ callback ) {
  var self = this;

  callback = callback || function () {};
  self.store.checkIsConnected();
  if ((self.statementResult.isDone == true) ||
      (self.statementResult.isCancelled == true))
    callback(null, self);
  else
    self.store.thriftClient.executionFutureUpdateStatusV2(
      self.executionId.executionId,
      function (err, result) {
        if (err) {
          var error = Errors.getProxyError(err, 'ExecutionFuture.getStatus()');
          self.store.reportError(error, callback);
        } else {
          self.statementResult = new StatementResult(result);
          callback(null, this);
        }
      })

};

/**
 * @callback updateStatusCallback
 * @param {Error} error The error returned by the operation, if any, null
 *  otherwise.
 * @param {ExecutionFuture} result A statementResult object with information
 *  about the process.
 */

/**
 * Attempts to cancel execution of this statement. Returns false if
 * the statement could not be cancelled, possibly because it has already
 * finished. If the statement has not succeeded already, and can be stopped,
 * the operation will transition to the FAILED state.
 *
 * @param {bool} [mayInterrupt] Option that allows to interrupt the execution.
 * @param {cancelCallback} [callback] A function that is called when
 * the process is cancelled or the cancellation process failed.
 */
ExecutionFuture.prototype.cancel =
  function cancel(/*bool*/ mayInterrupt,
                  /*cancelCallback*/ callback) {
  var self = this;

  if (typeof mayInterrupt == 'function') {
    callback = mayInterrupt;
    mayInterrupt = true;
  }
  callback = callback || function () {};

  self.store.checkIsConnected();
    if ((self.statementResult.isDone == true) ||
        (self.statementResult.isCancelled == true))
    callback(null, self);
  else
    self.store.thriftClient.executionFutureCancelV2(
      self.executionId.executionId,
      mayInterrupt,
      function (err, result) {
        if (err) {
          var error = Errors.getProxyError(err, 'ExecutionFuture.cancel()');
          self.store.reportError(error, callback);
        } else {
          self.statementResult = new StatementResult(result);
          callback(null, this);
        }
      })
};
/**
 * @callback cancelCallback
 * @param {Error} error The error returned by the operation, if any, null
 *  otherwise.
 * @param {bool} result A flag indicating if the process could be canceled.
 *
 */

/**
 * This method call the method specified in the callback parameter until the
 * command represented by the execution id completes. Returns information about
 * the execution of the statement.
 * @param {getCallback} [callback] A function that is called when
 * the process is cancelled or the cancellation process failed.
 */
ExecutionFuture.prototype.get =
  function get( /*getCallback*/ callback) {
  var self = this;

  callback = callback || function () {};

  self.store.checkIsConnected();

    if ((self.statementResult.isDone == true) ||
        (self.statementResult.isCancelled == true))
    callback(null, self);
  else
    self.store.thriftClient.executionFutureGetV2(
      self.executionId.executionId,
      function (err, result) {
        if (err) {
          var error = Errors.getProxyError(err, 'ExecutionFuture.get()');
          self.store.reportError(error, callback);
        } else {
          self.statementResult = new StatementResult(result);
          callback(null, this);
        }
      })
};
/**
 * @callback getCallback
 * @param {Error} error The error returned by the operation, if any, null
 *  otherwise.
 * @param {ExecutionFuture} result A statementResult object with information
 *  about the process.
 */


/**
 * @class
 * This object specify the module to be consulted by version() and status()
 * methods.
 * @property JS_CLIENT This javascript module.
 * @property PROXY_SERVER The proxy server.
 * @property JAVA_CLIENT The current java version used.
 */
var ModuleInfo = {
  JS_DRIVER: 1,
  PROXY_SERVER : ttypes.TModuleInfo.PROXY_SERVER,
  JAVA_CLIENT : ttypes.TModuleInfo.JAVA_CLIENT
};
exports.ModuleInfo = ModuleInfo;

/**
 * @class
 *
 */
function VerifyProperties(args) {
  ttypes.TVerifyProperties.call(this);
  this.kvStoreName = null;
  this.kvStoreHelperHosts = null;
  this.username = null;
  this.readZones = null;
  this.driverProtocolVersion = null;
  if (args) {
    if (args.kvStoreName !== undefined) {
      this.kvStoreName = args.kvStoreName;
    }
    if (args.kvStoreHelperHosts !== undefined) {
      this.kvStoreHelperHosts = args.kvStoreHelperHosts;
    }
    if (args.username !== undefined) {
      this.username = args.username;
    }
    if (args.readZones !== undefined) {
      this.readZones = args.readZones;
    }
    if (args.driverProtocolVersion !== undefined) {
      this.driverProtocolVersion = args.driverProtocolVersion;
    }
  }
}
util.inherits(VerifyProperties, ttypes.TVerifyProperties);
exports.VerifyProperties = VerifyProperties;


var VerifyError = {
  INVALID_KVSTORE_Name :
    ttypes.TVerifyError.INVALID_KVSTORE_Name,
  INVALID_KVSTORE_HelperHosts :
    ttypes.TVerifyError.INVALID_KVSTORE_HelperHosts,
  Unsupported_Driver_ProtocolVersion :
    ttypes.TVerifyError.Unsupported_Driver_ProtocolVersion
};
exports.VerifyError = VerifyError;

function VerifyErrorDescription(/*VerifyError*/ value) {
  switch (value) {
    case VerifyError.INVALID_KVSTORE_Name:
      return 'Invalid KVStore Name';
    case VerifyError.INVALID_KVSTORE_HelperHosts :
      return 'Invalid KVStore Helper Hosts';
    case VerifyError.Unsupported_Driver_ProtocolVersion :
      return 'Unsupported driver protocol version';
  }
}
exports.VerifyErrorDescription = VerifyErrorDescription;



/*
 ********** HELPER
 */
function setGlobals() {
  global.ReplicaAckPolicy = ReplicaAckPolicy;
  global.SyncPolicy = SyncPolicy;
  global.SimpleConsistency = SimpleConsistency;
  global.TimeConsistency = TimeConsistency;
  global.VersionConsistency = VersionConsistency;
  global.Consistency = Consistency;
  global.ReadOptions = ReadOptions;
  global.Durability = Durability;
  global.ReturnChoice = ReturnChoice;
  global.WriteOptions = WriteOptions;
  global.FieldRange = FieldRange;
  global.Direction = Direction;
  global.OperationType = OperationType;
  global.Operation = Operation;
}
exports.setGlobals = setGlobals;

// Having configuration here too
var Configuration = require ('./configuration').Configuration;
exports.Configuration = Configuration;