function BatchOperation(name, options) {
  if (!options) {
    options = {};
  }

  this.name = name;
  this.logger = options.logger || new Logger(Logger.LogLevels.INFO);
  this.operationMemoryUsage = options.operationMemoryUsage || DEFAULT_OPERATION_MEMORY_USAGE;
  this.callbackInOrder = options.callbackInOrder === true;
  this.callInOrder = options.callInOrder === true;
  this._currentOperationId = this.callbackInOrder ? 1 : -1;
  this.concurrency = DEFAULT_GLOBAL_CONCURRENCY;
  this.enableReuseSocket = (nodeVersion.major > 0 || nodeVersion.minor >= 10) && options.enableReuseSocket;

  this._emitter = new EventEmitter();
  this._enableComplete = false;
  this._ended = false;
  this._error = null;
  this._paused = false;

  //Total operations count(queued and active and connected)
  this._totalOperation = 0;

  //Action operations count(The operations which are connecting to remote or executing callback or queued for executing)
  this._activeOperation = 0;

  //Queued operations count(The operations which are connecting to remote or queued for executing)
  this._queuedOperation = 0;

  //finished operation should be removed from this array
  this._operations = [];
}
Concurrently execute batch operations and call operation callback randomly or in sequence.
Random mode is for uploading.
  1. Fire user callback when the operation is done.
Sequence mode is for downloading.
  1. Fire user callback when the operation is done and all previous operations and callback has finished.
  2. BatchOperation guarantees the user callback is fired one by one.
  3. The next user callback can't be fired until the current one is completed.