Kernel interface abstraction for attribute access

* Introduce interface AttributeCookie and currently only implementation
  UnpackingAttributeCookie. This is an interface for reading/stat()ing
  an attribute.
* Add abstract virtual Node::OpenAttribute() method that returns an
  AttributeCookie and implemented it for derived classes.
* In the kernel interface attribute hooks use AttributeCookie now. The
  attribute directory hooks are unchanged.
This commit is contained in:
Ingo Weinhold 2011-06-23 19:41:56 +02:00
parent 22a808885b
commit 8ae81ef94e
11 changed files with 261 additions and 96 deletions

View File

@ -0,0 +1,12 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "AttributeCookie.h"
AttributeCookie::~AttributeCookie()
{
}

View File

@ -0,0 +1,25 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef ATTRIBUTE_COOKIE_H
#define ATTRIBUTE_COOKIE_H
#include <sys/stat.h>
#include <SupportDefs.h>
class AttributeCookie {
public:
virtual ~AttributeCookie();
virtual status_t Close() = 0;
virtual status_t ReadAttribute(off_t offset, void* buffer,
size_t* bufferSize) = 0;
virtual status_t ReadAttributeStat(struct stat* st) = 0;
};
#endif // ATTRIBUTE_COOKIE_H

View File

@ -7,6 +7,7 @@
#include "Directory.h"
#include "DebugSupport.h"
#include "UnpackingAttributeCookie.h"
#include "Utils.h"
@ -171,6 +172,15 @@ Directory::ReadSymlink(void* buffer, size_t* bufferSize)
}
status_t
Directory::OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie)
{
return UnpackingAttributeCookie::Open(fPackageDirectories.Head(), name,
openMode, _cookie);
}
void
Directory::AddChild(Node* node)
{

View File

@ -51,6 +51,9 @@ public:
virtual status_t ReadSymlink(void* buffer,
size_t* bufferSize);
virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie);
void AddChild(Node* node);
void RemoveChild(Node* node);
Node* FindChild(const char* name);

View File

@ -7,6 +7,7 @@ UsePrivateHeaders shared ;
HAIKU_PACKAGE_FS_SOURCES =
AttributeCookie.cpp
BlockBufferCacheKernel.cpp
DebugSupport.cpp
Dependency.cpp
@ -26,6 +27,7 @@ HAIKU_PACKAGE_FS_SOURCES =
PackageNodeAttribute.cpp
PackageSymlink.cpp
Resolvable.cpp
UnpackingAttributeCookie.cpp
Version.cpp
Volume.cpp
;

View File

@ -10,6 +10,7 @@
#include <algorithm>
#include "UnpackingAttributeCookie.h"
#include "Utils.h"
@ -193,6 +194,15 @@ LeafNode::ReadSymlink(void* buffer, size_t* bufferSize)
}
status_t
LeafNode::OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie)
{
return UnpackingAttributeCookie::Open(fPackageNodes.Head(), name, openMode,
_cookie);
}
const char*
LeafNode::SymlinkPath() const
{

View File

@ -38,6 +38,9 @@ public:
virtual status_t ReadSymlink(void* buffer,
size_t* bufferSize);
virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie);
const char* SymlinkPath() const;
private:

View File

@ -17,6 +17,7 @@
#include <util/OpenHashTable.h>
class AttributeCookie;
class Directory;
class PackageNode;
@ -63,6 +64,9 @@ public:
virtual status_t ReadSymlink(void* buffer,
size_t* bufferSize) = 0;
virtual status_t OpenAttribute(const char* name, int openMode,
AttributeCookie*& _cookie) = 0;
protected:
rw_lock fLock;
ino_t fID;

View File

