* Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef VOLUME_H
#define VOLUME_H
#include <fs_interface.h>
#include <condition_variable.h>
#include <lock.h>
#include <util/AutoLock.h>
#include <util/DoublyLinkedList.h>
#include <util/KMessage.h>
#include <packagefs.h>
#include "Index.h"
#include "Node.h"
#include "NodeListener.h"
#include "Package.h"
#include "PackageLinksListener.h"
#include "PackagesDirectory.h"
#include "PackageSettings.h"
#include "Query.h"
class Directory;
class PackageFSRoot;
class PackagesDirectory;
class UnpackingNode;
typedef IndexHashTable::Iterator IndexDirIterator;
typedef PackageFSMountType MountType;
class Volume : public DoublyLinkedListLinkImpl<Volume>,
private PackageLinksListener {
public:
Volume(fs_volume* fsVolume);
~Volume();
inline bool ReadLock() const;
inline void ReadUnlock() const;
inline bool WriteLock();
inline void WriteUnlock();
inline bool IsWriteLocked() const;
fs_volume* FSVolume() const { return fFSVolume; }
dev_t ID() const { return fFSVolume->id; }
Directory* RootDirectory() const { return fRootDirectory; }
::MountType MountType() const { return fMountType; }
void SetPackageFSRoot(::PackageFSRoot* root)
{ fPackageFSRoot = root; }
::PackageFSRoot* PackageFSRoot() const
{ return fPackageFSRoot; }
dev_t MountPointDeviceID() const
{ return fMountPoint.deviceID; }
ino_t MountPointNodeID() const
{ return fMountPoint.nodeID; }
status_t Mount(const char* parameterString);
void Unmount();
Node* FindNode(ino_t nodeID) const
{ return fNodes.Lookup(nodeID); }
status_t IOCtl(Node* node, uint32 operation,
void* buffer, size_t size);
void AddNodeListener(NodeListener* listener,
Node* node);
void RemoveNodeListener(NodeListener* listener);
void AddQuery(Query* query);
void RemoveQuery(Query* query);
void UpdateLiveQueries(Node* node,
const char* attribute, int32 type,
const void* oldKey, size_t oldLength,
const void* newKey, size_t newLength);
Index* FindIndex(const StringKey& name) const
{ return fIndices.Lookup(name); }
IndexDirIterator GetIndexDirIterator() const
{ return fIndices.GetIterator(); }
status_t GetVNode(ino_t nodeID, Node*& _node);
status_t PutVNode(ino_t nodeID);
status_t RemoveVNode(ino_t nodeID);
status_t PublishVNode(Node* node);
private:
virtual void PackageLinkNodeAdded(Node* node);
virtual void PackageLinkNodeRemoved(Node* node);
virtual void PackageLinkNodeChanged(Node* node,
uint32 statFields,
const OldNodeAttributes& oldAttributes);
private:
struct ShineThroughDirectory;
struct ActivationChangeRequest;
private:
status_t _LoadOldPackagesStates(
const char* packagesState);
status_t _AddInitialPackages();
status_t _AddInitialPackagesFromActivationFile(
PackagesDirectory* packagesDirectory);
status_t _AddInitialPackagesFromDirectory();
status_t _LoadAndAddInitialPackage(
PackagesDirectory* packagesDirectory,
const char* name);
inline void _AddPackage(Package* package);
inline void _RemovePackage(Package* package);
void _RemoveAllPackages();
inline Package* _FindPackage(const char* fileName) const;
status_t _AddPackageContent(Package* package,
bool notify);
void _RemovePackageContent(Package* package,
PackageNode* endNode, bool notify);
status_t _AddPackageContentRootNode(Package* package,
PackageNode* node, bool notify);
void _RemovePackageContentRootNode(Package* package,
PackageNode* packageNode,
PackageNode* endPackageNode, bool notify);
status_t _AddPackageNode(Directory* directory,
PackageNode* packageNode, bool notify,
Node*& _node);
void _RemovePackageNode(Directory* directory,
PackageNode* packageNode, Node* node,
bool notify);
status_t _CreateUnpackingNode(mode_t mode,
Directory* parent, const String& name,
UnpackingNode*& _node);
void _RemoveNode(Node* node);
void _RemoveNodeAndVNode(Node* node);
status_t _LoadPackage(
PackagesDirectory* packagesDirectory,
const char* name, Package*& _package);
status_t _ChangeActivation(
ActivationChangeRequest& request);
status_t _InitMountType(const char* mountType);
status_t _CreateShineThroughDirectory(Directory* parent,
const char* name, Directory*& _directory);
status_t _CreateShineThroughDirectories(
const char* shineThroughSetting);
status_t _PublishShineThroughDirectories();
status_t _AddPackageLinksDirectory();
void _RemovePackageLinksDirectory();
void _AddPackageLinksNode(Node* node);
void _RemovePackageLinksNode(Node* node);
inline Volume* _SystemVolumeIfNotSelf() const;
void _NotifyNodeAdded(Node* node);
void _NotifyNodeRemoved(Node* node);
void _NotifyNodeChanged(Node* node,
uint32 statFields,
const OldNodeAttributes& oldAttributes);
private:
mutable rw_lock fLock;
fs_volume* fFSVolume;
Directory* fRootDirectory;
::PackageFSRoot* fPackageFSRoot;
::MountType fMountType;
PackagesDirectory* fPackagesDirectory;
PackagesDirectoryList fPackagesDirectories;
PackagesDirectoryHashTable fPackagesDirectoriesByNodeRef;
PackageSettings fPackageSettings;
struct {
dev_t deviceID;
ino_t nodeID;
} fMountPoint;
NodeIDHashTable fNodes;
NodeListenerHashTable fNodeListeners;
PackageFileNameHashTable fPackages;
QueryList fQueries;
IndexHashTable fIndices;
ino_t fNextNodeID;
};
bool
Volume::ReadLock() const
{
return rw_lock_read_lock(&fLock) == B_OK;
}
void
Volume::ReadUnlock() const
{
rw_lock_read_unlock(&fLock);
}
bool
Volume::WriteLock()
{
return rw_lock_write_lock(&fLock) == B_OK;
}
void
Volume::WriteUnlock()
{
rw_lock_write_unlock(&fLock);
}
bool
Volume::IsWriteLocked() const
{
return find_thread(NULL) == fLock.holder;
}
typedef AutoLocker<const Volume, AutoLockerReadLocking<const Volume> >
VolumeReadLocker;
typedef AutoLocker<Volume, AutoLockerWriteLocking<Volume> > VolumeWriteLocker;
#endif