The info about partitionable space will be provided by the userland disk

system add-ons. First work to make this class usable for them.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22539 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2007-10-13 21:17:26 +00:00
parent b3e7c4a4b9
commit 103ca6a3ad
2 changed files with 182 additions and 12 deletions

View File

@ -12,25 +12,35 @@ struct partitionable_space_data;
class BPartitioningInfo {
public:
BPartitioningInfo();
virtual ~BPartitioningInfo();
BPartitioningInfo();
virtual ~BPartitioningInfo();
void Unset();
status_t SetTo(off_t offset, off_t size);
void Unset();
partition_id PartitionID() const;
status_t ExcludeOccupiedSpace(off_t offset,
off_t size);
status_t GetPartitionableSpaceAt(int32 index, off_t *offset,
off_t *size) const;
int32 CountPartitionableSpaces() const;
// TODO: We don't need the partition ID.
partition_id PartitionID() const;
status_t GetPartitionableSpaceAt(int32 index,
off_t* offset, off_t*size) const;
int32 CountPartitionableSpaces() const;
private:
status_t _SetTo(partition_id partition, int32 changeCounter);
status_t _SetTo(partition_id partition,
int32 changeCounter);
status_t _InsertSpaces(int32 index, int32 count);
void _RemoveSpaces(int32 index, int32 count);
friend class BPartition;
partition_id fPartitionID;
partitionable_space_data *fSpaces;
int32 fCount;
partition_id fPartitionID;
partitionable_space_data* fSpaces;
int32 fCount;
int32 fCapacity;
};
#endif // _PARTITIONING_INFO_H

View File

@ -3,6 +3,8 @@
// by the OpenBeOS license.
//---------------------------------------------------------------------
#include <string.h>
#include <new>
#include <PartitioningInfo.h>
@ -10,22 +12,53 @@
#include <syscalls.h>
#include <disk_device_manager/ddm_userland_interface.h>
using namespace std;
// constructor
BPartitioningInfo::BPartitioningInfo()
: fPartitionID(-1),
fSpaces(NULL),
fCount(0)
fCount(0),
fCapacity(0)
{
}
// destructor
BPartitioningInfo::~BPartitioningInfo()
{
Unset();
}
// SetTo
status_t
BPartitioningInfo::SetTo(off_t offset, off_t size)
{
fPartitionID = -1;
delete[] fSpaces;
if (size > 0) {
fSpaces = new(nothrow) partitionable_space_data[1];
if (!fSpaces)
return B_NO_MEMORY;
fCount = 1;
fSpaces[0].offset = offset;
fSpaces[0].size = size;
} else {
fSpaces = NULL;
fCount = 0;
}
fCapacity = fCount;
return B_OK;
}
// Unset
void
BPartitioningInfo::Unset()
@ -34,8 +67,80 @@ BPartitioningInfo::Unset()
fPartitionID = -1;
fSpaces = NULL;
fCount = 0;
fCapacity = 0;
}
// ExcludeOccupiedSpace
status_t
BPartitioningInfo::ExcludeOccupiedSpace(off_t offset, off_t size)
{
if (size <= 0)
return B_OK;
int32 leftIndex = -1;
int32 rightIndex = -1;
for (int32 i = 0; i < fCount; i++) {
if (leftIndex == -1
&& offset < fSpaces[i].offset + fSpaces[i].size) {
leftIndex = i;
}
if (fSpaces[i].offset < offset + size)
rightIndex = i;
}
// If there's no intersection with any free space, we're done.
if (leftIndex == -1 || rightIndex == -1 || leftIndex > rightIndex)
return B_OK;
partitionable_space_data& leftSpace = fSpaces[leftIndex];
partitionable_space_data& rightSpace = fSpaces[rightIndex];
off_t rightSpaceEnd = rightSpace.offset + rightSpace.size;
// special case: split a single space in two
if (leftIndex == rightIndex && leftSpace.offset < offset
&& rightSpaceEnd > offset + size) {
// add a space after this one
status_t error = _InsertSpaces(leftIndex + 1, 1);
if (error != B_OK)
return error;
partitionable_space_data& space = fSpaces[leftIndex];
partitionable_space_data& newSpace = fSpaces[leftIndex + 1];
space.size = offset - space.offset;
newSpace.offset = offset + size;
newSpace.size = rightSpaceEnd - newSpace.offset;
return B_OK;
}
// check whether the first affected space is eaten completely
int32 deleteFirst = leftIndex;
if (leftSpace.offset < offset) {
leftSpace.size = offset - leftSpace.offset;
deleteFirst++;
}
// check whether the last affected space is eaten completely
int32 deleteLast = rightIndex;
if (rightSpaceEnd > offset + size) {
rightSpace.offset = offset + size;
rightSpace.size = rightSpaceEnd - rightSpace.offset;
deleteLast--;
}
// remove all spaces that are completely eaten
if (deleteFirst <= deleteLast)
_RemoveSpaces(deleteFirst, deleteLast - deleteFirst + 1);
return B_OK;
}
// PartitionID
partition_id
BPartitioningInfo::PartitionID() const
@ -43,6 +148,7 @@ BPartitioningInfo::PartitionID() const
return fPartitionID;
}
// GetPartitionableSpaceAt
status_t
BPartitioningInfo::GetPartitionableSpaceAt(int32 index, off_t *offset,
@ -55,6 +161,7 @@ BPartitioningInfo::GetPartitionableSpaceAt(int32 index, off_t *offset,
return B_OK;
}
// CountPartitionableSpaces
int32
BPartitioningInfo::CountPartitionableSpaces() const
@ -62,6 +169,7 @@ BPartitioningInfo::CountPartitionableSpaces() const
return fCount;
}
// _SetTo
status_t
BPartitioningInfo::_SetTo(partition_id partition, int32 changeCounter)
@ -100,3 +208,55 @@ BPartitioningInfo::_SetTo(partition_id partition, int32 changeCounter)
return error;
}
// _InsertSpaces
status_t
BPartitioningInfo::_InsertSpaces(int32 index, int32 count)
{
if (index <= 0 || index > fCount || count <= 0)
return B_BAD_VALUE;
// If the capacity is sufficient, we just need to copy the spaces to create
// a gap.
if (fCount + count <= fCapacity) {
memmove(fSpaces + index + count, fSpaces + index, fCount - index);
fCount += count;
return B_OK;
}
// alloc new array
int32 capacity = (fCount + count) * 2;
// add a bit room for further resizing
partitionable_space_data* spaces
= new(nothrow) partitionable_space_data[capacity];
if (!spaces)
return B_NO_MEMORY;
// copy items
memcpy(spaces, fSpaces, index);
memcpy(spaces + index + count, fSpaces + index, fCount - index);
delete[] fSpaces;
fSpaces = spaces;
fCapacity = capacity;
fCount += count;
return B_OK;
}
// _RemoveSpaces
void
BPartitioningInfo::_RemoveSpaces(int32 index, int32 count)
{
if (index <= 0 || count <= 0 || index + count > fCount)
return;
if (count < fCount) {
int32 endIndex = index + count;
memmove(fSpaces + index, fSpaces + endIndex, fCount - endIndex);
}
fCount -= count;
}