Implemented loading/unloading of add-ons.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22544 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -5,9 +5,17 @@
|
|||||||
|
|
||||||
#include "DiskSystemAddOnManager.h"
|
#include "DiskSystemAddOnManager.h"
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <Directory.h>
|
||||||
|
#include <Entry.h>
|
||||||
#include <image.h>
|
#include <image.h>
|
||||||
|
#include <Path.h>
|
||||||
|
|
||||||
#include <AppMisc.h>
|
#include <AppMisc.h>
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <AutoLocker.h>
|
#include <AutoLocker.h>
|
||||||
|
|
||||||
#include <DiskSystemAddOn.h>
|
#include <DiskSystemAddOn.h>
|
||||||
@@ -19,6 +27,17 @@ DiskSystemAddOnManager* DiskSystemAddOnManager::sManager = NULL;
|
|||||||
|
|
||||||
// AddOnImage
|
// AddOnImage
|
||||||
struct DiskSystemAddOnManager::AddOnImage {
|
struct DiskSystemAddOnManager::AddOnImage {
|
||||||
|
AddOnImage(image_id image)
|
||||||
|
: image(image),
|
||||||
|
refCount(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~AddOnImage()
|
||||||
|
{
|
||||||
|
unload_add_on(image);
|
||||||
|
}
|
||||||
|
|
||||||
image_id image;
|
image_id image;
|
||||||
int32 refCount;
|
int32 refCount;
|
||||||
};
|
};
|
||||||
@@ -26,12 +45,23 @@ struct DiskSystemAddOnManager::AddOnImage {
|
|||||||
|
|
||||||
// AddOn
|
// AddOn
|
||||||
struct DiskSystemAddOnManager::AddOn {
|
struct DiskSystemAddOnManager::AddOn {
|
||||||
|
AddOn(AddOnImage* image, BDiskSystemAddOn* addOn)
|
||||||
|
: image(image),
|
||||||
|
addOn(addOn)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
AddOnImage* image;
|
AddOnImage* image;
|
||||||
BDiskSystemAddOn* addOn;
|
BDiskSystemAddOn* addOn;
|
||||||
int32 refCount;
|
int32 refCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// StringSet
|
||||||
|
struct DiskSystemAddOnManager::StringSet : std::set<std::string> {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Default
|
// Default
|
||||||
DiskSystemAddOnManager*
|
DiskSystemAddOnManager*
|
||||||
DiskSystemAddOnManager::Default()
|
DiskSystemAddOnManager::Default()
|
||||||
@@ -74,15 +104,27 @@ DiskSystemAddOnManager::Unlock()
|
|||||||
|
|
||||||
|
|
||||||
// LoadDiskSystems
|
// LoadDiskSystems
|
||||||
void
|
status_t
|
||||||
DiskSystemAddOnManager::LoadDiskSystems()
|
DiskSystemAddOnManager::LoadDiskSystems()
|
||||||
{
|
{
|
||||||
AutoLocker<BLocker> _(fLock);
|
AutoLocker<BLocker> _(fLock);
|
||||||
|
|
||||||
if (++fLoadCount > 1)
|
if (++fLoadCount > 1)
|
||||||
return;
|
return B_OK;
|
||||||
|
|
||||||
// TODO: Load the add-ons ...
|
StringSet alreadyLoaded;
|
||||||
|
status_t error = _LoadAddOns(alreadyLoaded, B_USER_ADDONS_DIRECTORY);
|
||||||
|
|
||||||
|
if (error == B_OK)
|
||||||
|
error = _LoadAddOns(alreadyLoaded, B_COMMON_ADDONS_DIRECTORY);
|
||||||
|
|
||||||
|
if (error == B_OK)
|
||||||
|
error = _LoadAddOns(alreadyLoaded, B_BEOS_ADDONS_DIRECTORY);
|
||||||
|
|
||||||
|
if (error != B_OK)
|
||||||
|
UnloadDiskSystems();
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -92,10 +134,16 @@ DiskSystemAddOnManager::UnloadDiskSystems()
|
|||||||
{
|
{
|
||||||
AutoLocker<BLocker> _(fLock);
|
AutoLocker<BLocker> _(fLock);
|
||||||
|
|
||||||
if (--fLoadCount == 0)
|
if (fLoadCount == 0 || --fLoadCount > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: Unload the add-ons ...
|
fAddOnsToBeUnloaded.AddList(&fAddOns);
|
||||||
|
fAddOns.MakeEmpty();
|
||||||
|
|
||||||
|
// put all add-ons -- that will cause them to be deleted as soon as they're
|
||||||
|
// unused
|
||||||
|
for (int32 i = fAddOnsToBeUnloaded.CountItems() - 1; i >= 0; i--)
|
||||||
|
_PutAddOn(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -147,13 +195,24 @@ DiskSystemAddOnManager::PutAddOn(BDiskSystemAddOn* _addOn)
|
|||||||
|
|
||||||
for (int32 i = 0; AddOn* addOn = _AddOnAt(i); i++) {
|
for (int32 i = 0; AddOn* addOn = _AddOnAt(i); i++) {
|
||||||
if (_addOn == addOn->addOn) {
|
if (_addOn == addOn->addOn) {
|
||||||
if (addOn->refCount == 0)
|
if (addOn->refCount > 1) {
|
||||||
debugger("DiskSystemAddOnManager: unbalanced PutAddOn()");
|
|
||||||
else
|
|
||||||
addOn->refCount--;
|
addOn->refCount--;
|
||||||
|
} else {
|
||||||
|
debugger("Unbalanced call to "
|
||||||
|
"DiskSystemAddOnManager::PutAddOn()");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32 i = 0;
|
||||||
|
AddOn* addOn = (AddOn*)fAddOnsToBeUnloaded.ItemAt(i); i++) {
|
||||||
|
if (_addOn == addOn->addOn)
|
||||||
|
_PutAddOn(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugger("DiskSystemAddOnManager::PutAddOn(): disk system not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -161,6 +220,7 @@ DiskSystemAddOnManager::PutAddOn(BDiskSystemAddOn* _addOn)
|
|||||||
DiskSystemAddOnManager::DiskSystemAddOnManager()
|
DiskSystemAddOnManager::DiskSystemAddOnManager()
|
||||||
: fLock("disk system add-ons manager"),
|
: fLock("disk system add-ons manager"),
|
||||||
fAddOns(),
|
fAddOns(),
|
||||||
|
fAddOnsToBeUnloaded(),
|
||||||
fLoadCount(0)
|
fLoadCount(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -173,3 +233,114 @@ DiskSystemAddOnManager::_AddOnAt(int32 index) const
|
|||||||
return (AddOn*)fAddOns.ItemAt(index);
|
return (AddOn*)fAddOns.ItemAt(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _PutAddOn
|
||||||
|
void
|
||||||
|
DiskSystemAddOnManager::_PutAddOn(int32 index)
|
||||||
|
{
|
||||||
|
AddOn* addOn = (AddOn*)fAddOnsToBeUnloaded.ItemAt(index);
|
||||||
|
if (!addOn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (--addOn->refCount == 0) {
|
||||||
|
if (--addOn->image->refCount == 0)
|
||||||
|
delete addOn->image;
|
||||||
|
|
||||||
|
fAddOnsToBeUnloaded.RemoveItem(index);
|
||||||
|
delete addOn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _LoadAddOns
|
||||||
|
status_t
|
||||||
|
DiskSystemAddOnManager::_LoadAddOns(StringSet& alreadyLoaded,
|
||||||
|
directory_which addOnDir)
|
||||||
|
{
|
||||||
|
// get the add-on directory path
|
||||||
|
BPath path;
|
||||||
|
status_t error = find_directory(addOnDir, &path, false);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
error = path.Append("disk_systems");
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
if (!BEntry(path.Path()).Exists())
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
// open the directory and iterate through its entries
|
||||||
|
BDirectory directory;
|
||||||
|
error = directory.SetTo(path.Path());
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
entry_ref ref;
|
||||||
|
while (directory.GetNextRef(&ref) == B_OK) {
|
||||||
|
// skip, if already loaded
|
||||||
|
if (alreadyLoaded.find(ref.name) != alreadyLoaded.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// get the entry path
|
||||||
|
BPath entryPath;
|
||||||
|
error = entryPath.SetTo(&ref);
|
||||||
|
if (error != B_OK) {
|
||||||
|
if (error == B_NO_MEMORY)
|
||||||
|
return error;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load the add-on
|
||||||
|
image_id image = load_add_on(entryPath.Path());
|
||||||
|
if (image < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
AddOnImage* addOnImage = new(nothrow) AddOnImage(image);
|
||||||
|
if (!addOnImage) {
|
||||||
|
unload_add_on(image);
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
ObjectDeleter<AddOnImage> addOnImageDeleter(addOnImage);
|
||||||
|
|
||||||
|
// get the add-on objects
|
||||||
|
status_t (*getAddOns)(BList*);
|
||||||
|
error = get_image_symbol(image, "get_disk_system_add_ons",
|
||||||
|
B_SYMBOL_TYPE_TEXT, (void**)&getAddOns);
|
||||||
|
if (error != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BList addOns;
|
||||||
|
error = getAddOns(&addOns);
|
||||||
|
if (error != B_OK || addOns.IsEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// create and add AddOn objects
|
||||||
|
int32 count = addOns.CountItems();
|
||||||
|
for (int32 i = 0; i < count; i++) {
|
||||||
|
BDiskSystemAddOn* diskSystemAddOn
|
||||||
|
= (BDiskSystemAddOn*)addOns.ItemAt(i);
|
||||||
|
AddOn* addOn = new(nothrow) AddOn(addOnImage, diskSystemAddOn);
|
||||||
|
if (!addOn)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
if (fAddOns.AddItem(addOn)) {
|
||||||
|
addOnImage->refCount++;
|
||||||
|
addOnImageDeleter.Detach();
|
||||||
|
} else {
|
||||||
|
delete addOn;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the add-on name to the set of already loaded add-ons
|
||||||
|
try {
|
||||||
|
alreadyLoaded.insert(ref.name);
|
||||||
|
} catch (std::bad_alloc& exception) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#ifndef _DISK_SYSTEM_ADD_ON_MANAGER_H
|
#ifndef _DISK_SYSTEM_ADD_ON_MANAGER_H
|
||||||
#define _DISK_SYSTEM_ADD_ON_MANAGER_H
|
#define _DISK_SYSTEM_ADD_ON_MANAGER_H
|
||||||
|
|
||||||
|
#include <FindDirectory.h>
|
||||||
#include <List.h>
|
#include <List.h>
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ public:
|
|||||||
void Unlock();
|
void Unlock();
|
||||||
|
|
||||||
// load/unload all disk system add-ons
|
// load/unload all disk system add-ons
|
||||||
void LoadDiskSystems();
|
status_t LoadDiskSystems();
|
||||||
void UnloadDiskSystems();
|
void UnloadDiskSystems();
|
||||||
|
|
||||||
// manager must be locked
|
// manager must be locked
|
||||||
@@ -37,14 +38,20 @@ public:
|
|||||||
private:
|
private:
|
||||||
struct AddOnImage;
|
struct AddOnImage;
|
||||||
struct AddOn;
|
struct AddOn;
|
||||||
|
struct StringSet;
|
||||||
|
|
||||||
DiskSystemAddOnManager();
|
DiskSystemAddOnManager();
|
||||||
|
|
||||||
AddOn* _AddOnAt(int32 index) const;
|
AddOn* _AddOnAt(int32 index) const;
|
||||||
|
void _PutAddOn(int32 index);
|
||||||
|
|
||||||
|
status_t _LoadAddOns(StringSet& alreadyLoaded,
|
||||||
|
directory_which directory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable BLocker fLock;
|
mutable BLocker fLock;
|
||||||
BList fAddOns;
|
BList fAddOns;
|
||||||
|
BList fAddOnsToBeUnloaded;
|
||||||
int32 fLoadCount;
|
int32 fLoadCount;
|
||||||
|
|
||||||
static DiskSystemAddOnManager* sManager;
|
static DiskSystemAddOnManager* sManager;
|
||||||
|
|||||||
Reference in New Issue
Block a user