OidSpaceMap.h

// OidSpaceMap.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2010

@import "IPersistable.h"
@import "IPrefVisitor.h"
@import "pref.h"
@import "OidSpace.h"
@import "Ceda/cxObject/Guid2.h"
@import "Ceda/cxObject/WCSpace.h"
#include "Ceda/cxUtils/Archive.h"
#include "Ceda/cxUtils/xvector.h"
#include <map>

/*
OidSpaceMap
------------

Each WorkingSet has a single OidSpaceMap.

An OidSpaceMap is an IPersistable object which records a bijective mapping between a 32 bit OidHigh and 
128 bit OidSpaceGuid.  

This is the basis for allowing local Oids to map to globally unique identifiers (160 bit goids), and 
therefore to allow OidHighs to be translated as they are received over the wire

It is assumed all access to a given OidSpaceMap instance is protected by the CSpace mutex.

The concept of OidSpaceGuid is completely decoupled from the LSS - i.e. none of the modules in the LSS 
mention the concept of the OidSpaceGuid.

This is a quick and dirty implementation,  that is only suitable when there are a relatively small 
number of OidSpaceGuid's.  More generally it will be necessary to use data structures that lazily 
load from disk yet minimise the number of seeks.
*/

namespace ceda
{
$class+ OidSpaceMap isa IPersistable 
{
public:
    $implementing IPersistable {Serialise Deserialise};

    //////////// Read access //////////////

    void Write(xostream& os) const;

    ssize_t size() const;

    // Get the OidHigh for the given OidSpaceGuid, or returns 0 if not found
    OidHigh GetOidHigh(const OidSpaceGuid& osg) const;

    bool GetOidSpaceGuid(OidHigh oh, OidSpaceGuid& osg) const;

    //////////// Write access //////////////

    // Never returns 0
    OidHigh GetOrCreateOidHigh(const OidSpaceGuid& osg);

    void Add(OidHigh oh, const OidSpaceGuid& osg);

    const std::map<OidHigh,OidSpaceGuid>& GetOidHighToGuidMap() const; 

    // Allows for processing the changes to this OidSpaceMap in batches
    void SwapOutOidHighsDelta(xvector<OidHigh>& delta);

private:
    void GetOrCreateOidSpaceGuid(OidHigh oh, OidSpaceGuid& osg);
    void RemoveOidHigh(OidHigh oh);
    
private:
    ////////////////// Persistent

    typedef std::map<OidHigh,OidSpaceGuid> NAME_MAP;
    NAME_MAP nameMap_;

    ////////////////// Transient 

    // The inverse of nameMap_
    typedef std::map<OidSpaceGuid,OidHigh> ID_MAP;
    ID_MAP idMap_;

    // Records information about changes. i.e. a "delta" indicating what has changed since 
    // processing the last delta.
    //
    // Every time an (OidHigh,OidSpaceGuid) pair is created and inserted into the maps, the OidHigh
    // is also added to this vector.
    // The OidHighs in this vector can be "swapped out" in order to allow some process to efficiently
    // process the new OidHighs in batches, without any need for callbacks at the time an OidHigh
    // is created.
    //
    // Note that after deserialisation of the OidSpaceMap newOidHighsDelta_ is empty.
    xvector<OidHigh> newOidHighsDelta_;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// OidSpaceMapMixin

$mixin OidSpaceMapMixin
{
    void VisitObjects(IObjectVisitor& v) const
    {
        cxAssert(HaveLockedCSpace());
        BaseClass::VisitObjects(v);
        v << m_oidSpaceMap;
    }

    void VisitPrefs(IPrefVisitor& v) const
    {
        cxAssert(HaveLockedCSpace());
        BaseClass::VisitPrefs(v);
        v << m_oidSpaceMap;
    }
    
    void OnCreate(bool local)
    {
        cxAssert(HaveLockedCSpace());
        BaseClass::OnCreate(local);
        m_oidSpaceMap = $new OidSpaceMap;
    }

    OidSpaceMap& GetOidSpaceMap() { return *m_oidSpaceMap; }

protected:
    cref<OidSpaceMap> m_oidSpaceMap;
};

} // namespace ceda