root/src/add-ons/kernel/file_systems/packagefs/volume/PackageFSRoot.h
/*
 * Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Distributed under the terms of the MIT License.
 */
#ifndef PACKAGE_FS_ROOT_H
#define PACKAGE_FS_ROOT_H


#include <Referenceable.h>

#include <util/AutoLock.h>
#include <util/DoublyLinkedList.h>

#include <lock.h>

#include "DependencyFamily.h"
#include "ResolvableFamily.h"
#include "Volume.h"


class PackageLinksDirectory;


class PackageFSRoot : private BReferenceable,
        public DoublyLinkedListLinkImpl<PackageFSRoot> {
public:
        // constructor and destructor are conceptually private
                                                                PackageFSRoot(dev_t deviceID, ino_t nodeID);
        virtual                                         ~PackageFSRoot();

        static  status_t                        GlobalInit();
        static  void                            GlobalUninit();

        inline  bool                            ReadLock() const;
        inline  void                            ReadUnlock() const;
        inline  bool                            WriteLock();
        inline  void                            WriteUnlock();

                        status_t                        Init();

        static  status_t                        RegisterVolume(Volume* volume);
                        void                            UnregisterVolume(Volume* volume);

                        status_t                        AddPackage(Package* package);
                        void                            RemovePackage(Package* package);

                        dev_t                           DeviceID() const        { return fDeviceID; }
                        ino_t                           NodeID() const          { return fNodeID; }
                        bool                            IsCustom() const        { return fDeviceID < 0; }

                        Volume*                         SystemVolume() const;
                        PackageLinksDirectory* GetPackageLinksDirectory() const
                                                                        { return fPackageLinksDirectory; }

private:
                        typedef DoublyLinkedList<PackageFSRoot> RootList;
                        typedef DoublyLinkedList<Volume> VolumeList;

private:
                        status_t                        _AddVolume(Volume* volume);
                        void                            _RemoveVolume(Volume* volume);

                        status_t                        _AddPackage(Package* package);
                        void                            _RemovePackage(Package* package);

                        void                            _ResolveDependencies(
                                                                        ResolvableDependencyList& dependencies);
                        void                            _ResolveDependency(Dependency* dependency);

        static  status_t                        _GetOrCreateRoot(dev_t deviceID, ino_t nodeID,
                                                                        PackageFSRoot*& _root);
        static  PackageFSRoot*          _FindRootLocked(dev_t deviceID, ino_t nodeID);
        static  void                            _PutRoot(PackageFSRoot* root);

private:
        static  mutex                           sRootListLock;
        static  RootList                        sRootList;

        mutable rw_lock                         fLock;
                        dev_t                           fDeviceID;
                        ino_t                           fNodeID;
                        VolumeList                      fVolumes;
                        Volume*                         fSystemVolume;
                        PackageLinksDirectory* fPackageLinksDirectory;
                        ResolvableFamilyHashTable fResolvables;
                        DependencyFamilyHashTable fDependencies;
};


bool
PackageFSRoot::ReadLock() const
{
        return rw_lock_read_lock(&fLock) == B_OK;
}


void
PackageFSRoot::ReadUnlock() const
{
        rw_lock_read_unlock(&fLock);
}


bool
PackageFSRoot::WriteLock()
{
        return rw_lock_write_lock(&fLock) == B_OK;
}


void
PackageFSRoot::WriteUnlock()
{
        rw_lock_write_unlock(&fLock);
}


typedef AutoLocker<const PackageFSRoot,
        AutoLockerReadLocking<const PackageFSRoot> > PackageFSRootReadLocker;
typedef AutoLocker<PackageFSRoot, AutoLockerWriteLocking<PackageFSRoot> >
        PackageFSRootWriteLocker;


#endif  // PACKAGE_FS_ROOT_H