diff --git a/src/kits/storage/Jamfile b/src/kits/storage/Jamfile index e3e8b70cbc..88b6d93ec7 100644 --- a/src/kits/storage/Jamfile +++ b/src/kits/storage/Jamfile @@ -12,6 +12,7 @@ UseArchHeaders $(TARGET_ARCH) ; UsePublicHeaders [ FDirName add-ons registrar ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) disk_device ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) disk_device jobs ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) mime ] ; SEARCH_SOURCE += [ FDirName $(SUBDIR) sniffer ] ; @@ -72,6 +73,9 @@ MergeObject storage_kit.o : # disk device API DiskDevice.cpp + DiskDeviceJob.cpp + DiskDeviceJobGenerator.cpp + DiskDeviceJobQueue.cpp DiskDeviceList.cpp DiskDevicePrivate.cpp DiskDeviceRoster.cpp @@ -84,6 +88,9 @@ MergeObject storage_kit.o : Partition.cpp PartitionDelegate.cpp PartitioningInfo.cpp + PartitionReference.cpp + + InitializeJob.cpp ; diff --git a/src/kits/storage/disk_device/DiskDevice.cpp b/src/kits/storage/disk_device/DiskDevice.cpp index b4e3c664c6..24d7f8bf5e 100644 --- a/src/kits/storage/disk_device/DiskDevice.cpp +++ b/src/kits/storage/disk_device/DiskDevice.cpp @@ -23,6 +23,9 @@ #include #include +#include "DiskDeviceJob.h" +#include "DiskDeviceJobGenerator.h" +#include "DiskDeviceJobQueue.h" #include "DiskSystemAddOnManager.h" @@ -276,6 +279,7 @@ status_t BDiskDevice::CommitModifications(bool synchronously, BMessenger progressMessenger, bool receiveCompleteProgressUpdates) { +// TODO: Support parameters! status_t error = InitCheck(); if (error != B_OK) return error; @@ -283,7 +287,13 @@ BDiskDevice::CommitModifications(bool synchronously, if (!fDelegate) return B_BAD_VALUE; - // TODO: Implement! + // generate jobs + DiskDeviceJobQueue jobQueue; + error = DiskDeviceJobGenerator(this, &jobQueue).GenerateJobs(); + + // do the jobs + if (error == B_OK) + error = jobQueue.Execute(); _DeleteDelegates(); DiskSystemAddOnManager::Default()->UnloadDiskSystems(); diff --git a/src/kits/storage/disk_device/DiskDeviceJob.cpp b/src/kits/storage/disk_device/DiskDeviceJob.cpp new file mode 100644 index 0000000000..690a6db086 --- /dev/null +++ b/src/kits/storage/disk_device/DiskDeviceJob.cpp @@ -0,0 +1,33 @@ +/* + * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "DiskDeviceJob.h" + +#include "PartitionReference.h" + + +// constructor +DiskDeviceJob::DiskDeviceJob(PartitionReference* partition, + PartitionReference* child) + : fPartition(partition), + fChild(child) +{ + if (fPartition) + fPartition->AddReference(); + + if (fChild) + fChild->AddReference(); +} + + +// destructor +DiskDeviceJob::~DiskDeviceJob() +{ + if (fPartition) + fPartition->RemoveReference(); + + if (fChild) + fChild->RemoveReference(); +} diff --git a/src/kits/storage/disk_device/DiskDeviceJob.h b/src/kits/storage/disk_device/DiskDeviceJob.h new file mode 100644 index 0000000000..80995c0e92 --- /dev/null +++ b/src/kits/storage/disk_device/DiskDeviceJob.h @@ -0,0 +1,35 @@ +/* + * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _DISK_DEVICE_JOB_H +#define _DISK_DEVICE_JOB_H + +#include + + +namespace BPrivate { + + +class PartitionReference; + + +class DiskDeviceJob { +public: + DiskDeviceJob(PartitionReference* partition, + PartitionReference* child = NULL); + virtual ~DiskDeviceJob(); + + virtual status_t Do() = 0; + +protected: + PartitionReference* fPartition; + PartitionReference* fChild; +}; + + +} // namespace BPrivate + +using BPrivate::DiskDeviceJob; + +#endif // _DISK_DEVICE_JOB_H diff --git a/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp b/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp index eb224ef6f3..cf08ed0783 100644 --- a/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp +++ b/src/kits/storage/disk_device/DiskDeviceJobGenerator.cpp @@ -14,7 +14,12 @@ #include +#include "DiskDeviceJob.h" +#include "DiskDeviceJobQueue.h" #include "PartitionDelegate.h" +#include "PartitionReference.h" + +#include "InitializeJob.h" using std::nothrow; @@ -45,8 +50,8 @@ compare_string(const char* str1, const char* str2) } -// move_info -struct DiskDeviceJobGenerator::move_info { +// MoveInfo +struct DiskDeviceJobGenerator::MoveInfo { BPartition* partition; off_t position; off_t target_position; @@ -54,17 +59,38 @@ struct DiskDeviceJobGenerator::move_info { }; +// PartitionRefInfo +struct DiskDeviceJobGenerator::PartitionRefInfo { + PartitionRefInfo() + : partition(NULL), + reference(NULL) + { + } + + ~PartitionRefInfo() + { + if (reference) + reference->RemoveReference(); + } + + BPartition* partition; + PartitionReference* reference; +}; + + // constructor DiskDeviceJobGenerator::DiskDeviceJobGenerator(BDiskDevice* device, DiskDeviceJobQueue* jobQueue) : fDevice(device), fJobQueue(jobQueue), - fMoveInfos(NULL) + fMoveInfos(NULL), + fPartitionRefs(NULL) { - fMoveInfoCount = fDevice->CountDescendants(); + fPartitionCount = fDevice->CountDescendants(); - fMoveInfos = new(nothrow) move_info[fMoveInfoCount]; -// fPartitionIDs = new(nothrow) partition_id[fMoveInfoCount]; + fMoveInfos = new(nothrow) MoveInfo[fPartitionCount]; +// fPartitionIDs = new(nothrow) partition_id[fPartitionCount]; + fPartitionRefs = new(nothrow) PartitionRefInfo[fPartitionCount]; } @@ -73,6 +99,7 @@ DiskDeviceJobGenerator::~DiskDeviceJobGenerator() { delete[] fMoveInfos; // delete[] fPartitionIDs; + delete[] fPartitionRefs; } @@ -81,10 +108,11 @@ status_t DiskDeviceJobGenerator::GenerateJobs() { // check parameters - if (!fDevice || !fJobQueue /*|| !fMoveInfos || !fPartitionIDs - || fJobQueue->Device() != fDevice || !fDevice->ShadowPartition()*/) { + if (!fDevice || !fJobQueue) return B_BAD_VALUE; - } + + if (!fMoveInfos /*|| !fPartitionIDs*/ || !fPartitionRefs) + return B_NO_MEMORY; // 1) Generate jobs for all physical partitions that don't have an // associated shadow partition, i.e. those that shall be deleted. @@ -116,8 +144,14 @@ DiskDeviceJobGenerator::GenerateJobs() status_t DiskDeviceJobGenerator::_AddJob(DiskDeviceJob* job) { -// TODO: Implement! - return B_BAD_VALUE; + if (!job) + return B_NO_MEMORY; + + status_t error = fJobQueue->AddJob(job); + if (error != B_OK) + delete job; + + return error; } @@ -208,8 +242,8 @@ DiskDeviceJobGenerator::_GenerateChildPlacementJobs(BPartition* partition) for (int32 i = 0; BPartition* child = partition->_ChildAt(i); i++) { if (BMutablePartition* childShadow = _GetMutablePartition(child)) { - // add a move_info for the child - move_info& info = fMoveInfos[childCount]; + // add a MoveInfo for the child + MoveInfo& info = fMoveInfos[childCount]; childCount++; info.partition = child; info.position = child->Offset(); @@ -233,7 +267,7 @@ DiskDeviceJobGenerator::_GenerateChildPlacementJobs(BPartition* partition) // sort the move infos if (childCount > 0 && moveForth + moveBack > 0) { - qsort(fMoveInfos, childCount, sizeof(move_info), + qsort(fMoveInfos, childCount, sizeof(MoveInfo), _CompareMoveInfoPosition); } @@ -243,7 +277,7 @@ DiskDeviceJobGenerator::_GenerateChildPlacementJobs(BPartition* partition) if (moveForth < moveBack) { // move children back for (int32 i = 0; i < childCount; i++) { - move_info &info = fMoveInfos[i]; + MoveInfo &info = fMoveInfos[i]; if (info.position > info.target_position) { if (i == 0 || info.target_position >= fMoveInfos[i - 1].position @@ -262,7 +296,7 @@ DiskDeviceJobGenerator::_GenerateChildPlacementJobs(BPartition* partition) } else { // move children forth for (int32 i = childCount - 1; i >= 0; i--) { - move_info &info = fMoveInfos[i]; + MoveInfo &info = fMoveInfos[i]; if (info.position > info.target_position) { if (i == childCount - 1 || info.target_position + info.size @@ -430,8 +464,23 @@ DiskDeviceJobGenerator::_GetMutablePartition(BPartition* partition) status_t DiskDeviceJobGenerator::_GenerateInitializeJob(BPartition* partition) { -// TODO: Implement! - return B_BAD_VALUE; + PartitionReference* reference; + status_t error = _GetPartitionReference(partition, reference); + if (error != B_OK) + return error; + + InitializeJob* job = new(nothrow) InitializeJob(reference); + if (!job) + return B_NO_MEMORY; + + error = job->Init(partition->ContentType(), + partition->ContentName(), partition->ContentParameters()); + if (error != B_OK) { + delete job; + return error; + } + + return _AddJob(job); } @@ -557,12 +606,52 @@ DiskDeviceJobGenerator::_CollectContentsToMove(BPartition* partition) } +// _GetPartitionReference +status_t +DiskDeviceJobGenerator::_GetPartitionReference(BPartition* partition, + PartitionReference*& reference) +{ + if (!partition) + return B_BAD_VALUE; + + for (int32 i = 0; i < fPartitionCount; i++) { + PartitionRefInfo& info = fPartitionRefs[i]; + + if (info.partition == partition) { + reference = info.reference; + return B_OK; + } + + if (info.partition == NULL) { + // create partition reference + info.reference = new(nothrow) PartitionReference(); + if (!info.reference) + return B_NO_MEMORY; + + // set partition ID and change counter + user_partition_data* partitionData = partition->fPartitionData; + if (partitionData) { + info.reference->SetPartitionID(partitionData->id); + info.reference->SetChangeCounter(partitionData->change_counter); + } + + info.partition = partition; + reference = info.reference; + return B_OK; + } + } + + // Out of slots -- that can't happen. + return B_ERROR; +} + + // _CompareMoveInfoOffset int DiskDeviceJobGenerator::_CompareMoveInfoPosition(const void* _a, const void* _b) { - const move_info* a = static_cast(_a); - const move_info* b = static_cast(_b); + const MoveInfo* a = static_cast(_a); + const MoveInfo* b = static_cast(_b); if (a->position < b->position) return -1; if (a->position > b->position) diff --git a/src/kits/storage/disk_device/DiskDeviceJobGenerator.h b/src/kits/storage/disk_device/DiskDeviceJobGenerator.h index 2d67835fce..af7dd901f7 100644 --- a/src/kits/storage/disk_device/DiskDeviceJobGenerator.h +++ b/src/kits/storage/disk_device/DiskDeviceJobGenerator.h @@ -18,6 +18,7 @@ namespace BPrivate { class DiskDeviceJob; class DiskDeviceJobQueue; +class PartitionReference; class DiskDeviceJobGenerator { @@ -65,16 +66,21 @@ private: status_t _CollectContentsToMove(BPartition* partition); + status_t _GetPartitionReference(BPartition* partition, + PartitionReference*& reference); + static int _CompareMoveInfoPosition(const void* _a, const void* _b); private: - struct move_info; + struct MoveInfo; + struct PartitionRefInfo; BDiskDevice* fDevice; DiskDeviceJobQueue* fJobQueue; - move_info* fMoveInfos; - int32 fMoveInfoCount; + MoveInfo* fMoveInfos; + int32 fPartitionCount; + PartitionRefInfo* fPartitionRefs; }; diff --git a/src/kits/storage/disk_device/DiskDeviceJobQueue.cpp b/src/kits/storage/disk_device/DiskDeviceJobQueue.cpp new file mode 100644 index 0000000000..8e65a90315 --- /dev/null +++ b/src/kits/storage/disk_device/DiskDeviceJobQueue.cpp @@ -0,0 +1,48 @@ +/* + * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "DiskDeviceJobQueue.h" + +#include "DiskDeviceJob.h" + + +// constructor +DiskDeviceJobQueue::DiskDeviceJobQueue() + : fJobs(20, true) +{ +} + + +// destructor +DiskDeviceJobQueue::~DiskDeviceJobQueue() +{ +} + + +// AddJob +status_t +DiskDeviceJobQueue::AddJob(DiskDeviceJob* job) +{ + if (!job) + return B_BAD_VALUE; + + return fJobs.AddItem(job) ? B_OK : B_NO_MEMORY; +} + + +// Execute +status_t +DiskDeviceJobQueue::Execute() +{ + int32 count = fJobs.CountItems(); + for (int32 i = 0; i < count; i++) { + DiskDeviceJob* job = fJobs.ItemAt(i); + status_t error = job->Do(); + if (error != B_OK) + return error; + } + + return B_OK; +} diff --git a/src/kits/storage/disk_device/DiskDeviceJobQueue.h b/src/kits/storage/disk_device/DiskDeviceJobQueue.h new file mode 100644 index 0000000000..eee931caee --- /dev/null +++ b/src/kits/storage/disk_device/DiskDeviceJobQueue.h @@ -0,0 +1,38 @@ +/* + * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _DISK_DEVICE_JOB_QUEUE_H +#define _DISK_DEVICE_JOB_QUEUE_H + +#include +#include + + +namespace BPrivate { + + +class DiskDeviceJob; + + +class DiskDeviceJobQueue { +public: + DiskDeviceJobQueue(); + ~DiskDeviceJobQueue(); + + status_t AddJob(DiskDeviceJob* job); + + status_t Execute(); + +private: + typedef BObjectList JobList; + + JobList fJobs; +}; + + +} // namespace BPrivate + +using BPrivate::DiskDeviceJobQueue; + +#endif // _DISK_DEVICE_JOB_QUEUE_H diff --git a/src/kits/storage/disk_device/DiskDeviceUtils.h b/src/kits/storage/disk_device/DiskDeviceUtils.h new file mode 100644 index 0000000000..e896d2b183 --- /dev/null +++ b/src/kits/storage/disk_device/DiskDeviceUtils.h @@ -0,0 +1,47 @@ +/* + * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _DISK_DEVICE_UTILS_H +#define _DISK_DEVICE_UTILS_H + +#include +#include + +#include + + +namespace BPrivate { + + +// set_string +static inline status_t +set_string(char*& location, const char* newString) +{ + char* string = NULL; + if (newString) { + string = strdup(newString); + if (!string) + return B_NO_MEMORY; + } + + free(location); + location = string; + + return B_OK; +} + + +#define SET_STRING_RETURN_ON_ERROR(location, string) \ +{ \ + status_t error = set_string(location, string); \ + if (error != B_OK) \ + return error; \ +} + + +} // namespace BPrivate + +using BPrivate::set_string; + +#endif // _DISK_DEVICE_UTILS_H diff --git a/src/kits/storage/disk_device/MutablePartition.cpp b/src/kits/storage/disk_device/MutablePartition.cpp index a3f2fceeb0..29a370e733 100644 --- a/src/kits/storage/disk_device/MutablePartition.cpp +++ b/src/kits/storage/disk_device/MutablePartition.cpp @@ -14,38 +14,13 @@ #include +#include "DiskDeviceUtils.h" #include "PartitionDelegate.h" using std::nothrow; -// set_string -static status_t -set_string(char*& location, const char* newString) -{ - char* string = NULL; - if (newString) { - string = strdup(newString); - if (!string) - return B_NO_MEMORY; - } - - free(location); - location = string; - - return B_OK; -} - - -#define SET_STRING_RETURN_ON_ERROR(location, string) \ -{ \ - status_t error = set_string(location, string); \ - if (error != B_OK) \ - return error; \ -} - - // Offset off_t BMutablePartition::Offset() const diff --git a/src/kits/storage/disk_device/PartitionReference.cpp b/src/kits/storage/disk_device/PartitionReference.cpp new file mode 100644 index 0000000000..6f434bba93 --- /dev/null +++ b/src/kits/storage/disk_device/PartitionReference.cpp @@ -0,0 +1,53 @@ +/* + * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "PartitionReference.h" + + +// constructor +PartitionReference::PartitionReference(partition_id id, uint32 changeCounter) + : Referenceable(true), // delete when unreferenced + fID(id), + fChangeCounter(changeCounter) +{ +} + + +// destructor +PartitionReference::~PartitionReference() +{ +} + + +// PartitionID +partition_id +PartitionReference::PartitionID() const +{ + return fID; +} + + +// SetPartitionID +void +PartitionReference::SetPartitionID(partition_id id) +{ + fID = id; +} + + +// ChangeCounter +uint32 +PartitionReference::ChangeCounter() const +{ + return fChangeCounter; +} + + +// SetChangeCounter +void +PartitionReference::SetChangeCounter(uint32 counter) +{ + fChangeCounter = counter; +} diff --git a/src/kits/storage/disk_device/PartitionReference.h b/src/kits/storage/disk_device/PartitionReference.h new file mode 100644 index 0000000000..46401c49fa --- /dev/null +++ b/src/kits/storage/disk_device/PartitionReference.h @@ -0,0 +1,38 @@ +/* + * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _PARTITION_REFERENCE_H +#define _PARTITION_REFERENCE_H + +#include + +#include + + +namespace BPrivate { + + +class PartitionReference : public Referenceable { +public: + PartitionReference(partition_id id = -1, + uint32 changeCounter = 0); + ~PartitionReference(); + + partition_id PartitionID() const; + void SetPartitionID(partition_id id); + + uint32 ChangeCounter() const; + void SetChangeCounter(uint32 counter); + +private: + partition_id fID; + uint32 fChangeCounter; +}; + + +} // namespace BPrivate + +using BPrivate::PartitionReference; + +#endif // _PARTITION_REFERENCE_H diff --git a/src/kits/storage/disk_device/jobs/InitializeJob.cpp b/src/kits/storage/disk_device/jobs/InitializeJob.cpp new file mode 100644 index 0000000000..694e146a4d --- /dev/null +++ b/src/kits/storage/disk_device/jobs/InitializeJob.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "InitializeJob.h" + +#include "DiskDeviceUtils.h" +#include "PartitionReference.h" + + +// constructor +InitializeJob::InitializeJob(PartitionReference* partition) + : DiskDeviceJob(partition), + fDiskSystem(NULL), + fName(NULL), + fParameters(NULL) +{ +} + + +// destructor +InitializeJob::~InitializeJob() +{ + free(fDiskSystem); + free(fName); + free(fParameters); +} + + +// Init +status_t +InitializeJob::Init(const char* diskSystem, const char* name, + const char* parameters) +{ + SET_STRING_RETURN_ON_ERROR(fDiskSystem, diskSystem); + SET_STRING_RETURN_ON_ERROR(fName, name); + SET_STRING_RETURN_ON_ERROR(fParameters, parameters); + + return B_OK; +} + + +// Do +status_t +InitializeJob::Do() +{ +// Implement! + return B_BAD_VALUE; +} + diff --git a/src/kits/storage/disk_device/jobs/InitializeJob.h b/src/kits/storage/disk_device/jobs/InitializeJob.h new file mode 100644 index 0000000000..1dfb966a26 --- /dev/null +++ b/src/kits/storage/disk_device/jobs/InitializeJob.h @@ -0,0 +1,36 @@ +/* + * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _INITIALIZE_JOB_H +#define _INITIALIZE_JOB_H + +#include "DiskDeviceJob.h" + + +namespace BPrivate { + + +class InitializeJob : public DiskDeviceJob { +public: + + InitializeJob(PartitionReference* partition); + virtual ~InitializeJob(); + + status_t Init(const char* diskSystem, const char* name, + const char* parameters); + + virtual status_t Do(); + +protected: + char* fDiskSystem; + char* fName; + char* fParameters; +}; + + +} // namespace BPrivate + +using BPrivate::InitializeJob; + +#endif // _INITIALIZE_JOB_H