@ -0,0 +1,142 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "UnpackingAttributeCookie.h"
#include <algorithm>
#include <new>
#include <package/hpkg/DataReader.h>
#include <package/hpkg/PackageData.h>
#include <package/hpkg/PackageDataReader.h>
#include <AutoDeleter.h>
#include "DebugSupport.h"
#include "GlobalFactory.h"
#include "Package.h"
#include "PackageNode.h"
using BPackageKit::BHPKG::BBufferDataReader;
//using BPackageKit::BHPKG::BDataReader;
using BPackageKit::BHPKG::BFDDataReader;
//using BPackageKit::BHPKG::BPackageData;
//using BPackageKit::BHPKG::BPackageDataReader;
static status_t
read_package_data(const BPackageData& data, BDataReader* dataReader,
off_t offset, void* buffer, size_t* bufferSize)
{
// create a BPackageDataReader
BPackageDataReader* reader;
status_t error = GlobalFactory::Default()->CreatePackageDataReader(
dataReader, data, reader);
if (error != B_OK)
RETURN_ERROR(error);
ObjectDeleter<BPackageDataReader> readerDeleter(reader);
// check the offset
if (offset < 0 || (uint64)offset > data.UncompressedSize())
return B_BAD_VALUE;
// clamp the size
size_t toRead = std::min((uint64)*bufferSize,
data.UncompressedSize() - offset);
// read
if (toRead > 0) {
status_t error = reader->ReadData(offset, buffer, toRead);
if (error != B_OK)
RETURN_ERROR(error);
}
*bufferSize = toRead;
return B_OK;
}
UnpackingAttributeCookie::UnpackingAttributeCookie(PackageNode* packageNode,
PackageNodeAttribute* attribute, int openMode)
:
fPackageNode(packageNode),
fPackage(packageNode->GetPackage()),
fAttribute(attribute),
fOpenMode(openMode)
{
fPackageNode->AcquireReference();
fPackage->AcquireReference();
}
UnpackingAttributeCookie::~UnpackingAttributeCookie()
{
fPackageNode->ReleaseReference();
fPackage->ReleaseReference();
}
/*static*/ status_t
UnpackingAttributeCookie::Open(PackageNode* packageNode, const char* name,
int openMode, AttributeCookie*& _cookie)
{
if (packageNode == NULL)
return B_ENTRY_NOT_FOUND;
// get the attribute
PackageNodeAttribute* attribute = packageNode->FindAttribute(name);
if (attribute == NULL)
return B_ENTRY_NOT_FOUND;
// allocate the cookie
UnpackingAttributeCookie* cookie = new(std::nothrow)
UnpackingAttributeCookie(packageNode, attribute, openMode);
if (cookie == NULL)
RETURN_ERROR(B_NO_MEMORY);
_cookie = cookie;
return B_OK;
}
status_t
UnpackingAttributeCookie::Close()
{
return B_OK;
}
status_t
UnpackingAttributeCookie::ReadAttribute(off_t offset, void* buffer,
size_t* bufferSize)
{
const BPackageData& data = fAttribute->Data();
if (data.IsEncodedInline()) {
// inline data
BBufferDataReader dataReader(data.InlineData(), data.CompressedSize());
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
}
// data not inline -- open the package
int fd = fPackage->Open();
if (fd < 0)
RETURN_ERROR(fd);
PackageCloser packageCloser(fPackage);
BFDDataReader dataReader(fd);
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
}
status_t
UnpackingAttributeCookie::ReadAttributeStat(struct stat* st)
{
st->st_size = fAttribute->Data().UncompressedSize();
st->st_type = fAttribute->Type();
return B_OK;
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef UNPACKING_ATTRIBUTE_COOKIE_H
#define UNPACKING_ATTRIBUTE_COOKIE_H
#include "AttributeCookie.h"
class Package;
class PackageNode;
class PackageNodeAttribute;
class UnpackingAttributeCookie : public AttributeCookie {
public:
UnpackingAttributeCookie(
PackageNode* packageNode,
PackageNodeAttribute* attribute,
int openMode);
virtual ~UnpackingAttributeCookie();
static status_t Open(PackageNode* packageNode, const char* name,
int openMode, AttributeCookie*& _cookie);
virtual status_t Close();
virtual status_t ReadAttribute(off_t offset, void* buffer,
size_t* bufferSize);
virtual status_t ReadAttributeStat(struct stat* st);
private:
PackageNode* fPackageNode;
Package* fPackage;
PackageNodeAttribute* fAttribute;
int fOpenMode;
};
#endif // UNPACKING_ATTRIBUTE_COOKIE_H

View File

@ -8,7 +8,6 @@
#include <dirent.h>
#include <algorithm>
#include <new>
#include <fs_info.h>
@ -18,6 +17,7 @@
#include <AutoDeleter.h>
#include "AttributeCookie.h"
#include "DebugSupport.h"
#include "Directory.h"
#include "GlobalFactory.h"
@ -25,10 +25,6 @@
#include "Volume.h"
using BPackageKit::BHPKG::BBufferDataReader;
using BPackageKit::BHPKG::BFDDataReader;
static const uint32 kOptimalIOSize = 64 * 1024;
@ -860,32 +856,6 @@ packagefs_rewind_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
// #pragma mark - Attribute Operations
struct AttributeCookie {
PackageNode* packageNode;
Package* package;
PackageNodeAttribute* attribute;
int openMode;
AttributeCookie(PackageNode* packageNode, PackageNodeAttribute* attribute,
int openMode)
:
packageNode(packageNode),
package(packageNode->GetPackage()),
attribute(attribute),
openMode(openMode)
{
packageNode->AcquireReference();
package->AcquireReference();
}
~AttributeCookie()
{
packageNode->ReleaseReference();
package->ReleaseReference();
}
};
status_t
packagefs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
int openMode, void** _cookie)
@ -907,21 +877,12 @@ packagefs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
if (error != B_OK)
return error;
// get the package node and the respectively named attribute
PackageNode* packageNode = node->GetPackageNode();
PackageNodeAttribute* attribute = packageNode != NULL
? packageNode->FindAttribute(name) : NULL;
if (attribute == NULL)
return B_ENTRY_NOT_FOUND;
// allocate the cookie
AttributeCookie* cookie = new(std::nothrow) AttributeCookie(packageNode,
attribute, openMode);
if (cookie == NULL)
RETURN_ERROR(B_NO_MEMORY);
AttributeCookie* cookie;
error = node->OpenAttribute(name, openMode, cookie);
if (error != B_OK)
return error;
*_cookie = cookie;
return B_OK;
}
@ -929,7 +890,8 @@ packagefs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
status_t
packagefs_close_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
{
return B_OK;
AttributeCookie* cookie = (AttributeCookie*)_cookie;
RETURN_ERROR(cookie->Close());
}
@ -951,38 +913,6 @@ packagefs_free_attr_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
}
static status_t
read_package_data(const BPackageData& data, BDataReader* dataReader, off_t offset,
void* buffer, size_t* bufferSize)
{
// create a BPackageDataReader
BPackageDataReader* reader;
status_t error = GlobalFactory::Default()->CreatePackageDataReader(
dataReader, data, reader);
if (error != B_OK)
RETURN_ERROR(error);
ObjectDeleter<BPackageDataReader> readerDeleter(reader);
// check the offset
if (offset < 0 || (uint64)offset > data.UncompressedSize())
return B_BAD_VALUE;
// clamp the size
size_t toRead = std::min((uint64)*bufferSize,
data.UncompressedSize() - offset);
// read
if (toRead > 0) {
status_t error = reader->ReadData(offset, buffer, toRead);
if (error != B_OK)
RETURN_ERROR(error);
}
*bufferSize = toRead;
return B_OK;
}
status_t
packagefs_read_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
off_t offset, void* buffer, size_t* bufferSize)
@ -996,21 +926,7 @@ packagefs_read_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
TOUCH(volume);
TOUCH(node);
const BPackageData& data = cookie->attribute->Data();
if (data.IsEncodedInline()) {
// inline data
BBufferDataReader dataReader(data.InlineData(), data.CompressedSize());
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
}
// data not inline -- open the package
int fd = cookie->package->Open();
if (fd < 0)
RETURN_ERROR(fd);
PackageCloser packageCloser(cookie->package);
BFDDataReader dataReader(fd);
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
return cookie->ReadAttribute(offset, buffer, bufferSize);
}
@ -1027,10 +943,7 @@ packagefs_read_attr_stat(fs_volume* fsVolume, fs_vnode* fsNode,
TOUCH(volume);
TOUCH(node);
st->st_size = cookie->attribute->Data().UncompressedSize();
st->st_type = cookie->attribute->Type();
return B_OK;
return cookie->ReadAttributeStat(st);
}