Added reference counting of media add-on instances.

You can't create more node instances than "possible_count".


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2990 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
beveloper 2003-03-22 01:11:07 +00:00
parent b498f2e40c
commit 626824eaaf
7 changed files with 316 additions and 196 deletions

View File

@ -98,7 +98,7 @@ enum {
SERVER_UNREGISTER_BUFFER, SERVER_UNREGISTER_BUFFER,
SERVER_RESCAN_DEFAULTS, SERVER_RESCAN_DEFAULTS,
SERVER_SET_NODE_CREATOR, SERVER_SET_NODE_CREATOR,
SERVER_CHANGE_DORMANT_NODE_USECOUNT, SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT,
SERVER_MESSAGE_END, SERVER_MESSAGE_END,
NODE_MESSAGE_START = 0x200, NODE_MESSAGE_START = 0x200,
@ -210,14 +210,14 @@ enum node_type
// used by SERVER_PUBLISH_INPUTS and SERVER_PUBLISH_OUTPUTS // used by SERVER_PUBLISH_INPUTS and SERVER_PUBLISH_OUTPUTS
enum enum
{ {
MAX_OUTPUTS = 48, MAX_OUTPUTS = 8,
MAX_INPUTS = 48, MAX_INPUTS = 8,
}; };
// used by SERVER_GET_LIVE_NODES // used by SERVER_GET_LIVE_NODES
enum enum
{ {
MAX_LIVE_INFO = 62, MAX_LIVE_INFO = 16,
}; };
// used by SERVER_GET_INSTANCES_FOR // used by SERVER_GET_INSTANCES_FOR
@ -318,22 +318,6 @@ struct producer_disconnect_reply : public reply_data
{ {
}; };
struct producer_format_suggestion_requested_request : public request_data struct producer_format_suggestion_requested_request : public request_data
{ {
media_type type; media_type type;
@ -437,36 +421,6 @@ struct producer_late_notice_received_command : public command_data
bigtime_t performance_time; bigtime_t performance_time;
}; };
struct consumer_accept_format_request : public request_data struct consumer_accept_format_request : public request_data
{ {
media_destination dest; media_destination dest;
@ -568,22 +522,6 @@ struct consumer_disconnected_reply : public reply_data
{ {
}; };
struct consumer_buffer_received_command : public command_data struct consumer_buffer_received_command : public command_data
{ {
media_buffer_id buffer; media_buffer_id buffer;
@ -634,12 +572,6 @@ struct consumer_seek_tag_requested_reply : public reply_data
uint32 flags; uint32 flags;
}; };
struct server_register_addonserver_request : public request_data struct server_register_addonserver_request : public request_data
{ {
team_id team; team_id team;
@ -678,14 +610,15 @@ struct server_set_node_creator_reply : public reply_data
{ {
}; };
struct server_change_dormant_node_usecount_request : public request_data struct server_change_addon_flavor_instances_count_request : public request_data
{ {
media_addon_id addon_id; media_addon_id addonid;
int32 addon_flavor_id; int32 flavorid;
int32 delta; int32 delta; // must be +1 or -1
team_id team;
}; };
struct server_change_dormant_node_usecount_reply : public reply_data struct server_change_addon_flavor_instances_count_reply : public reply_data
{ {
}; };
@ -804,9 +737,6 @@ struct server_rescan_defaults_command : public command_data
{ {
}; };
struct addonserver_rescan_mediaaddon_flavors_command : public command_data struct addonserver_rescan_mediaaddon_flavors_command : public command_data
{ {
media_addon_id addonid; media_addon_id addonid;

View File

@ -35,8 +35,8 @@ public:
status_t SaveNodeConfiguration(BMediaNode *node); status_t SaveNodeConfiguration(BMediaNode *node);
status_t LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg); status_t LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg);
status_t IncrementDormantNodeUseCount(media_addon_id addonid, int32 flavorid); status_t IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid);
status_t DecrementDormantNodeUseCount(media_addon_id addonid, int32 flavorid); status_t DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid);
status_t SetNodeCreator(media_node_id node, team_id creator); status_t SetNodeCreator(media_node_id node, team_id creator);

View File

@ -11,7 +11,7 @@
#include "DataExchange.h" #include "DataExchange.h"
#include "ServerInterface.h" // NEW_MEDIA_SERVER_SIGNATURE #include "ServerInterface.h" // NEW_MEDIA_SERVER_SIGNATURE
#define TIMEOUT 5000000 // 5 seconds timeout! #define TIMEOUT 15000000 // 15 seconds timeout!
namespace BPrivate { namespace BPrivate {
namespace media { namespace media {

View File

@ -1765,7 +1765,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, t
status_t rv; status_t rv;
rv = GetDormantFlavorInfo(addonid, flavorid, &node_info); rv = GetDormantFlavorInfo(addonid, flavorid, &node_info);
if (rv != B_OK) { if (rv != B_OK) {
FATAL("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavour-id %ld\n", addonid, flavorid); FATAL("BMediaRosterEx::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
return B_ERROR; return B_ERROR;
} }
@ -1784,7 +1784,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, t
// flavor is limited. // flavor is limited.
rv = IncrementAddonFlavorInstancesCount(addonid, flavorid); rv = IncrementAddonFlavorInstancesCount(addonid, flavorid);
if (rv != B_OK) { if (rv != B_OK) {
FATAL("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavour-id %ld\n", addonid, flavorid); FATAL("BMediaRosterEx::InstantiateDormantNode error: can't create more nodes for addon-id %ld, flavor-id %ld\n", addonid, flavorid);
// Put the addon back into the pool // Put the addon back into the pool
_DormantNodeManager->PutAddon(addonid); _DormantNodeManager->PutAddon(addonid);
return B_ERROR; return B_ERROR;
@ -1874,8 +1874,8 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
status_t rv; status_t rv;
rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info); rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info);
if (rv != B_OK) { if (rv != B_OK) {
FATAL("BMediaRoster::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavour-id %ld\n", in_info.addon, in_info.flavor_id); FATAL("BMediaRoster::InstantiateDormantNode error: failed to get dormant_flavor_info for addon-id %ld, flavor-id %ld\n", in_info.addon, in_info.flavor_id);
return B_ERROR; return B_NAME_NOT_FOUND;
} }
ASSERT(node_info.internal_id == in_info.flavor_id); ASSERT(node_info.internal_id == in_info.flavor_id);
@ -1898,11 +1898,11 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
// by the caller are not incompatible. // by the caller are not incompatible.
if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) { if ((node_info.flavor_flags & B_FLAVOR_IS_GLOBAL) && (flags & B_FLAVOR_IS_LOCAL)) {
FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n"); FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_LOCAL, but dormant node has B_FLAVOR_IS_GLOBAL\n");
return B_BAD_VALUE; return B_NAME_NOT_FOUND;
} }
if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) { if ((node_info.flavor_flags & B_FLAVOR_IS_LOCAL) && (flags & B_FLAVOR_IS_GLOBAL)) {
FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n"); FATAL("BMediaRoster::InstantiateDormantNode Error: requested B_FLAVOR_IS_GLOBAL, but dormant node has B_FLAVOR_IS_LOCAL\n");
return B_BAD_VALUE; return B_NAME_NOT_FOUND;
} }
// If either the node, or the caller requested to make the instance global // If either the node, or the caller requested to make the instance global
@ -1915,23 +1915,25 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info,
addonserver_instantiate_dormant_node_request request; addonserver_instantiate_dormant_node_request request;
addonserver_instantiate_dormant_node_reply reply; addonserver_instantiate_dormant_node_reply reply;
status_t rv;
request.addonid = in_info.addon; request.addonid = in_info.addon;
request.flavorid = in_info.flavor_id; request.flavorid = in_info.flavor_id;
request.creator_team = team; // creator team is allowed to also release global nodes request.creator_team = team; // creator team is allowed to also release global nodes
rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply)); rv = QueryAddonServer(ADDONSERVER_INSTANTIATE_DORMANT_NODE, &request, sizeof(request), &reply, sizeof(reply));
if (rv == B_OK) { if (rv == B_OK) {
*out_node = reply.node; *out_node = reply.node;
} else {
*out_node = media_node::null;
} }
return rv;
} else { } else {
// creator team = -1, as this is a local node // creator team = -1, as this is a local node
return MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node); rv = MediaRosterEx(this)->InstantiateDormantNode(in_info.addon, in_info.flavor_id, -1, out_node);
} }
if (rv != B_OK) {
*out_node = media_node::null;
return B_NAME_NOT_FOUND;
}
return B_OK;
} }

