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:
Ingo Weinhold
2003-07-30 00:18:16 +00:00
parent 6eaec7ddda
commit ace55d9bfc
2 changed files with 170 additions and 117 deletions
@@ -11,6 +11,7 @@ namespace DiskDevice {
class KDiskDevice; class KDiskDevice;
class KDiskDeviceJob; class KDiskDeviceJob;
class KDiskDeviceJobFactory;
class KDiskDeviceJobQueue; class KDiskDeviceJobQueue;
class KDiskSystem; class KDiskSystem;
class KFileDiskDevice; class KFileDiskDevice;
@@ -74,14 +75,17 @@ public:
// Jobs // Jobs
// manager must be locked // manager must be locked
KDiskDeviceJob *JobWithID(disk_job_id id); KDiskDeviceJob *FindJob(disk_job_id id);
int32 CountJobs(); int32 CountJobs();
KDiskDeviceJob *JobAt(int32 index); KDiskDeviceJob *NextJob(int32 *cookie);
// manager must be locked // 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(); int32 CountJobQueues();
KDiskDeviceJobQueue *JobQueueAt(int32 index); KDiskDeviceJobQueue *NextJobQueue(int32 *cookie);
// Disk Systems // Disk Systems
@@ -110,12 +114,15 @@ private:
bool _AddDevice(KDiskDevice *device); bool _AddDevice(KDiskDevice *device);
bool _RemoveDevice(KDiskDevice *device); bool _RemoveDevice(KDiskDevice *device);
bool _RemoveJobQueue(KDiskDeviceJobQueue *jobQueue);
status_t _Scan(const char *path); status_t _Scan(const char *path);
status_t _ScanDevice(KDiskDevice *device);
status_t _ScanPartition(KPartition *partition); status_t _ScanPartition(KPartition *partition);
struct DeviceMap; struct DeviceMap;
struct DiskSystemMap; struct DiskSystemMap;
struct JobMap;
struct JobQueueVector;
struct PartitionMap; struct PartitionMap;
struct PartitionSet; struct PartitionSet;
@@ -124,6 +131,9 @@ private:
PartitionMap *fPartitions; PartitionMap *fPartitions;
DiskSystemMap *fDiskSystems; DiskSystemMap *fDiskSystems;
PartitionSet *fObsoletePartitions; PartitionSet *fObsoletePartitions;
JobMap *fJobs;
JobQueueVector *fJobQueues;
KDiskDeviceJobFactory *fJobFactory;
static KDiskDeviceManager *fDefaultManager; static KDiskDeviceManager *fDefaultManager;
}; };
@@ -12,6 +12,9 @@
#include <VectorSet.h> #include <VectorSet.h>
#include "KDiskDevice.h" #include "KDiskDevice.h"
#include "KDiskDeviceJob.h"
#include "KDiskDeviceJobFactory.h"
#include "KDiskDeviceJobQueue.h"
#include "KDiskDeviceManager.h" #include "KDiskDeviceManager.h"
#include "KDiskDeviceUtils.h" #include "KDiskDeviceUtils.h"
#include "KDiskSystem.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 // PartitionMap
struct KDiskDeviceManager::PartitionMap : VectorMap<partition_id, KPartition*, struct KDiskDeviceManager::PartitionMap : VectorMap<partition_id, KPartition*,
VectorMapEntryStrategy::ImplicitKey<partition_id, KPartition*, VectorMapEntryStrategy::ImplicitKey<partition_id, KPartition*,
@@ -72,6 +83,15 @@ struct KDiskDeviceManager::DiskSystemMap : VectorMap<disk_system_id,
struct KDiskDeviceManager::PartitionSet : VectorSet<KPartition*> { 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 // constructor
KDiskDeviceManager::KDiskDeviceManager() KDiskDeviceManager::KDiskDeviceManager()
@@ -79,7 +99,10 @@ KDiskDeviceManager::KDiskDeviceManager()
fDevices(new(nothrow) DeviceMap), fDevices(new(nothrow) DeviceMap),
fPartitions(new(nothrow) PartitionMap), fPartitions(new(nothrow) PartitionMap),
fDiskSystems(new(nothrow) DiskSystemMap), 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) if (InitCheck() != B_OK)
return; return;
@@ -112,6 +135,7 @@ DBG(OUT("number of disk systems: %ld\n", CountDiskSystems()));
// destructor // destructor
KDiskDeviceManager::~KDiskDeviceManager() KDiskDeviceManager::~KDiskDeviceManager()
{ {
// TODO: terminate and remove all jobs
// remove all devices // remove all devices
for (int32 cookie = 0; KDiskDevice *device = NextDevice(&cookie);) { for (int32 cookie = 0; KDiskDevice *device = NextDevice(&cookie);) {
PartitionRegistrar _(device); PartitionRegistrar _(device);
@@ -150,14 +174,19 @@ KDiskDeviceManager::~KDiskDeviceManager()
delete fDevices; delete fDevices;
delete fDiskSystems; delete fDiskSystems;
delete fObsoletePartitions; delete fObsoletePartitions;
delete fJobs;
delete fJobQueues;
delete fJobFactory;
} }
// InitCheck // InitCheck
status_t status_t
KDiskDeviceManager::InitCheck() const KDiskDeviceManager::InitCheck() const
{ {
if (!fPartitions || !fDevices || !fDiskSystems || !fObsoletePartitions) if (!fPartitions || !fDevices || !fDiskSystems || !fObsoletePartitions
|| !fJobs || !fJobQueues || !fJobFactory) {
return B_NO_MEMORY; return B_NO_MEMORY;
}
return (fLock.Sem() >= 0 ? B_OK : fLock.Sem()); return (fLock.Sem() >= 0 ? B_OK : fLock.Sem());
} }
@@ -454,7 +483,6 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath)
if (!filePath) if (!filePath)
return B_BAD_VALUE; return B_BAD_VALUE;
status_t error = B_ERROR; status_t error = B_ERROR;
partition_id deviceID = -1;
KFileDiskDevice *device = NULL; KFileDiskDevice *device = NULL;
if (ManagerLocker locker = this) { if (ManagerLocker locker = this) {
// check, if the device does already exist // check, if the device does already exist
@@ -468,20 +496,15 @@ KDiskDeviceManager::CreateFileDevice(const char *filePath)
error = device->SetTo(filePath); error = device->SetTo(filePath);
if (error == B_OK && !_AddDevice(device)) if (error == B_OK && !_AddDevice(device))
error = B_NO_MEMORY; error = B_NO_MEMORY;
// set result / cleanup und failure
if (error != B_OK) {
delete device;
return error;
}
deviceID = device->ID();
device->Register();
}
// scan device // scan device
if (error == B_OK && device) { if (error == B_OK) {
_ScanDevice(device); _ScanPartition(device);
device->Unregister(); return device->ID();
} }
return (error == B_OK ? deviceID : error); // cleanup on failure
delete device;
}
return error;
} }
// DeleteFileDevice // DeleteFileDevice
@@ -572,52 +595,105 @@ KDiskDeviceManager::DeletePartition(KPartition *partition)
return false; return false;
} }
// JobWithID // FindJob
KDiskDeviceJob * KDiskDeviceJob *
KDiskDeviceManager::JobWithID(disk_job_id id) KDiskDeviceManager::FindJob(disk_job_id id)
{ {
// not implemented JobMap::Iterator it = fJobs->Find(id);
if (it == fJobs->End())
return NULL; return NULL;
return it->Value();
} }
// CountJobs // CountJobs
int32 int32
KDiskDeviceManager::CountJobs() KDiskDeviceManager::CountJobs()
{ {
// not implemented return fJobs->Count();
return 0;
} }
// JobAt // NextJob
KDiskDeviceJob * 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; return NULL;
} }
// AddJobQueue // AddJobQueue
bool status_t
KDiskDeviceManager::AddJobQueue(KDiskDeviceJobQueue *jobQueue) KDiskDeviceManager::AddJobQueue(KDiskDeviceJobQueue *jobQueue)
{ {
// not implemented // check the parameter
return false; 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 // CountJobQueues
int32 int32
KDiskDeviceManager::CountJobQueues() KDiskDeviceManager::CountJobQueues()
{ {
// not implemented return fJobQueues->Count();
return 0;
} }
// JobQueueAt // NextJobQueue
KDiskDeviceJobQueue * KDiskDeviceJobQueue *
KDiskDeviceManager::JobQueueAt(int32 index) KDiskDeviceManager::NextJobQueue(int32 *cookie)
{ {
// not implemented if (!cookie || *cookie < 0 || *cookie >= CountJobQueues())
return NULL; return NULL;
return fJobQueues->ElementAt((*cookie)++);
} }
// FindDiskSystem // FindDiskSystem
@@ -713,15 +789,16 @@ KDiskDeviceManager::InitialDeviceScan()
{ {
status_t error = B_ERROR; status_t error = B_ERROR;
// scan for devices // scan for devices
if (ManagerLocker locker = this) if (ManagerLocker locker = this) {
error = _Scan("/dev/disk"); error = _Scan("/dev/disk");
if (error != B_OK)
return error;
// scan the devices for partitions // scan the devices for partitions
// TODO: This is only provisional.
if (error == B_OK) {
int32 cookie = 0; int32 cookie = 0;
while (KDiskDevice *device = RegisterNextDevice(&cookie)) { while (KDiskDevice *device = NextDevice(&cookie)) {
error = _ScanDevice(device); error = _ScanPartition(device);
device->Unregister(); if (error != B_OK)
break;
} }
} }
return error; return error;
@@ -789,6 +866,25 @@ KDiskDeviceManager::_RemoveDevice(KDiskDevice *device)
&& PartitionRemoved(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 // _Scan
status_t status_t
KDiskDeviceManager::_Scan(const char *path) KDiskDeviceManager::_Scan(const char *path)
@@ -837,85 +933,32 @@ DBG(OUT(" found device: %s\n", path));
return error; 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 // _ScanPartition
status_t status_t
KDiskDeviceManager::_ScanPartition(KPartition *partition) KDiskDeviceManager::_ScanPartition(KPartition *partition)
{ {
// the partition's device must be write-locked
if (!partition) if (!partition)
return B_BAD_VALUE; return B_BAD_VALUE;
char partitionPath[B_PATH_NAME_LENGTH]; // create a new job queue for the device
partition->GetPath(partitionPath); KDiskDeviceJobQueue *jobQueue = new(nothrow) KDiskDeviceJobQueue;
DBG(OUT("KDiskDeviceManager::_ScanPartition(%s)\n", partitionPath)); if (!jobQueue)
// publish the partition return B_NO_MEMORY;
status_t error = partition->PublishDevice(); 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) if (error != B_OK)
return error; delete jobQueue;
// 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
}
return error; return error;
} }