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


#include <package/hpkg/DataReader.h>
#include <package/PackageFlags.h>
#include <package/PackageArchitecture.h>

#include <WeakReferenceable.h>

#include <util/DoublyLinkedList.h>
#include <util/OpenHashTable.h>
#include <util/StringHash.h>

#include <lock.h>

#include "Dependency.h"
#include "PackageNode.h"
#include "Resolvable.h"
#include "String.h"


using BPackageKit::BPackageArchitecture;
using BPackageKit::BHPKG::BAbstractBufferedDataReader;


class PackageLinkDirectory;
class PackagesDirectory;
class PackageSettings;
class Volume;
class Version;


class Package : public BWeakReferenceable,
        public DoublyLinkedListLinkImpl<Package> {
public:
                                                                Package(::Volume* volume,
                                                                        PackagesDirectory* directory,
                                                                        dev_t deviceID, ino_t nodeID);
                                                                ~Package();

                        status_t                        Init(const char* fileName);
                        status_t                        Load(const PackageSettings& settings);

                        ::Volume*                       Volume() const          { return fVolume; }
                        const String&           FileName() const        { return fFileName; }

                        void                            SetName(const String& name);
                        const String&           Name() const            { return fName; }

                        const String&           VersionedName() const
                                                                        { return fVersionedName; }

                        dev_t                           DeviceID() const
                                                                        { return fDeviceID; }
                        ino_t                           NodeID() const
                                                                        { return fNodeID; }
                        PackagesDirectory*      Directory() const
                                                                        { return fPackagesDirectory; }

                        void                            SetInstallPath(const String& installPath);
                        const String&           InstallPath() const     { return fInstallPath; }

                        void                            SetVersion(::Version* version);
                                                                        // takes over object ownership
                        ::Version*                      Version() const
                                                                        { return fVersion; }

                        void                            SetFlags(uint32 flags)
                                                                        { fFlags = flags; }
                        uint32                          Flags() const
                                                                        { return fFlags; }

                        void                            SetArchitecture(
                                                                        BPackageArchitecture architecture)
                                                                        { fArchitecture = architecture; }
                        BPackageArchitecture Architecture() const
                                                                        { return fArchitecture; }
                        const char*                     ArchitectureName() const;

                        void                            SetLinkDirectory(
                                                                        PackageLinkDirectory* linkDirectory)
                                                                        { fLinkDirectory = linkDirectory; }
                        PackageLinkDirectory* LinkDirectory() const
                                                                        { return fLinkDirectory; }

                        Package*&                       FileNameHashTableNext()
                                                                        { return fFileNameHashTableNext; }

                        void                            AddNode(PackageNode* node);
                        void                            AddResolvable(Resolvable* resolvable);
                        void                            AddDependency(Dependency* dependency);

                        int                                     Open();
                        void                            Close();

                        status_t                        CreateDataReader(const PackageData& data,
                                                                        BAbstractBufferedDataReader*& _reader);

                        const PackageNodeList& Nodes() const    { return fNodes; }
                        const ResolvableList& Resolvables() const
                                                                        { return fResolvables; }
                        const DependencyList& Dependencies() const
                                                                        { return fDependencies; }

private:
                        struct LoaderErrorOutput;
                        struct LoaderContentHandler;
                        struct LoaderContentHandlerV1;
                        struct HeapReader;
                        struct HeapReaderV1;
                        struct HeapReaderV2;
                        struct CachingPackageReader;

private:
                        status_t                        _Load(const PackageSettings& settings);
                        bool                            _InitVersionedName();

private:
                        mutex                           fLock;
                        ::Volume*                       fVolume;
                        PackagesDirectory*      fPackagesDirectory;
                        String                          fFileName;
                        String                          fName;
                        String                          fInstallPath;
                        String                          fVersionedName;
                        ::Version*                      fVersion;
                        uint32                          fFlags;
                        BPackageArchitecture fArchitecture;
                        PackageLinkDirectory* fLinkDirectory;
                        int                                     fFD;
                        uint32                          fOpenCount;
                        HeapReader*                     fHeapReader;
                        Package*                        fFileNameHashTableNext;
                        ino_t                           fNodeID;
                        dev_t                           fDeviceID;
                        PackageNodeList         fNodes;
                        ResolvableList          fResolvables;
                        DependencyList          fDependencies;
};


struct PackageCloser {
        PackageCloser(Package* package)
                :
                fPackage(package)
        {
        }

        ~PackageCloser()
        {
                if (fPackage != NULL)
                        fPackage->Close();
        }

        void Detach()
        {
                fPackage = NULL;
        }

private:
        Package*        fPackage;
};


struct PackageFileNameHashDefinition {
        typedef const char*             KeyType;
        typedef Package                 ValueType;

        size_t HashKey(const char* key) const
        {
                return hash_hash_string(key);
        }

        size_t Hash(const Package* value) const
        {
                return value->FileName().Hash();
        }

        bool Compare(const char* key, const Package* value) const
        {
                return strcmp(value->FileName(), key) == 0;
        }

        Package*& GetLink(Package* value) const
        {
                return value->FileNameHashTableNext();
        }
};


typedef BOpenHashTable<PackageFileNameHashDefinition> PackageFileNameHashTable;
typedef DoublyLinkedList<Package> PackageList;


#endif  // PACKAGE_H