View File

@ -13,6 +13,7 @@
#include <MediaAddOn.h> #include <MediaAddOn.h>
#include "debug.h" #include "debug.h"
#include "NodeManager.h" #include "NodeManager.h"
#include "DefaultManager.h"
#include "AppManager.h" #include "AppManager.h"
extern AppManager *gAppManager; extern AppManager *gAppManager;
@ -23,7 +24,7 @@ NodeManager::NodeManager() :
fNextAddOnID(1), fNextAddOnID(1),
fNextNodeID(1), fNextNodeID(1),
fLocker(new BLocker("node manager locker")), fLocker(new BLocker("node manager locker")),
fDormantFlavorList(new List<dormant_flavor_info>), fDormantAddonFlavorList(new List<dormant_addon_flavor_info>),
fAddonPathMap(new Map<media_addon_id, entry_ref>), fAddonPathMap(new Map<media_addon_id, entry_ref>),
fRegisteredNodeMap(new Map<media_node_id, registered_node>), fRegisteredNodeMap(new Map<media_node_id, registered_node>),
fDefaultManager(new DefaultManager) fDefaultManager(new DefaultManager)
@ -34,12 +35,15 @@ NodeManager::NodeManager() :
NodeManager::~NodeManager() NodeManager::~NodeManager()
{ {
delete fLocker; delete fLocker;
delete fDormantFlavorList; delete fDormantAddonFlavorList;
delete fAddonPathMap; delete fAddonPathMap;
delete fRegisteredNodeMap; delete fRegisteredNodeMap;
delete fDefaultManager; delete fDefaultManager;
} }
/**********************************************************************
* Live node management
**********************************************************************/
status_t status_t
NodeManager::RegisterNode(media_node_id *nodeid, media_addon_id addon_id, int32 addon_flavor_id, const char *name, uint64 kinds, port_id port, team_id team) NodeManager::RegisterNode(media_node_id *nodeid, media_addon_id addon_id, int32 addon_flavor_id, const char *name, uint64 kinds, port_id port, team_id team)
@ -366,6 +370,30 @@ NodeManager::FindNodeId(media_node_id *nodeid, port_id port)
return B_ERROR; return B_ERROR;
} }
status_t
NodeManager::GetDormantNodeInfo(dormant_node_info *node_info, const media_node &node)
{
BAutolock lock(fLocker);
// XXX not sure if this is correct
registered_node *rn;
for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) {
if (rn->nodeid == node.node) {
if (rn->addon_id == -1) { // This function must return an error if the node is application owned
TRACE("NodeManager::GetDormantNodeInfo NODE IS APPLICATION OWNED! node %ld, addon_id %ld, addon_flavor_id %ld, name \"%s\"\n", node.node, rn->addon_id, rn->addon_flavor_id, rn->name);
return B_ERROR;
}
ASSERT(node.port == rn->port);
ASSERT(node.kind == rn->kinds);
node_info->addon = rn->addon_id;
node_info->flavor_id = rn->addon_flavor_id;
strcpy(node_info->name, rn->name);
TRACE("NodeManager::GetDormantNodeInfo node %ld, addon_id %ld, addon_flavor_id %ld, name \"%s\"\n", node.node, rn->addon_id, rn->addon_flavor_id, rn->name);
return B_OK;
}
}
FATAL("!!! NodeManager::GetDormantNodeInfo failed, node %ld\n", node.node);
return B_ERROR;
}
status_t status_t
NodeManager::GetLiveNodeInfo(live_node_info *live_info, const media_node &node) NodeManager::GetLiveNodeInfo(live_node_info *live_info, const media_node &node)
@ -469,34 +497,6 @@ NodeManager::GetLiveNodes(Stack<live_node_info> *livenodes, int32 maxcount, cons
return B_OK; return B_OK;
} }
status_t
NodeManager::GetDormantNodeInfo(dormant_node_info *node_info, const media_node &node)
{
BAutolock lock(fLocker);
// XXX not sure if this is correct
registered_node *rn;
for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) {
if (rn->nodeid == node.node) {
if (rn->addon_id == -1) { // This function must return an error if the node is application owned
TRACE("NodeManager::GetDormantNodeInfo NODE IS APPLICATION OWNED! node %ld, addon_id %ld, addon_flavor_id %ld, name \"%s\"\n", node.node, rn->addon_id, rn->addon_flavor_id, rn->name);
return B_ERROR;
}
ASSERT(node.port == rn->port);
ASSERT(node.kind == rn->kinds);
node_info->addon = rn->addon_id;
node_info->flavor_id = rn->addon_flavor_id;
strcpy(node_info->name, rn->name);
TRACE("NodeManager::GetDormantNodeInfo node %ld, addon_id %ld, addon_flavor_id %ld, name \"%s\"\n", node.node, rn->addon_id, rn->addon_flavor_id, rn->name);
return B_OK;
}
}
FATAL("!!! NodeManager::GetDormantNodeInfo failed, node %ld\n", node.node);
return B_ERROR;
}
/* Add media_node_id of all live nodes to the message /* Add media_node_id of all live nodes to the message
* int32 "media_node_id" (multiple items) * int32 "media_node_id" (multiple items)
*/ */
@ -511,6 +511,10 @@ NodeManager::GetLiveNodes(BMessage *msg)
return B_OK; return B_OK;
} }
/**********************************************************************
* Registration of BMediaAddOns
**********************************************************************/
void void
NodeManager::RegisterAddon(const entry_ref &ref, media_addon_id *newid) NodeManager::RegisterAddon(const entry_ref &ref, media_addon_id *newid)
{ {
@ -536,42 +540,6 @@ NodeManager::UnregisterAddon(media_addon_id id)
fAddonPathMap->Remove(id); fAddonPathMap->Remove(id);
} }
// this function is only called (indirectly) by the media_addon_server
void
NodeManager::AddDormantFlavorInfo(const dormant_flavor_info &dfi)
{
BAutolock lock(fLocker);
printf("NodeManager::AddDormantFlavorInfo, addon-id %ld, flavor-id %ld, name \"%s\", flavor-name \"%s\", flavor-info \"%s\"\n", dfi.node_info.addon, dfi.node_info.flavor_id, dfi.node_info.name, dfi.name, dfi.info);
fDormantFlavorList->Insert(dfi);
}
// this function is only called (indirectly) by the media_addon_server
void
NodeManager::RemoveDormantFlavorInfo(media_addon_id id)
{
BAutolock lock(fLocker);
dormant_flavor_info *flavor;
for (fDormantFlavorList->Rewind(); fDormantFlavorList->GetNext(&flavor); ) {
if (flavor->node_info.addon == id) {
printf("NodeManager::RemoveDormantFlavorInfo, addon-id %ld, flavor-id %ld, name \"%s\", flavor-name \"%s\", flavor-info \"%s\"\n", flavor->node_info.addon, flavor->node_info.flavor_id, flavor->node_info.name, flavor->name, flavor->info);
fDormantFlavorList->RemoveCurrent();
}
}
}
// this function is called when the media_addon_server has crashed
void
NodeManager::CleanupDormantFlavorInfos()
{
BAutolock lock(fLocker);
printf("NodeManager::CleanupDormantFlavorInfos\n");
fDormantFlavorList->MakeEmpty();
printf("NodeManager::CleanupDormantFlavorInfos done\n");
// XXX FlavorsChanged(media_addon_id addonid, int32 newcount, int32 gonecount)
}
status_t status_t
NodeManager::GetAddonRef(entry_ref *ref, media_addon_id id) NodeManager::GetAddonRef(entry_ref *ref, media_addon_id id)
{ {
@ -586,6 +554,151 @@ NodeManager::GetAddonRef(entry_ref *ref, media_addon_id id)
return B_ERROR; return B_ERROR;
} }
/**********************************************************************
* Registration of node flavors, published by BMediaAddOns
**********************************************************************/
// this function is only called (indirectly) by the media_addon_server
void
NodeManager::AddDormantFlavorInfo(const dormant_flavor_info &dfi)
{
BAutolock lock(fLocker);
printf("NodeManager::AddDormantFlavorInfo, addon-id %ld, flavor-id %ld, name \"%s\", flavor-name \"%s\", flavor-info \"%s\"\n", dfi.node_info.addon, dfi.node_info.flavor_id, dfi.node_info.name, dfi.name, dfi.info);
// Try to find the addon-id/flavor-id in the list.
// If it already exists, update the Info, but don't
// change the GlobalInstancesCount
dormant_addon_flavor_info *dafi;
for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) {
if (dafi->AddonID != dfi.node_info.addon || dafi->AddonFlavorID != dfi.node_info.flavor_id)
continue;
if (dafi->InfoValid) {
FATAL("NodeManager::AddDormantFlavorInfo, addon-id %ld, flavor-id %ld does already exist\n", dafi->Info.node_info.addon, dafi->Info.node_info.flavor_id);
}
TRACE("NodeManager::AddDormantFlavorInfo, updating addon-id %ld, flavor-id %ld\n", dafi->Info.node_info.addon, dafi->Info.node_info.flavor_id);
dafi->MaxInstancesCount = dfi.possible_count > 0 ? dfi.possible_count : 0x7fffffff;
// do NOT modify dafi.GlobalInstancesCount
dafi->InfoValid = true;
dafi->Info = dfi;
return;
}
// Insert information into the list
{
dormant_addon_flavor_info dafi;
dafi.AddonID = dfi.node_info.addon;
dafi.AddonFlavorID = dfi.node_info.flavor_id;
dafi.MaxInstancesCount = dfi.possible_count > 0 ? dfi.possible_count : 0x7fffffff;
dafi.GlobalInstancesCount = 0;
dafi.InfoValid = true;
dafi.Info = dfi;
fDormantAddonFlavorList->Insert(dafi);
}
}
// this function is only called (indirectly) by the media_addon_server
void
NodeManager::InvalidateDormantFlavorInfo(media_addon_id id)
{
BAutolock lock(fLocker);
dormant_addon_flavor_info *dafi;
for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) {
if (dafi->AddonID == id && dafi->InfoValid == true) {
printf("NodeManager::InvalidateDormantFlavorInfo, addon-id %ld, flavor-id %ld, name \"%s\", flavor-name \"%s\", flavor-info \"%s\"\n", dafi->Info.node_info.addon, dafi->Info.node_info.flavor_id, dafi->Info.node_info.name, dafi->Info.name, dafi->Info.info);
dormant_flavor_info dfi_null;
dafi->Info = dfi_null;
dafi->InfoValid = false;
}
}
}
// this function is only called by clean up after gone add-ons
void
NodeManager::RemoveDormantFlavorInfo(media_addon_id id)
{
BAutolock lock(fLocker);
dormant_addon_flavor_info *dafi;
for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) {
if (dafi->AddonID == id) {
printf("NodeManager::RemoveDormantFlavorInfo, addon-id %ld, flavor-id %ld, name \"%s\", flavor-name \"%s\", flavor-info \"%s\"\n", dafi->Info.node_info.addon, dafi->Info.node_info.flavor_id, dafi->Info.node_info.name, dafi->Info.name, dafi->Info.info);
fDormantAddonFlavorList->RemoveCurrent();
}
}
}
status_t
NodeManager::IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid, team_id team)
{
BAutolock lock(fLocker);
dormant_addon_flavor_info *dafi;
for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) {
if (dafi->AddonID != addonid || dafi->AddonFlavorID != flavorid)
continue;
if (dafi->GlobalInstancesCount >= dafi->MaxInstancesCount) {
FATAL("NodeManager::IncrementAddonFlavorInstancesCount addonid %ld, flavorid %ld maximum (or more) instances already exist\n", addonid, flavorid);
return B_ERROR; // maximum (or more) instances already exist
}
bool b;
int32 *count;
b = dafi->TeamInstancesCount.Get(team, &count);
if (b) {
*count += 1;
} else {
b = dafi->TeamInstancesCount.Insert(team, 1);
ASSERT(b);
}
dafi->GlobalInstancesCount += 1;
return B_OK;
}
FATAL("NodeManager::IncrementAddonFlavorInstancesCount addonid %ld, flavorid %ld not found\n", addonid, flavorid);
return B_ERROR;
}
status_t
NodeManager::DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid, team_id team)
{
BAutolock lock(fLocker);
dormant_addon_flavor_info *dafi;
for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) {
if (dafi->AddonID != addonid || dafi->AddonFlavorID != flavorid)
continue;
bool b;
int32 *count;
b = dafi->TeamInstancesCount.Get(team, &count);
if (!b) {
FATAL("NodeManager::DecrementAddonFlavorInstancesCount addonid %ld, flavorid %ld team %ld has no references\n", addonid, flavorid, team);
return B_ERROR;
}
*count -= 1;
if (*count == 0) {
b = dafi->TeamInstancesCount.Remove(team);
ASSERT(b);
}
if (dafi->GlobalInstancesCount > 0) // avoid underflow
dafi->GlobalInstancesCount -= 1;
return B_OK;
}
FATAL("NodeManager::DecrementAddonFlavorInstancesCount addonid %ld, flavorid %ld not found\n", addonid, flavorid);
return B_ERROR;
}
// this function is called when the media_addon_server has crashed
void
NodeManager::CleanupDormantFlavorInfos()
{
BAutolock lock(fLocker);
printf("NodeManager::CleanupDormantFlavorInfos\n");
fDormantAddonFlavorList->MakeEmpty();
printf("NodeManager::CleanupDormantFlavorInfos done\n");
// XXX FlavorsChanged(media_addon_id addonid, int32 newcount, int32 gonecount)
}
status_t status_t
NodeManager::GetDormantNodes(dormant_node_info * out_info, NodeManager::GetDormantNodes(dormant_node_info * out_info,
int32 * io_count, int32 * io_count,
@ -596,8 +709,8 @@ NodeManager::GetDormantNodes(dormant_node_info * out_info,
uint64 deny_kinds /* = NULL */) uint64 deny_kinds /* = NULL */)
{ {
BAutolock lock(fLocker); BAutolock lock(fLocker);
dormant_addon_flavor_info *dafi;
int32 maxcount; int32 maxcount;
dormant_flavor_info *dfi;
int namelen; int namelen;
// determine the count of byte to compare when checking for a name with(out) wildcard // determine the count of byte to compare when checking for a name with(out) wildcard
@ -612,7 +725,13 @@ NodeManager::GetDormantNodes(dormant_node_info * out_info,
maxcount = *io_count; maxcount = *io_count;
*io_count = 0; *io_count = 0;
for (fDormantFlavorList->Rewind(); (*io_count < maxcount) && fDormantFlavorList->GetNext(&dfi); ) { for (fDormantAddonFlavorList->Rewind(); (*io_count < maxcount) && fDormantAddonFlavorList->GetNext(&dafi); ) {
if (!dafi->InfoValid)
continue;
dormant_flavor_info *dfi;
dfi = &dafi->Info;
if ((dfi->kinds & require_kinds) != require_kinds) if ((dfi->kinds & require_kinds) != require_kinds)
continue; continue;
if ((dfi->kinds & deny_kinds) != 0) if ((dfi->kinds & deny_kinds) != 0)
@ -655,16 +774,20 @@ NodeManager::GetDormantFlavorInfoFor(media_addon_id addon,
dormant_flavor_info *outFlavor) dormant_flavor_info *outFlavor)
{ {
BAutolock lock(fLocker); BAutolock lock(fLocker);
dormant_flavor_info *flavor; dormant_addon_flavor_info *dafi;
for (fDormantFlavorList->Rewind(); fDormantFlavorList->GetNext(&flavor); ) { for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) {
if (flavor->node_info.addon == addon && flavor->node_info.flavor_id == flavor_id) { if (dafi->AddonID == addon && dafi->AddonFlavorID == flavor_id && dafi->InfoValid == true) {
*outFlavor = *flavor; *outFlavor = dafi->Info;
return B_OK; return B_OK;
} }
} }
return B_ERROR; return B_ERROR;
} }
/**********************************************************************
* Default node management
**********************************************************************/
status_t status_t
NodeManager::SetDefaultNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input) NodeManager::SetDefaultNode(node_type type, const media_node *node, const dormant_node_info *info, const media_input *input)
{ {
@ -686,6 +809,10 @@ NodeManager::RescanDefaultNodes()
return fDefaultManager->Rescan(); return fDefaultManager->Rescan();
} }
/**********************************************************************
* Cleanup of dead teams
**********************************************************************/
void void
NodeManager::CleanupTeam(team_id team) NodeManager::CleanupTeam(team_id team)
{ {
@ -697,9 +824,12 @@ NodeManager::CleanupTeam(team_id team)
// XXX send notifications after removing nodes // XXX send notifications after removing nodes
// Cleanup node references
registered_node *rn; registered_node *rn;
for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) { for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) {
// if the gone team was the creator of some global dormant node instance, we now invalidate that // if the gone team was the creator of some global dormant node instance, we now invalidate that
// we may want to remove that global node, but I'm not sure
if (rn->creator == team) { if (rn->creator == team) {
rn->creator = -1; rn->creator = -1;
// fall through // fall through
@ -727,8 +857,28 @@ NodeManager::CleanupTeam(team_id team)
fRegisteredNodeMap->RemoveCurrent(); fRegisteredNodeMap->RemoveCurrent();
} }
} }
// Cleanup addon references
dormant_addon_flavor_info *dafi;
for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) {
bool b;
int32 *count;
b = dafi->TeamInstancesCount.Get(team, &count);
if (b) {
FATAL("NodeManager::CleanupTeam: removing %ld instances from addon %ld, flavor %ld\n", *count, dafi->AddonID, dafi->AddonFlavorID);
dafi->GlobalInstancesCount -= *count;
if (dafi->GlobalInstancesCount < 0) // avoid underflow
dafi->GlobalInstancesCount = 0;
b = dafi->TeamInstancesCount.Remove(team);
ASSERT(b);
}
}
} }
/**********************************************************************
* State saving/loading
**********************************************************************/
status_t status_t
NodeManager::LoadState() NodeManager::LoadState()
{ {
@ -743,11 +893,18 @@ NodeManager::SaveState()
return fDefaultManager->SaveState(); return fDefaultManager->SaveState();
} }
/**********************************************************************
* Debugging
**********************************************************************/
void void
NodeManager::Dump() NodeManager::Dump()
{ {
BAutolock lock(fLocker); BAutolock lock(fLocker);
printf("\n"); printf("\n");
/* for each addon-id, the addon path map contians an entry_ref
*/
printf("NodeManager: addon path map follows:\n"); printf("NodeManager: addon path map follows:\n");
entry_ref *ref; entry_ref *ref;
media_addon_id *id; media_addon_id *id;
@ -758,11 +915,14 @@ NodeManager::Dump()
} }
printf("NodeManager: list end\n"); printf("NodeManager: list end\n");
printf("\n"); printf("\n");
/* for each node-id, the registered node map contians information about source of the node, users, etc.
*/
printf("NodeManager: registered nodes map follows:\n"); printf("NodeManager: registered nodes map follows:\n");
registered_node *rn; registered_node *rn;
for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) { for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) {
printf(" node-id %ld, addon-id %ld, addon-flavor-id %ld, port %ld, team %ld, kinds %#08Lx, name \"%s\"\n", printf(" node-id %ld, addon-id %ld, addon-flavor-id %ld, port %ld, creator %ld, team %ld, kinds %#08Lx, name \"%s\"\n",
rn->nodeid, rn->addon_id, rn->addon_flavor_id, rn->port, rn->team, rn->kinds, rn->name); rn->nodeid, rn->addon_id, rn->addon_flavor_id, rn->port, rn->creator, rn->team, rn->kinds, rn->name);
printf(" teams (refcount): "); printf(" teams (refcount): ");
team_id *team; team_id *team;
int32 *refcount; int32 *refcount;
@ -784,15 +944,22 @@ NodeManager::Dump()
} }
printf("NodeManager: list end\n"); printf("NodeManager: list end\n");
printf("\n"); printf("\n");
/*
*/
printf("NodeManager: dormant flavor list follows:\n"); printf("NodeManager: dormant flavor list follows:\n");
dormant_flavor_info *dfi; dormant_addon_flavor_info *dafi;
for (fDormantFlavorList->Rewind(); fDormantFlavorList->GetNext(&dfi); ) { for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) {
printf(" addon-id %ld, addon-flavor-id %ld, addon-name \"%s\"\n", printf(" AddonID %ld, AddonFlavorID %ld, MaxInstancesCount %ld, GlobalInstancesCount %ld, InfoValid %s\n",
dfi->node_info.addon, dfi->node_info.flavor_id, dfi->node_info.name); dafi->AddonID, dafi->AddonFlavorID, dafi->MaxInstancesCount, dafi->GlobalInstancesCount, dafi->InfoValid ? "yes" : "no");
if (!dafi->InfoValid)
continue;
printf(" addon-id %ld, addon-flavor-id %ld, addon-name \"%s\"\n",
dafi->Info.node_info.addon, dafi->Info.node_info.flavor_id, dafi->Info.node_info.name);
printf(" flavor-kinds %#08Lx, flavor_flags %#08lx, internal_id %ld, possible_count %ld, in_format_count %ld, out_format_count %ld\n", printf(" flavor-kinds %#08Lx, flavor_flags %#08lx, internal_id %ld, possible_count %ld, in_format_count %ld, out_format_count %ld\n",
dfi->kinds, dfi->flavor_flags, dfi->internal_id, dfi->possible_count, dfi->in_format_count, dfi->out_format_count); dafi->Info.kinds, dafi->Info.flavor_flags, dafi->Info.internal_id, dafi->Info.possible_count, dafi->Info.in_format_count, dafi->Info.out_format_count);
printf(" flavor-name \"%s\"\n", dfi->name); printf(" flavor-name \"%s\"\n", dafi->Info.name);
printf(" flavor-info \"%s\"\n", dfi->info); printf(" flavor-info \"%s\"\n", dafi->Info.info);
} }
printf("NodeManager: list end\n"); printf("NodeManager: list end\n");
fDefaultManager->Dump(); fDefaultManager->Dump();

