// $Id: JGProcProgStorage.h,v 1.2 2003/02/15 04:18:09 fukasawa Exp $

//=============================================================================
/**
 *  @file    JGProcProg.h
 *
 *  @author  Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 2001-2003 BEE Co.,Ltd. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
//=============================================================================

#ifndef JGPROCPROGSTORAGE_H
#define JGPROCPROGSTORAGE_H

#include "JGMemoryMappedFile.h"
#include "JGLogTime.h"
#include "ace/Process_Mutex.h"

class JGEquipment;
class JGVariable;
class JGBitVector;
class JGFile;

enum { MAX_PROCPROG_COUNT = 4096 };

// Proccess Program Control Block
struct ProcProgBlock
{
    enum { NAME_LENGTH = 130 };   // 128 + 2
    enum { PPID_LENGTH = 82 };    // 80 + 2

    BCHAR     m_fname[NAME_LENGTH];
    BCHAR     m_ppid[PPID_LENGTH];
    size_t    m_size;
    JGLogTime m_time;               // Edit time

    //
    ProcProgBlock() : m_size(0) {
            memset(m_fname, 0, NAME_LENGTH); memset(m_ppid, 0, PPID_LENGTH);
        }
    ProcProgBlock(const string& fname, const string& ppid, size_t size,
                  const JGLogTime& logtm) {
            memmove(m_fname, fname.c_str(), min(NAME_LENGTH-1, fname.size()));
            m_fname[NAME_LENGTH-1] = '\0';
            memmove(m_ppid, ppid.c_str(), min(PPID_LENGTH-1, ppid.size()));
            m_ppid[PPID_LENGTH-1] = '\0';
            m_size = size;
            m_time = logtm;
        }
    ProcProgBlock(const ProcProgBlock& rhs) { copy(rhs); }
    ProcProgBlock& operator=(const ProcProgBlock& rhs) {
            if (this == &rhs)
                return *this;
            copy(rhs);
            return *this;
        }

    void copy(const ProcProgBlock& rhs) {
            memmove(m_fname, rhs.m_fname, NAME_LENGTH);
            memmove(m_ppid, rhs.m_ppid, PPID_LENGTH);
            m_size = rhs.m_size;
            m_time = rhs.m_time;
        }

    void getFileName(string& retName) { retName = m_fname; }
    void getName(string& retName)     { retName = m_ppid; }
    void getID(JGid& retID)           { retID = m_ppid; }
    void setID(JGid& ppid);
    int erase() {
            m_fname[0] = '\0'; m_ppid[0] = '\0'; m_size = 0; return 0;
        }
    bool deleted() {
            if (ACE_OS::strlen(m_fname) == 0 || ACE_OS::strlen(m_ppid) == 0 ||
                m_size == 0) {
                return true;
            }
            return false;
        }
};

//
// Layout of process program control storage (mmap)
//
//  +-------------------------+
//  |   Revision Number       | (24 bytes)
//  +-------------------------+
//  |  Process Program Count  | (4 bytes)
//  +-------------------------+
//  |   Control Header Size   | (4 bytes)
//  +-------------------------+
//  |      Current Size       | (4 bytes)
//  +-------------------------+
//  |                         |
//  =   (Block Usage BitMap)  = ((Process Program Count / 32) * 4 bytes)
//  |                         | (4 bytes)
//  +-------------------------+
//  |                         |
//  |   Control Header Data   |
//  =     (ProcProgBlock)     =
//  |                         |
//  +-------------------------+
//
#define PROCPROG_BLOCK_REVISION       0
#define PROCPROG_BLOCK_COUNT          24
#define PROCPROG_BLOCK_SIZE           28
#define PROCPROG_CURRENT_SIZE         32

struct ProcProgHeader
{
    char m_revision[24];
    int  m_blockCount;
    int  m_blockSize;
    int  m_cursize;
};

#define PROCPROG_DATA_TOP(x)   (sizeof(ProcProgHeader) + BITMAP_BYTES(x))


typedef map<JGid, ProcProgBlock *, id_less, allocator<ProcProgBlock *> >
        PPBlockTable;
typedef PPBlockTable::value_type  PPBlockPair;

//
// Process Program Storage
//
class JGProcProgStorage : public JGMemoryMappedFile
{
public:
    JGProcProgStorage(const string& dir, const string& ppext);
    ~JGProcProgStorage() { fini(); }

    int  init(size_t maxsize = MAX_PROCPROG_COUNT);
    void dump() const;

    int  put(JGid& ppid, BYTE * datap, size_t size);
    int  get(JGid& ppid, BYTE*& datap, size_t& size);
    int  del(JGid& ppid);
    int  create(JGid& ppid);
    int  purge();
    bool full() const { return (m_pph->m_cursize >= m_pph->m_blockCount); }
    size_t cursize() const { return m_pph->m_cursize; }
    size_t maxsize() const { return m_pph->m_blockCount; }
    ProcProgBlock * find(JGid& ppid);
    ProcProgBlock * find(const string& ppid);
    int all(vector<JGid>& ids);

private:
    void fini();
    int  readHeader(ProcProgHeader& buf);
    ProcProgBlock * makeProcProgBlock(JGid& ppid, size_t size = 0);
    JGFile * openProgram(ProcProgBlock * ppblock, const string& caller);
    void     ppid2fname(JGid& ppid, string& fname);

// member variables
private:
    string m_ppext;
    ProcProgHeader *  m_pph;
    size_t            m_maxsize;
    JGBitVector *     m_usage;
    PPBlockTable      m_blockTable;     // vector of blocks
    ProcProgBlock *   m_top;            // data top address in mmap

    ACE_Process_Mutex m_pplock;         // mutex of other process
};


#endif  /* JGPROCPROGSTORAGE_H */
