#ifndef _CEGOLOCKHANDLER_H_INCLUDED_
#define _CEGOLOCKHANDLER_H_INCLUDED_
///////////////////////////////////////////////////////////////////////////////
//                                                         
// CegoLockHandler.h
// -----------------
// Cego lock handler class definition
//     
// Design and Implementation by Bjoern Lemke
//
// (C)opyright 2000-2019 Bjoern Lemke
//
// INTERFACE MODULE
//
// Class: CegoLockHandler
// 
// Description: All semaphore lock operations on database files, pool buffers, pages and records level
//              are managed using the LockHandler class.
//              A number of available semaphores is distributed among all required lock operations.
//              
//             
// Status: CLEAN 
//
///////////////////////////////////////////////////////////////////////////////

// CEGO INCLUDES
#include "CegoDefs.h"
#include "CegoDataPointer.h"
#include "CegoBufferPage.h"
#include "CegoObject.h"

class CegoDatabaseManager;

class CegoLockHandler {
    
public:

    enum LockMode { READ, WRITE };

    CegoLockHandler(CegoDatabaseManager* pDBMng);
    ~CegoLockHandler();

    void initLocks();
    void deleteLocks();

    unsigned long long lockRecord(const CegoDataPointer& dp, enum LockMode lockMode);
    void unlockRecord(unsigned long long id);

    unsigned long long lockRBRecord(const CegoDataPointer& dp, enum LockMode lockMode);
    void unlockRBRecord(unsigned long long id);

    unsigned long long lockSysRecord(const CegoDataPointer& dp, enum LockMode lockMode);
    void unlockSysRecord(unsigned long long id);

    unsigned long long lockSysPage(PageIdType pageId, enum LockMode lockMode);
    void unlockSysPage(unsigned long long id);
    
    unsigned long long lockData(CegoObject::ObjectType type, PageIdType pageId, enum LockMode lockMode);
    void unlockData(CegoObject::ObjectType type, unsigned long long id);

    void lockDataFile(int fileId, enum LockMode lockMode);
    void unlockDataFile(int fileId);

    void lockBufferPool(int hashId, enum LockMode lockMode);
    void unlockBufferPool(int hashId);

    void lockBufferPool();
    void unlockBufferPool();

    void getLockStat(int semId, Chain& lockName, int& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);
    void getAggLockStat(const Chain& lockName, int& numLock, int& lockCount, unsigned long long &numRdLock, unsigned long long &numWrLock, unsigned long long &sumRdDelay, unsigned long long &sumWrDelay);

private:

    unsigned long long lockDataPage(PageIdType pageId, enum LockMode lockMode);
    void unlockDataPage(unsigned long long id);

    unsigned long long lockIndexPage(PageIdType pageId, enum LockMode lockMode);
    void unlockIndexPage(unsigned long long id);

    unsigned long long lockRBPage(PageIdType pageId, enum LockMode lockMode);
    void unlockRBPage(unsigned long long id);

    unsigned long long _nextLockId;

    int *_lockCount; 

    struct RecordLock
    {
 	unsigned long long lockId;
	int semId;
    } *_recordLock, *_rbRecordLock, *_sysRecordLock; 
    
    struct PageLock
    {
	unsigned long long lockId;
	PageIdType pageId;
	int semId;
    } *_sysPageLock, 
	  *_dataPageLock, 
	  *_idxPageLock,
	  *_rbPageLock;
        
    int _numRecSema;
    int _numRBRecSema;
    int _numSysRecSema;

    int _numSysPageSema;
    int _numDataPageSema;
    int _numIdxPageSema;
    int _numRBPageSema;
    int _numDataFileSema;
    int _numBufferPoolSema;

    int _numSema;

    int _pageLockTimeout;
    int _recLockTimeout;
    int _fileLockTimeout;
    int _poolLockTimeout;
    int _numLockTries;

    int _poolLockRange;
    
    CegoDatabaseManager *_pDBMng;

    unsigned long _modId;

};

#endif