View File

@ -6,7 +6,6 @@
#include "TMap.h" #include "TMap.h"
#include "TStack.h" #include "TStack.h"
#include "DataExchange.h" #include "DataExchange.h"
#include "DefaultManager.h"
struct registered_node struct registered_node
{ {
@ -24,6 +23,21 @@ struct registered_node
List<media_output> outputlist; List<media_output> outputlist;
}; };
struct dormant_addon_flavor_info
{
media_addon_id AddonID;
int32 AddonFlavorID;
int32 MaxInstancesCount;
int32 GlobalInstancesCount;
Map<team_id, int32> TeamInstancesCount;
bool InfoValid;
dormant_flavor_info Info;
};
class DefaultManager;
class BufferManager; class BufferManager;
class NodeManager class NodeManager
@ -31,19 +45,7 @@ class NodeManager
public: public:
NodeManager(); NodeManager();
~NodeManager(); ~NodeManager();
status_t RegisterNode(BMessenger, media_node &, char const *, long *, char const *, long, char const *, long, media_type, media_type);
status_t UnregisterNode(long);
status_t GetNodes(BMessage &, char const *);
status_t GetLiveNode(BMessage &, char const *, long);
status_t GetLiveNodes(BMessage &, char const *, media_format const *, media_format const *, char const *, unsigned long);
status_t FindNode(long, media_node &);
status_t FindSaveInfo(long, char const **, long *, long *, char const **);
status_t FindDormantNodeFor(long, dormant_node_info *);
status_t FindNodesFor(long, long, BMessage &, char const *);
status_t FindNodesForPort(long, BMessage &, char const *);
status_t UnregisterTeamNodes(long, BMessage &, char const *, long *, BufferManager *);
status_t DumpGlobalReferences(BMessage &, char const *);
status_t BroadcastMessage(long, void *, long, long long);
status_t LoadState(); status_t LoadState();
status_t SaveState(); status_t SaveState();
@ -76,12 +78,18 @@ public:
* int32 "media_node_id" (multiple items) * int32 "media_node_id" (multiple items)
*/ */
status_t GetLiveNodes(BMessage *msg); status_t GetLiveNodes(BMessage *msg);
void AddDormantFlavorInfo(const dormant_flavor_info &dfi);
void RemoveDormantFlavorInfo(media_addon_id id);
void CleanupDormantFlavorInfos();
void RegisterAddon(const entry_ref &ref, media_addon_id *newid); void RegisterAddon(const entry_ref &ref, media_addon_id *newid);
void UnregisterAddon(media_addon_id id); void UnregisterAddon(media_addon_id id);
void AddDormantFlavorInfo(const dormant_flavor_info &dfi);
void InvalidateDormantFlavorInfo(media_addon_id id);
void RemoveDormantFlavorInfo(media_addon_id id);
void CleanupDormantFlavorInfos();
status_t IncrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid, team_id team);
status_t DecrementAddonFlavorInstancesCount(media_addon_id addonid, int32 flavorid, team_id team);
status_t GetAddonRef(entry_ref *ref, media_addon_id id); status_t GetAddonRef(entry_ref *ref, media_addon_id id);
status_t GetDormantNodes(dormant_node_info * out_info, status_t GetDormantNodes(dormant_node_info * out_info,
int32 * io_count, int32 * io_count,
@ -102,7 +110,7 @@ private:
media_node_id fNextNodeID; media_node_id fNextNodeID;
BLocker *fLocker; BLocker *fLocker;
List<dormant_flavor_info> *fDormantFlavorList; List<dormant_addon_flavor_info> *fDormantAddonFlavorList;
Map<media_addon_id,entry_ref> *fAddonPathMap; Map<media_addon_id,entry_ref> *fAddonPathMap;
Map<media_node_id,registered_node> *fRegisteredNodeMap; Map<media_node_id,registered_node> *fRegisteredNodeMap;
DefaultManager *fDefaultManager; DefaultManager *fDefaultManager;

View File

@ -175,6 +175,19 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size)
status_t rv; status_t rv;
INFO("ServerApp::HandleMessage %#lx\n", code); INFO("ServerApp::HandleMessage %#lx\n", code);
switch (code) { switch (code) {
case SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT:
{
const server_change_addon_flavor_instances_count_request *request = reinterpret_cast<const server_change_addon_flavor_instances_count_request *>(data);
server_change_addon_flavor_instances_count_reply reply;
ASSERT(request->delta == 1 || request->delta == -1);
if (request->delta == 1)
rv = gNodeManager->IncrementAddonFlavorInstancesCount(request->addonid, request->flavorid, request->team);
else
rv = gNodeManager->DecrementAddonFlavorInstancesCount(request->addonid, request->flavorid, request->team);
request->SendReply(rv, &reply, sizeof(reply));
break;
}
case SERVER_RESCAN_DEFAULTS: case SERVER_RESCAN_DEFAULTS:
{ {
gNodeManager->RescanDefaultNodes(); gNodeManager->RescanDefaultNodes();
@ -415,7 +428,7 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size)
xfer_server_register_dormant_node *msg = (xfer_server_register_dormant_node *)data; xfer_server_register_dormant_node *msg = (xfer_server_register_dormant_node *)data;
dormant_flavor_info dfi; dormant_flavor_info dfi;
if (msg->purge_id > 0) if (msg->purge_id > 0)
gNodeManager->RemoveDormantFlavorInfo(msg->purge_id); gNodeManager->InvalidateDormantFlavorInfo(msg->purge_id);
rv = dfi.Unflatten(msg->dfi_type, &(msg->dfi), msg->dfi_size); rv = dfi.Unflatten(msg->dfi_type, &(msg->dfi), msg->dfi_size);
ASSERT(rv == B_OK); ASSERT(rv == B_OK);
gNodeManager->AddDormantFlavorInfo(dfi); gNodeManager->AddDormantFlavorInfo(dfi);