// Copyright (c) 2015, Red Hat, Inc.  All rights reserved.
//  This source code is licensed under both the GPLv2 (found in the
//  COPYING file in the root directory) and Apache 2.0 License
//  (found in the LICENSE.Apache file in the root directory).
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
//
// MirrorEnv is an Env implementation that mirrors all file-related
// operations to two backing Env's (provided at construction time).
// Writes are mirrored.  For read operations, we do the read from both
// backends and assert that the results match.
//
// This is useful when implementing a new Env and ensuring that the
// semantics and behavior are correct (in that they match that of an
// existing, stable Env, like the default POSIX one).

#pragma once

#ifndef ROCKSDB_LITE

#include <iostream>
#include <algorithm>
#include <vector>
#include "rocksdb/env.h"

namespace rocksdb {

class SequentialFileMirror;
class RandomAccessFileMirror;
class WritableFileMirror;

class EnvMirror : public EnvWrapper {
  Env* a_, *b_;
  bool free_a_, free_b_;

 public:
  EnvMirror(Env* a, Env* b, bool free_a=false, bool free_b=false)
    : EnvWrapper(a),
      a_(a),
      b_(b),
      free_a_(free_a),
      free_b_(free_b) {}
  ~EnvMirror() {
    if (free_a_)
      delete a_;
    if (free_b_)
      delete b_;
  }

  Status NewSequentialFile(const std::string& f, unique_ptr<SequentialFile>* r,
                           const EnvOptions& options) override;
  Status NewRandomAccessFile(const std::string& f,
                             unique_ptr<RandomAccessFile>* r,
                             const EnvOptions& options) override;
  Status NewWritableFile(const std::string& f, unique_ptr<WritableFile>* r,
                         const EnvOptions& options) override;
  Status ReuseWritableFile(const std::string& fname,
                           const std::string& old_fname,
                           unique_ptr<WritableFile>* r,
                           const EnvOptions& options) override;
  virtual Status NewDirectory(const std::string& name,
                              unique_ptr<Directory>* result) override {
    unique_ptr<Directory> br;
    Status as = a_->NewDirectory(name, result);
    Status bs = b_->NewDirectory(name, &br);
    assert(as == bs);
    return as;
  }
  Status FileExists(const std::string& f) override {
    Status as = a_->FileExists(f);
    Status bs = b_->FileExists(f);
    assert(as == bs);
    return as;
  }
  Status GetChildren(const std::string& dir,
                     std::vector<std::string>* r) override {
    std::vector<std::string> ar, br;
    Status as = a_->GetChildren(dir, &ar);
    Status bs = b_->GetChildren(dir, &br);
    assert(as == bs);
    std::sort(ar.begin(), ar.end());
    std::sort(br.begin(), br.end());
    if (!as.ok() || ar != br) {
      assert(0 == "getchildren results don't match");
    }
    *r = ar;
    return as;
  }
  Status DeleteFile(const std::string& f) override {
    Status as = a_->DeleteFile(f);
    Status bs = b_->DeleteFile(f);
    assert(as == bs);
    return as;
  }
  Status CreateDir(const std::string& d) override {
    Status as = a_->CreateDir(d);
    Status bs = b_->CreateDir(d);
    assert(as == bs);
    return as;
  }
  Status CreateDirIfMissing(const std::string& d) override {
    Status as = a_->CreateDirIfMissing(d);
    Status bs = b_->CreateDirIfMissing(d);
    assert(as == bs);
    return as;
  }
  Status DeleteDir(const std::string& d) override {
    Status as = a_->DeleteDir(d);
    Status bs = b_->DeleteDir(d);
    assert(as == bs);
    return as;
  }
  Status GetFileSize(const std::string& f, uint64_t* s) override {
    uint64_t asize, bsize;
    Status as = a_->GetFileSize(f, &asize);
    Status bs = b_->GetFileSize(f, &bsize);
    assert(as == bs);
    assert(!as.ok() || asize == bsize);
    *s = asize;
    return as;
  }

  Status GetFileModificationTime(const std::string& fname,
                                 uint64_t* file_mtime) override {
    uint64_t amtime, bmtime;
    Status as = a_->GetFileModificationTime(fname, &amtime);
    Status bs = b_->GetFileModificationTime(fname, &bmtime);
    assert(as == bs);
    assert(!as.ok() || amtime - bmtime < 10000 || bmtime - amtime < 10000);
    *file_mtime = amtime;
    return as;
  }

  Status RenameFile(const std::string& s, const std::string& t) override {
    Status as = a_->RenameFile(s, t);
    Status bs = b_->RenameFile(s, t);
    assert(as == bs);
    return as;
  }

  Status LinkFile(const std::string& s, const std::string& t) override {
    Status as = a_->LinkFile(s, t);
    Status bs = b_->LinkFile(s, t);
    assert(as == bs);
    return as;
  }

  class FileLockMirror : public FileLock {
   public:
    FileLock* a_, *b_;
    FileLockMirror(FileLock* a, FileLock* b) : a_(a), b_(b) {}
  };

  Status LockFile(const std::string& f, FileLock** l) override {
    FileLock* al, *bl;
    Status as = a_->LockFile(f, &al);
    Status bs = b_->LockFile(f, &bl);
    assert(as == bs);
    if (as.ok()) *l = new FileLockMirror(al, bl);
    return as;
  }

  Status UnlockFile(FileLock* l) override {
    FileLockMirror* ml = static_cast<FileLockMirror*>(l);
    Status as = a_->UnlockFile(ml->a_);
    Status bs = b_->UnlockFile(ml->b_);
    assert(as == bs);
    delete ml;
    return as;
  }
};

}  // namespace rocksdb

#endif  // ROCKSDB_LITE
