Implemented the job related functionality. Moved scanning of partitions into the respective job class.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4127 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6eaec7ddda
commit
ace55d9bfc
@ -11,6 +11,7 @@ namespace DiskDevice {
|
||||
|
||||
class KDiskDevice;
|
||||
class KDiskDeviceJob;
|
||||
class KDiskDeviceJobFactory;
|
||||
class KDiskDeviceJobQueue;
|
||||
class KDiskSystem;
|
||||
class KFileDiskDevice;
|
||||
@ -74,14 +75,17 @@ public:
|
||||
// Jobs
|
||||
|
||||
// manager must be locked
|
||||
KDiskDeviceJob *JobWithID(disk_job_id id);
|
||||
KDiskDeviceJob *FindJob(disk_job_id id);
|
||||
int32 CountJobs();
|
||||
KDiskDeviceJob *JobAt(int32 index);
|
||||
KDiskDeviceJob *NextJob(int32 *cookie);
|
||||
|
||||
// manager must be locked
|
||||
bool AddJobQueue(KDiskDeviceJobQueue *jobQueue);
|
||||
status_t AddJobQueue(KDiskDeviceJobQueue *jobQueue);
|
||||
status_t RemoveJobQueue(KDiskDeviceJobQueue *jobQueue);
|
||||
status_t DeleteJobQueue(KDiskDeviceJobQueue *jobQueue);
|
||||
// called when the execution is done
|
||||
int32 CountJobQueues();
|
||||
KDiskDeviceJobQueue *JobQueueAt(int32 index);
|
||||
KDiskDeviceJobQueue *NextJobQueue(int32 *cookie);
|
||||
|
||||
// Disk Systems
|
||||
|
||||
@ -110,12 +114,15 @@ private:
|
||||
bool _AddDevice(KDiskDevice *device);
|
||||
bool _RemoveDevice(KDiskDevice *device);
|
||||
|
||||
bool _RemoveJobQueue(KDiskDeviceJobQueue *jobQueue);
|
||||
|
||||
status_t _Scan(const char *path);
|
||||
status_t _ScanDevice(KDiskDevice *device);
|
||||
status_t _ScanPartition(KPartition *partition);
|
||||
|
||||
struct DeviceMap;
|
||||
struct DiskSystemMap;
|
||||
struct JobMap;
|
||||
struct JobQueueVector;
|
||||
struct PartitionMap;
|
||||
struct PartitionSet;
|
||||
|
||||
@ -124,6 +131,9 @@ private:
|
||||
PartitionMap *fPartitions;
|
||||
DiskSystemMap *fDiskSystems;
|
||||
PartitionSet *fObsoletePartitions;
|
||||
JobMap *fJobs;
|
||||
JobQueueVector *fJobQueues;
|
||||
KDiskDeviceJobFactory *fJobFactory;
|
||||
|
||||
static KDiskDeviceManager *fDefaultManager;
|
||||
};
|
||||
|
@ -12,6 +12,9 @@
|
||||
#include <VectorSet.h>
|
||||
|
||||
#include "KDiskDevice.h"
|
||||
#include "KDiskDeviceJob.h"
|
||||
#include "KDiskDeviceJobFactory.h"
|
||||
#include "KDiskDeviceJobQueue.h"
|
||||
#include "KDiskDeviceManager.h"
|
||||
#include "KDiskDeviceUtils.h"
|
||||
#include "KDiskSystem.h"
|
||||
@ -49,6 +52,14 @@ struct GetDiskSystemID {
|
||||
}
|
||||
};
|
||||
|
||||
// GetJobID
|
||||
struct GetJobID {
|
||||
inline disk_job_id operator()(const KDiskDeviceJob *job) const
|
||||
{
|
||||
return job->ID();
|
||||
}
|
||||
};
|
||||
|
||||
// PartitionMap
|
||||
struct KDiskDeviceManager::PartitionMap : VectorMap<partition_id, KPartition*,
|
||||
VectorMapEntryStrategy::ImplicitKey<partition_id, KPartition*,
|
||||
@ -72,6 +83,15 @@ struct KDiskDeviceManager::DiskSystemMap : VectorMap<disk_system_id,
|
||||
struct KDiskDeviceManager::PartitionSet : VectorSet<KPartition*> {
|
||||
};
|
||||
|
||||
// JobMap
|
||||
struct KDiskDeviceManager::JobMap : VectorMap<disk_job_id, KDiskDeviceJob*,
|
||||
VectorMapEntryStrategy::ImplicitKey<disk_job_id, KDiskDeviceJob*,
|
||||
GetJobID> > {
|
||||
};
|
||||
|
||||
// JobQueueVector
|
||||
struct KDiskDeviceManager::JobQueueVector : Vector<KDiskDeviceJobQueue*> {};
|
||||
|
||||
|
||||
// constructor
|
||||
KDiskDeviceManager::KDiskDeviceManager()
|
||||
@ -79,7 +99,10 @@ KDiskDeviceManager::KDiskDeviceManager()
|
||||
fDevices(new(nothrow) DeviceMap),
|
||||
fPartitions(new(nothrow) PartitionMap),
|
||||
fDiskSystems(new(nothrow) DiskSystemMap),
|
||||
fObsoletePartitions(new(nothrow) PartitionSet)
|
||||
fObsoletePartitions(new(nothrow) PartitionSet),
|
||||
fJobs(new(nothrow) JobMap),
|
||||
fJobQueues(new(nothrow) JobQueueVector),
|
||||
fJobFactory(new(nothrow) KDiskDeviceJobFactory)
|
||||
{
|
||||
if (InitCheck() != B_OK)
|
||||
return;
|
||||
@ -112,6 +135,7 @@ DBG(OUT("number of disk systems: %ld\n", CountDiskSystems()));
|
||||
// destructor
|
||||
KDiskDeviceManager::~KDiskDeviceManager()
|
||||
{
|
||||
// TODO: terminate and remove all jobs
|
||||
// remove all devices
|
||||
for (int32 cookie = 0; KDiskDevice *device = NextDevice(&cookie);) {
|
||||
PartitionRegistrar _(device);
|
||||
@ -150,14 +174,19 @@ KDiskDeviceManager::~KDiskDeviceManager()
|
||||
delete fDevices;
|
||||
delete fDiskSystems;
|
||||
delete fObsoletePartitions;
|
||||
delete fJobs;
|
||||
delete fJobQueues;
|
||||
delete fJobFactory;
|
||||
}
|
||||
|
||||
// InitCheck
|
||||
status_t
|
||||
KDiskDeviceManager::InitCheck() const
|
||||
{
|
||||
if (!fPartitions || !fDevices || !fDiskSystems || !fObsoletePartitions)
|
||||
if (!fPartitions || !fDevices || !fDiskSystems || !fObsoletePartitions
|
||||
|| !fJobs || !fJobQueues || !fJobFactory) {
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
return (fLock.Sem() >= 0 ? B_OK : fLock.Sem());
|
||||
}
|
||||
|
||||
@ -454,7 +483,6 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath)
|
||||
if (!filePath)
|
||||
return B_BAD_VALUE;
|
||||
status_t error = B_ERROR;
|
||||
partition_id deviceID = -1;
|
||||
KFileDiskDevice *device = NULL;
|
||||
if (ManagerLocker locker = this) {
|
||||
// check, if the device does already exist
|
||||
@ -468,20 +496,15 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath)
|
||||
error = device->SetTo(filePath);
|
||||
if (error == B_OK && !_AddDevice(device))
|
||||
error = B_NO_MEMORY;
|
||||
// set result / cleanup und failure
|
||||
if (error != B_OK) {
|
||||
delete device;
|
||||
return error;
|
||||
// scan device
|
||||
if (error == B_OK) {
|
||||
_ScanPartition(device);
|
||||
return device->ID();
|
||||
}
|
||||
deviceID = device->ID();
|
||||
device->Register();
|
||||
// cleanup on failure
|
||||
delete device;
|
||||
}
|
||||
// scan device
|
||||
if (error == B_OK && device) {
|
||||
_ScanDevice(device);
|
||||
device->Unregister();
|
||||
}
|
||||
return (error == B_OK ? deviceID : error);
|
||||
return error;
|
||||
}
|
||||
|
||||
// DeleteFileDevice
|
||||
@ -572,52 +595,105 @@ KDiskDeviceManager::DeletePartition(KPartition *partition)
|
||||
return false;
|
||||
}
|
||||
|
||||
// JobWithID
|
||||
// FindJob
|
||||
KDiskDeviceJob *
|
||||
KDiskDeviceManager::JobWithID(disk_job_id id)
|
||||
KDiskDeviceManager::FindJob(disk_job_id id)
|
||||
{
|
||||
// not implemented
|
||||
return NULL;
|
||||
JobMap::Iterator it = fJobs->Find(id);
|
||||
if (it == fJobs->End())
|
||||
return NULL;
|
||||
return it->Value();
|
||||
}
|
||||
|
||||
// CountJobs
|
||||
int32
|
||||
KDiskDeviceManager::CountJobs()
|
||||
{
|
||||
// not implemented
|
||||
return 0;
|
||||
return fJobs->Count();
|
||||
}
|
||||
|
||||
// JobAt
|
||||
// NextJob
|
||||
KDiskDeviceJob *
|
||||
KDiskDeviceManager::JobAt(int32 index)
|
||||
KDiskDeviceManager::NextJob(int32 *cookie)
|
||||
{
|
||||
// not implemented
|
||||
if (!cookie)
|
||||
return NULL;
|
||||
JobMap::Iterator it = fJobs->FindClose(*cookie, false);
|
||||
if (it != fJobs->End()) {
|
||||
KDiskDeviceJob *job = it->Value();
|
||||
*cookie = job->ID() + 1;
|
||||
return job;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// AddJobQueue
|
||||
bool
|
||||
status_t
|
||||
KDiskDeviceManager::AddJobQueue(KDiskDeviceJobQueue *jobQueue)
|
||||
{
|
||||
// not implemented
|
||||
return false;
|
||||
// check the parameter
|
||||
if (!jobQueue)
|
||||
return B_BAD_VALUE;
|
||||
if (jobQueue->InitCheck() != B_OK)
|
||||
return jobQueue->InitCheck();
|
||||
// add the queue
|
||||
status_t error = fJobQueues->PushBack(jobQueue);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// add the queue's jobs
|
||||
int32 count = jobQueue->CountJobs();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
KDiskDeviceJob *job = jobQueue->JobAt(i);
|
||||
error = fJobs->Put(job->ID(), job);
|
||||
if (error != B_OK) {
|
||||
_RemoveJobQueue(jobQueue);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
// start its execution
|
||||
error = jobQueue->Execute();
|
||||
if (error != B_OK)
|
||||
_RemoveJobQueue(jobQueue);
|
||||
return error;
|
||||
}
|
||||
|
||||
// RemoveJobQueue
|
||||
status_t
|
||||
KDiskDeviceManager::RemoveJobQueue(KDiskDeviceJobQueue *jobQueue)
|
||||
{
|
||||
if (!jobQueue)
|
||||
return B_BAD_VALUE;
|
||||
if (jobQueue->InitCheck() != B_OK)
|
||||
return jobQueue->InitCheck();
|
||||
if (jobQueue->IsExecuting())
|
||||
return B_BAD_VALUE;
|
||||
return (_RemoveJobQueue(jobQueue) ? B_OK : B_ENTRY_NOT_FOUND);
|
||||
}
|
||||
|
||||
// DeleteJobQueue
|
||||
status_t
|
||||
KDiskDeviceManager::DeleteJobQueue(KDiskDeviceJobQueue *jobQueue)
|
||||
{
|
||||
status_t error = RemoveJobQueue(jobQueue);
|
||||
if (error == B_OK)
|
||||
delete jobQueue;
|
||||
return error;
|
||||
}
|
||||
|
||||
// CountJobQueues
|
||||
int32
|
||||
KDiskDeviceManager::CountJobQueues()
|
||||
{
|
||||
// not implemented
|
||||
return 0;
|
||||
return fJobQueues->Count();
|
||||
}
|
||||
|
||||
// JobQueueAt
|
||||
// NextJobQueue
|
||||
KDiskDeviceJobQueue *
|
||||
KDiskDeviceManager::JobQueueAt(int32 index)
|
||||
KDiskDeviceManager::NextJobQueue(int32 *cookie)
|
||||
{
|
||||
// not implemented
|
||||
return NULL;
|
||||
if (!cookie || *cookie < 0 || *cookie >= CountJobQueues())
|
||||
return NULL;
|
||||
return fJobQueues->ElementAt((*cookie)++);
|
||||
}
|
||||
|
||||
// FindDiskSystem
|
||||
@ -713,15 +789,16 @@ KDiskDeviceManager::InitialDeviceScan()
|
||||
{
|
||||
status_t error = B_ERROR;
|
||||
// scan for devices
|
||||
if (ManagerLocker locker = this)
|
||||
if (ManagerLocker locker = this) {
|
||||
error = _Scan("/dev/disk");
|
||||
// scan the devices for partitions
|
||||
// TODO: This is only provisional.
|
||||
if (error == B_OK) {
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// scan the devices for partitions
|
||||
int32 cookie = 0;
|
||||
while (KDiskDevice *device = RegisterNextDevice(&cookie)) {
|
||||
error = _ScanDevice(device);
|
||||
device->Unregister();
|
||||
while (KDiskDevice *device = NextDevice(&cookie)) {
|
||||
error = _ScanPartition(device);
|
||||
if (error != B_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
@ -789,6 +866,25 @@ KDiskDeviceManager::_RemoveDevice(KDiskDevice *device)
|
||||
&& PartitionRemoved(device));
|
||||
}
|
||||
|
||||
// _RemoveJobQueue
|
||||
bool
|
||||
KDiskDeviceManager::_RemoveJobQueue(KDiskDeviceJobQueue *jobQueue)
|
||||
{
|
||||
if (!jobQueue)
|
||||
return false;
|
||||
// find the job queue
|
||||
JobQueueVector::Iterator it = fJobQueues->Find(jobQueue);
|
||||
if (it == fJobQueues->End())
|
||||
return false;
|
||||
// remove the queue's jobs
|
||||
int32 count = jobQueue->CountJobs();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
KDiskDeviceJob *job = jobQueue->JobAt(i);
|
||||
fJobs->Remove(job->ID());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// _Scan
|
||||
status_t
|
||||
KDiskDeviceManager::_Scan(const char *path)
|
||||
@ -837,85 +933,32 @@ DBG(OUT(" found device: %s\n", path));
|
||||
return error;
|
||||
}
|
||||
|
||||
// _ScanDevice
|
||||
status_t
|
||||
KDiskDeviceManager::_ScanDevice(KDiskDevice *device)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
if (device->WriteLock()) {
|
||||
// scan the device
|
||||
if (device->HasMedia()) {
|
||||
error = _ScanPartition(device);
|
||||
if (error != B_OK) {
|
||||
// ...
|
||||
error = B_OK;
|
||||
}
|
||||
}
|
||||
device->WriteUnlock();
|
||||
} else
|
||||
error = B_ERROR;
|
||||
return error;
|
||||
}
|
||||
|
||||
// _ScanPartition
|
||||
status_t
|
||||
KDiskDeviceManager::_ScanPartition(KPartition *partition)
|
||||
{
|
||||
// the partition's device must be write-locked
|
||||
if (!partition)
|
||||
return B_BAD_VALUE;
|
||||
char partitionPath[B_PATH_NAME_LENGTH];
|
||||
partition->GetPath(partitionPath);
|
||||
DBG(OUT("KDiskDeviceManager::_ScanPartition(%s)\n", partitionPath));
|
||||
// publish the partition
|
||||
status_t error = partition->PublishDevice();
|
||||
// create a new job queue for the device
|
||||
KDiskDeviceJobQueue *jobQueue = new(nothrow) KDiskDeviceJobQueue;
|
||||
if (!jobQueue)
|
||||
return B_NO_MEMORY;
|
||||
jobQueue->SetDevice(partition->Device());
|
||||
// create a job for scanning the device and add it to the job queue
|
||||
KDiskDeviceJob *job = fJobFactory->CreateScanPartitionJob(partition->ID());
|
||||
if (!job) {
|
||||
delete jobQueue;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
if (!jobQueue->AddJob(job)) {
|
||||
delete jobQueue;
|
||||
delete job;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
// add the job queue
|
||||
status_t error = AddJobQueue(jobQueue);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
// find the disk system that returns the best priority for this partition
|
||||
float bestPriority = -1;
|
||||
KDiskSystem *bestDiskSystem = NULL;
|
||||
void *bestCookie = NULL;
|
||||
int32 itCookie = 0;
|
||||
while (KDiskSystem *diskSystem = LoadNextDiskSystem(&itCookie)) {
|
||||
DBG(OUT(" trying: %s\n", diskSystem->Name()));
|
||||
void *cookie = NULL;
|
||||
float priority = diskSystem->Identify(partition, &cookie);
|
||||
DBG(OUT(" returned: %f\n", priority));
|
||||
if (priority >= 0 && priority > bestPriority) {
|
||||
// new best disk system
|
||||
if (bestDiskSystem) {
|
||||
bestDiskSystem->FreeIdentifyCookie(partition, bestCookie);
|
||||
bestDiskSystem->Unload();
|
||||
}
|
||||
bestPriority = priority;
|
||||
bestDiskSystem = diskSystem;
|
||||
bestCookie = cookie;
|
||||
} else {
|
||||
// disk system doesn't identify the partition or worse than our
|
||||
// current favorite
|
||||
diskSystem->FreeIdentifyCookie(partition, cookie);
|
||||
diskSystem->Unload();
|
||||
}
|
||||
}
|
||||
// now, if we have found a disk system, let it scan the partition
|
||||
if (bestDiskSystem) {
|
||||
DBG(OUT(" scanning with: %s\n", bestDiskSystem->Name()));
|
||||
error = bestDiskSystem->Scan(partition, bestCookie);
|
||||
if (error == B_OK) {
|
||||
partition->SetDiskSystem(bestDiskSystem);
|
||||
for (int32 i = 0; KPartition *child = partition->ChildAt(i); i++)
|
||||
_ScanPartition(child);
|
||||
} else {
|
||||
// TODO: Handle the error.
|
||||
DBG(OUT(" scanning failed: %s\n", strerror(error)));
|
||||
}
|
||||
// now we can safely unload the disk system -- it has been loaded by
|
||||
// the partition(s) and thus will not really be unloaded
|
||||
bestDiskSystem->Unload();
|
||||
} else {
|
||||
// contents not recognized
|
||||
// nothing to be done -- partitions are created as unrecognized
|
||||
}
|
||||
delete jobQueue;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user