From 626824eaaf91ec35de3ca9eb737f87d98ffb6121 Mon Sep 17 00:00:00 2001 From: beveloper Date: Sat, 22 Mar 2003 01:11:07 +0000 Subject: [PATCH] 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 --- headers/private/media/DataExchange.h | 90 +------ headers/private/media/MediaRosterEx.h | 4 +- src/kits/media/DataExchange.cpp | 2 +- src/kits/media/MediaRoster.cpp | 26 +- src/servers/media/NodeManager.cpp | 329 +++++++++++++++++++------- src/servers/media/NodeManager.h | 46 ++-- src/servers/media/media_server.cpp | 15 +- 7 files changed, 316 insertions(+), 196 deletions(-) diff --git a/headers/private/media/DataExchange.h b/headers/private/media/DataExchange.h index d80f597979..480c981f36 100644 --- a/headers/private/media/DataExchange.h +++ b/headers/private/media/DataExchange.h @@ -98,7 +98,7 @@ enum { SERVER_UNREGISTER_BUFFER, SERVER_RESCAN_DEFAULTS, SERVER_SET_NODE_CREATOR, - SERVER_CHANGE_DORMANT_NODE_USECOUNT, + SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT, SERVER_MESSAGE_END, NODE_MESSAGE_START = 0x200, @@ -210,14 +210,14 @@ enum node_type // used by SERVER_PUBLISH_INPUTS and SERVER_PUBLISH_OUTPUTS enum { - MAX_OUTPUTS = 48, - MAX_INPUTS = 48, + MAX_OUTPUTS = 8, + MAX_INPUTS = 8, }; // used by SERVER_GET_LIVE_NODES enum { - MAX_LIVE_INFO = 62, + MAX_LIVE_INFO = 16, }; // 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 { media_type type; @@ -437,36 +421,6 @@ struct producer_late_notice_received_command : public command_data bigtime_t performance_time; }; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - struct consumer_accept_format_request : public request_data { media_destination dest; @@ -568,22 +522,6 @@ struct consumer_disconnected_reply : public reply_data { }; - - - - - - - - - - - - - - - - struct consumer_buffer_received_command : public command_data { media_buffer_id buffer; @@ -634,12 +572,6 @@ struct consumer_seek_tag_requested_reply : public reply_data uint32 flags; }; - - - - - - struct server_register_addonserver_request : public request_data { 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; - int32 addon_flavor_id; - int32 delta; + media_addon_id addonid; + int32 flavorid; + 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 { media_addon_id addonid; diff --git a/headers/private/media/MediaRosterEx.h b/headers/private/media/MediaRosterEx.h index 376ce2513e..55a6fdd692 100644 --- a/headers/private/media/MediaRosterEx.h +++ b/headers/private/media/MediaRosterEx.h @@ -35,8 +35,8 @@ public: status_t SaveNodeConfiguration(BMediaNode *node); status_t LoadNodeConfiguration(media_addon_id addonid, int32 flavorid, BMessage *out_msg); - status_t IncrementDormantNodeUseCount(media_addon_id addonid, int32 flavorid); - status_t DecrementDormantNodeUseCount(media_addon_id addonid, int32 flavorid); + status_t IncrementAddonFlavorInstancesCount(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); diff --git a/src/kits/media/DataExchange.cpp b/src/kits/media/DataExchange.cpp index 8902ad9514..6ab35a0371 100644 --- a/src/kits/media/DataExchange.cpp +++ b/src/kits/media/DataExchange.cpp @@ -11,7 +11,7 @@ #include "DataExchange.h" #include "ServerInterface.h" // NEW_MEDIA_SERVER_SIGNATURE -#define TIMEOUT 5000000 // 5 seconds timeout! +#define TIMEOUT 15000000 // 15 seconds timeout! namespace BPrivate { namespace media { diff --git a/src/kits/media/MediaRoster.cpp b/src/kits/media/MediaRoster.cpp index 307bb547d8..1845aec640 100644 --- a/src/kits/media/MediaRoster.cpp +++ b/src/kits/media/MediaRoster.cpp @@ -1765,7 +1765,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, t status_t rv; rv = GetDormantFlavorInfo(addonid, flavorid, &node_info); 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; } @@ -1784,7 +1784,7 @@ BMediaRosterEx::InstantiateDormantNode(media_addon_id addonid, int32 flavorid, t // flavor is limited. rv = IncrementAddonFlavorInstancesCount(addonid, flavorid); 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 _DormantNodeManager->PutAddon(addonid); return B_ERROR; @@ -1874,8 +1874,8 @@ BMediaRoster::InstantiateDormantNode(const dormant_node_info & in_info, status_t rv; rv = MediaRosterEx(this)->GetDormantFlavorInfo(in_info.addon, in_info.flavor_id, &node_info); 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); - return B_ERROR; + 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_NAME_NOT_FOUND; } 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. 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"); - return B_BAD_VALUE; + return B_NAME_NOT_FOUND; } 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"); - return B_BAD_VALUE; + return B_NAME_NOT_FOUND; } // 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_reply reply; - status_t rv; request.addonid = in_info.addon; request.flavorid = in_info.flavor_id; 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)); if (rv == B_OK) { *out_node = reply.node; - } else { - *out_node = media_node::null; } - return rv; } else { - + // 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; } diff --git a/src/servers/media/NodeManager.cpp b/src/servers/media/NodeManager.cpp index 6bacaad3b4..d0a53d040a 100644 --- a/src/servers/media/NodeManager.cpp +++ b/src/servers/media/NodeManager.cpp @@ -13,6 +13,7 @@ #include #include "debug.h" #include "NodeManager.h" +#include "DefaultManager.h" #include "AppManager.h" extern AppManager *gAppManager; @@ -23,7 +24,7 @@ NodeManager::NodeManager() : fNextAddOnID(1), fNextNodeID(1), fLocker(new BLocker("node manager locker")), - fDormantFlavorList(new List), + fDormantAddonFlavorList(new List), fAddonPathMap(new Map), fRegisteredNodeMap(new Map), fDefaultManager(new DefaultManager) @@ -34,12 +35,15 @@ NodeManager::NodeManager() : NodeManager::~NodeManager() { delete fLocker; - delete fDormantFlavorList; + delete fDormantAddonFlavorList; delete fAddonPathMap; delete fRegisteredNodeMap; delete fDefaultManager; } +/********************************************************************** + * Live node management + **********************************************************************/ 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) @@ -366,6 +370,30 @@ NodeManager::FindNodeId(media_node_id *nodeid, port_id port) 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 NodeManager::GetLiveNodeInfo(live_node_info *live_info, const media_node &node) @@ -469,34 +497,6 @@ NodeManager::GetLiveNodes(Stack *livenodes, int32 maxcount, cons 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 * int32 "media_node_id" (multiple items) */ @@ -511,6 +511,10 @@ NodeManager::GetLiveNodes(BMessage *msg) return B_OK; } +/********************************************************************** + * Registration of BMediaAddOns + **********************************************************************/ + void NodeManager::RegisterAddon(const entry_ref &ref, media_addon_id *newid) { @@ -536,42 +540,6 @@ NodeManager::UnregisterAddon(media_addon_id 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 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; } +/********************************************************************** + * 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 NodeManager::GetDormantNodes(dormant_node_info * out_info, int32 * io_count, @@ -596,8 +709,8 @@ NodeManager::GetDormantNodes(dormant_node_info * out_info, uint64 deny_kinds /* = NULL */) { BAutolock lock(fLocker); + dormant_addon_flavor_info *dafi; int32 maxcount; - dormant_flavor_info *dfi; int namelen; // 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; *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) continue; if ((dfi->kinds & deny_kinds) != 0) @@ -655,16 +774,20 @@ NodeManager::GetDormantFlavorInfoFor(media_addon_id addon, dormant_flavor_info *outFlavor) { BAutolock lock(fLocker); - dormant_flavor_info *flavor; - for (fDormantFlavorList->Rewind(); fDormantFlavorList->GetNext(&flavor); ) { - if (flavor->node_info.addon == addon && flavor->node_info.flavor_id == flavor_id) { - *outFlavor = *flavor; + dormant_addon_flavor_info *dafi; + for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) { + if (dafi->AddonID == addon && dafi->AddonFlavorID == flavor_id && dafi->InfoValid == true) { + *outFlavor = dafi->Info; return B_OK; } } return B_ERROR; } +/********************************************************************** + * Default node management + **********************************************************************/ + status_t 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(); } +/********************************************************************** + * Cleanup of dead teams + **********************************************************************/ + void NodeManager::CleanupTeam(team_id team) { @@ -697,9 +824,12 @@ NodeManager::CleanupTeam(team_id team) // XXX send notifications after removing nodes + // Cleanup node references + registered_node *rn; for (fRegisteredNodeMap->Rewind(); fRegisteredNodeMap->GetNext(&rn); ) { // 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) { rn->creator = -1; // fall through @@ -727,8 +857,28 @@ NodeManager::CleanupTeam(team_id team) 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 NodeManager::LoadState() { @@ -743,11 +893,18 @@ NodeManager::SaveState() return fDefaultManager->SaveState(); } +/********************************************************************** + * Debugging + **********************************************************************/ + void NodeManager::Dump() { BAutolock lock(fLocker); printf("\n"); + + /* for each addon-id, the addon path map contians an entry_ref + */ printf("NodeManager: addon path map follows:\n"); entry_ref *ref; media_addon_id *id; @@ -758,11 +915,14 @@ NodeManager::Dump() } printf("NodeManager: list end\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"); registered_node *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", - rn->nodeid, rn->addon_id, rn->addon_flavor_id, rn->port, rn->team, rn->kinds, rn->name); + 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->creator, rn->team, rn->kinds, rn->name); printf(" teams (refcount): "); team_id *team; int32 *refcount; @@ -784,15 +944,22 @@ NodeManager::Dump() } printf("NodeManager: list end\n"); printf("\n"); + + /* + */ printf("NodeManager: dormant flavor list follows:\n"); - dormant_flavor_info *dfi; - for (fDormantFlavorList->Rewind(); fDormantFlavorList->GetNext(&dfi); ) { - printf(" addon-id %ld, addon-flavor-id %ld, addon-name \"%s\"\n", - dfi->node_info.addon, dfi->node_info.flavor_id, dfi->node_info.name); + dormant_addon_flavor_info *dafi; + for (fDormantAddonFlavorList->Rewind(); fDormantAddonFlavorList->GetNext(&dafi); ) { + printf(" AddonID %ld, AddonFlavorID %ld, MaxInstancesCount %ld, GlobalInstancesCount %ld, InfoValid %s\n", + 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", - dfi->kinds, dfi->flavor_flags, dfi->internal_id, dfi->possible_count, dfi->in_format_count, dfi->out_format_count); - printf(" flavor-name \"%s\"\n", dfi->name); - printf(" flavor-info \"%s\"\n", dfi->info); + 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", dafi->Info.name); + printf(" flavor-info \"%s\"\n", dafi->Info.info); } printf("NodeManager: list end\n"); fDefaultManager->Dump(); diff --git a/src/servers/media/NodeManager.h b/src/servers/media/NodeManager.h index fd65957ee0..e0f7b5c42f 100644 --- a/src/servers/media/NodeManager.h +++ b/src/servers/media/NodeManager.h @@ -6,7 +6,6 @@ #include "TMap.h" #include "TStack.h" #include "DataExchange.h" -#include "DefaultManager.h" struct registered_node { @@ -24,6 +23,21 @@ struct registered_node List outputlist; }; +struct dormant_addon_flavor_info +{ + media_addon_id AddonID; + int32 AddonFlavorID; + + int32 MaxInstancesCount; + int32 GlobalInstancesCount; + + Map TeamInstancesCount; + + bool InfoValid; + dormant_flavor_info Info; +}; + +class DefaultManager; class BufferManager; class NodeManager @@ -31,19 +45,7 @@ class NodeManager public: 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 SaveState(); @@ -76,12 +78,18 @@ public: * int32 "media_node_id" (multiple items) */ 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 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 GetDormantNodes(dormant_node_info * out_info, int32 * io_count, @@ -102,7 +110,7 @@ private: media_node_id fNextNodeID; BLocker *fLocker; - List *fDormantFlavorList; + List *fDormantAddonFlavorList; Map *fAddonPathMap; Map *fRegisteredNodeMap; DefaultManager *fDefaultManager; diff --git a/src/servers/media/media_server.cpp b/src/servers/media/media_server.cpp index a1745161b5..0d79463bbc 100644 --- a/src/servers/media/media_server.cpp +++ b/src/servers/media/media_server.cpp @@ -175,6 +175,19 @@ ServerApp::HandleMessage(int32 code, void *data, size_t size) status_t rv; INFO("ServerApp::HandleMessage %#lx\n", code); switch (code) { + case SERVER_CHANGE_ADDON_FLAVOR_INSTANCES_COUNT: + { + const server_change_addon_flavor_instances_count_request *request = reinterpret_cast(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: { 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; dormant_flavor_info dfi; 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); ASSERT(rv == B_OK); gNodeManager->AddDormantFlavorInfo(dfi);