/*
 * Copyright (c) 2016 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * For use for simulation and test purposes only
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * Author: Brandon Potter
 */

#ifndef __FD_ENTRY_HH__
#define __FD_ENTRY_HH__

#include <memory>
#include <ostream>
#include <string>

#include "sim/serialize.hh"

class EmulatedDriver;

/**
 * Holds a single file descriptor mapping and that mapping's data for
 * processes running in syscall emulation mode.
 */
class FDEntry : public Serializable
{
  public:
    FDEntry(bool close_on_exec = false)
        : _closeOnExec(close_on_exec)
    { }

    virtual std::shared_ptr<FDEntry> clone() const = 0;

    inline bool getCOE() const { return _closeOnExec; }

    inline void setCOE(bool close_on_exec) { _closeOnExec = close_on_exec; }

    virtual void serialize(CheckpointOut &cp) const;
    virtual void unserialize(CheckpointIn &cp);

  protected:
    bool _closeOnExec;
};

/**
 * Extends the base class to include a host-backed file descriptor field
 * that records the integer used to represent the file descriptor on the host
 * and the file's flags.
 */
class HBFDEntry: public FDEntry
{
  public:
    HBFDEntry(int flags, int sim_fd, bool close_on_exec = false)
        : FDEntry(close_on_exec), _flags(flags), _simFD(sim_fd)
    { }

    inline int getFlags() const { return _flags; }
    inline int getSimFD() const { return _simFD; }

    inline void setFlags(int flags) { _flags = flags; }
    inline void setSimFD(int sim_fd) { _simFD = sim_fd; }

  protected:
    int _flags;
    int _simFD;
};

/**
 * Holds file descriptors for host-backed files; host-backed files are
 * files which were opened on the physical machine where the simulation
 * is running (probably the thing on/under your desk). All regular files
 * are redirected to make it appear that the file descriptor assignment
 * starts at file descriptor '3' (not including stdin, stdout, stderr) and
 * then grows upward.
 */
class FileFDEntry: public HBFDEntry
{
  public:
    FileFDEntry(int sim_fd, int flags, std::string const& file_name,
                uint64_t file_offset, bool close_on_exec = false)
        : HBFDEntry(flags, sim_fd, close_on_exec),
          _fileName(file_name), _fileOffset(file_offset)
    { }

    FileFDEntry(FileFDEntry const& reg, bool close_on_exec = false)
        : HBFDEntry(reg._flags, reg._simFD, close_on_exec),
          _fileName(reg._fileName), _fileOffset(reg._fileOffset)
    { }

    inline std::shared_ptr<FDEntry>
    clone() const override
    {
        return std::make_shared<FileFDEntry>(*this);
    }

    inline std::string getFileName() const { return _fileName; }
    inline uint64_t getFileOffset() const { return _fileOffset; }

    inline void setFileName(std::string file_name) { _fileName = file_name; }
    inline void setFileOffset (uint64_t f_off) { _fileOffset = f_off; }

    void serialize(CheckpointOut &cp) const override;
    void unserialize(CheckpointIn &cp) override;

  private:
    std::string _fileName;
    uint64_t _fileOffset;
};

/**
 * Holds the metadata needed to maintain the mappings for file descriptors
 * allocated with the pipe() system calls and its variants.
 */
class PipeFDEntry: public HBFDEntry
{
  public:
    enum EndType {
        read = 0,
        write = 1
    };

    PipeFDEntry(int sim_fd, int flags, EndType pipe_end_type,
                bool close_on_exec = false)
        : HBFDEntry(flags, sim_fd, close_on_exec), _pipeReadSource(-1),
          _pipeEndType(pipe_end_type)
    { }

    PipeFDEntry(PipeFDEntry const& pipe, bool close_on_exec = false)
        : HBFDEntry(pipe._flags, pipe._simFD, close_on_exec),
          _pipeReadSource(pipe._pipeReadSource),
          _pipeEndType(pipe._pipeEndType)
    { }

    inline std::shared_ptr<FDEntry>
    clone() const override
    {
        return std::make_shared<PipeFDEntry>(*this);
    }

    inline EndType getEndType() const { return _pipeEndType; }
    inline int getPipeReadSource() const { return _pipeReadSource; }

    inline void setPipeReadSource(int tgt_fd) { _pipeReadSource = tgt_fd; }
    inline void setEndType(EndType type) { _pipeEndType = type; }

    void serialize(CheckpointOut &cp) const override;
    void unserialize(CheckpointIn &cp) override;

  private:
    int _pipeReadSource;
    EndType _pipeEndType;
};

/**
 * Holds file descriptors needed to simulate devices opened with pseudo
 * files (commonly with calls to ioctls).
 */
class DeviceFDEntry : public FDEntry
{
  public:
    DeviceFDEntry(EmulatedDriver *driver, std::string const& file_name,
                  bool close_on_exec = false)
        : FDEntry(close_on_exec), _driver(driver), _fileName(file_name)
    { }

    DeviceFDEntry(DeviceFDEntry const& dev, bool close_on_exec = false)
        : FDEntry(close_on_exec), _driver(dev._driver),
          _fileName(dev._fileName)
    { }

    std::shared_ptr<FDEntry>
    clone() const override
    {
        return std::make_shared<DeviceFDEntry>(*this);
    }

    inline EmulatedDriver *getDriver() const { return _driver; }
    inline std::string getFileName() const { return _fileName; }

    void serialize(CheckpointOut &cp) const override;
    void unserialize(CheckpointIn &cp) override;

  private:
    EmulatedDriver *_driver;
    std::string _fileName;
};

#endif // __FD_ENTRY_HH__
