// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#ifndef KUDU_CODEGEN_ROW_PROJECTOR_H
#define KUDU_CODEGEN_ROW_PROJECTOR_H

#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <memory>
#include <vector>

#include <glog/logging.h>

#include "kudu/codegen/jit_wrapper.h"
#include "kudu/common/row.h"
#include "kudu/common/rowblock.h"
#include "kudu/common/schema.h"
#include "kudu/gutil/macros.h"
#include "kudu/gutil/port.h"
#include "kudu/gutil/ref_counted.h"
#include "kudu/util/status.h"

namespace llvm {
class TargetMachine;
} // namespace llvm

namespace kudu {

class Arena;
class faststring;

namespace codegen {

// The JITWrapper for codegen::RowProjector functions. Contains
// the compiled functions themselves as well as the schemas used
// to generate them.
class RowProjectorFunctions : public JITWrapper {
 public:
  // Compiles the row projector functions for the given base
  // and projection.
  // Writes the llvm::TargetMachine* used to 'tm' (if not NULL)
  // and the functions to 'out' upon success.
  static Status Create(const Schema& base_schema, const Schema& projection,
                       scoped_refptr<RowProjectorFunctions>* out,
                       llvm::TargetMachine** tm = NULL);

  const Schema& base_schema() { return base_schema_; }
  const Schema& projection() { return projection_; }

  typedef bool(*ProjectionFunction)(const uint8_t*, RowBlockRow*, Arena*);
  ProjectionFunction read() const { return read_f_; }
  ProjectionFunction write() const { return write_f_; }

  virtual Status EncodeOwnKey(faststring* out) OVERRIDE {
    return EncodeKey(base_schema_, projection_, out);
  }

  static Status EncodeKey(const Schema& base, const Schema& proj,
                          faststring* out);

 private:
  RowProjectorFunctions(const Schema& base_schema, const Schema& projection,
                        ProjectionFunction read_f, ProjectionFunction write_f,
                        std::unique_ptr<JITCodeOwner> owner);

  const Schema base_schema_, projection_;
  const ProjectionFunction read_f_, write_f_;
};

// This projector behaves the almost the same way as a tablet/RowProjector except that
// it only supports certain row types, and expects a regular Arena. Furthermore,
// the Reset() public method is unsupported.
//
// See documentation for RowProjector. Any differences in the API will be explained
// in this class.
class RowProjector {
 public:
  typedef kudu::RowProjector::ProjectionIdxMapping ProjectionIdxMapping;

  // Requires that both schemas remain valid for the lifetime of this
  // object. Also requires that the schemas are compatible with
  // the schemas used to create 'functions'.
  RowProjector(const Schema* base_schema, const Schema* projection,
               scoped_refptr<RowProjectorFunctions> functions);

  Status Init();

  // Ignores relocations if dst_arena == NULL
  template<class ContiguousRowType>
  Status ProjectRowForRead(const ContiguousRowType& src_row,
                           RowBlockRow* dst_row,
                           Arena* dst_arena) const {
    DCHECK_SCHEMA_EQ(*base_schema(), *src_row.schema());
    DCHECK_SCHEMA_EQ(*projection(), *dst_row->schema());
    RowProjectorFunctions::ProjectionFunction f = functions_->read();
    if (PREDICT_TRUE(f(src_row.row_data(), dst_row, dst_arena))) {
      return Status::OK();
    }
    return Status::IOError("out of memory copying slice during projection. "
                           "Base schema row: ", base_schema()->DebugRow(src_row));
  }

  // Warning: the projection schema should have write-defaults defined
  // if it has default columns. There was no check for default write
  // columns during this class' initialization.
  // Ignores relocations if dst_arena == NULL
  template<class ContiguousRowType>
  Status ProjectRowForWrite(const ContiguousRowType& src_row,
                            RowBlockRow* dst_row,
                            Arena* dst_arena) const {
    DCHECK_SCHEMA_EQ(*base_schema(), *src_row.schema());
    DCHECK_SCHEMA_EQ(*projection(), *dst_row->schema());
    RowProjectorFunctions::ProjectionFunction f = functions_->write();
    if (PREDICT_TRUE(f(src_row.row_data(), dst_row, dst_arena))) {
      return Status::OK();
    }
    return Status::IOError("out of memory copying slice during projection. "
                           "Base schema row: ", base_schema()->DebugRow(src_row));
  }

  const std::vector<ProjectionIdxMapping>& base_cols_mapping() const {
    return projector_.base_cols_mapping();
  }
  const std::vector<size_t>& projection_defaults() const {
    return projector_.projection_defaults();
  }
  bool is_identity() const { return projector_.is_identity(); }
  const Schema* projection() const { return projector_.projection(); }
  const Schema* base_schema() const { return projector_.base_schema(); }

 private:
  kudu::RowProjector projector_;
  scoped_refptr<RowProjectorFunctions> functions_;

  DISALLOW_COPY_AND_ASSIGN(RowProjector);
};

extern std::ostream& operator<<(std::ostream& o, const RowProjector& rp);

} // namespace codegen
} // namespace kudu

#endif
