Replace synchronization semaphore with async messages
* Remove SyncToServices, I will probably readd it in future but this time using a local synchronization service more than relying on the media_server to release the semaphore. * Due to some discussions today in mailing list I decided to step back and retry the initial way to notify media rosters about media services status. It is woking by using two different notifications for reconnecting to the media_server and notifying the local subscribers. * This speed up the media services restart. * Sorry for the noise and very thanks for reviewing my code to everyone.
This commit is contained in:
@@ -44,10 +44,6 @@ public:
|
|||||||
// Check if the media services are running.
|
// Check if the media services are running.
|
||||||
static bool IsRunning();
|
static bool IsRunning();
|
||||||
|
|
||||||
// This functions blocks until the media services are available,
|
|
||||||
// don't abuse of it.
|
|
||||||
static status_t SyncToServices(bigtime_t timeout = -1);
|
|
||||||
|
|
||||||
// Getting common instances of system nodes:
|
// Getting common instances of system nodes:
|
||||||
status_t GetVideoInput(media_node* _node);
|
status_t GetVideoInput(media_node* _node);
|
||||||
status_t GetAudioInput(media_node* _node);
|
status_t GetAudioInput(media_node* _node);
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ enum {
|
|||||||
|
|
||||||
// sent by the rescan thread
|
// sent by the rescan thread
|
||||||
MEDIA_SERVER_RESCAN_COMPLETED,
|
MEDIA_SERVER_RESCAN_COMPLETED,
|
||||||
|
// sent to rosters when rescan is completed
|
||||||
|
MEDIA_SERVER_ALIVE,
|
||||||
|
|
||||||
// media add-on server
|
// media add-on server
|
||||||
MEDIA_ADD_ON_SERVER_PLAY_MEDIA = '_TRU'
|
MEDIA_ADD_ON_SERVER_PLAY_MEDIA = '_TRU'
|
||||||
@@ -373,7 +375,6 @@ struct server_register_app_request : request_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct server_register_app_reply : reply_data {
|
struct server_register_app_reply : reply_data {
|
||||||
sem_id global_synchro;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct server_unregister_app_request : request_data {
|
struct server_unregister_app_request : request_data {
|
||||||
|
|||||||
@@ -107,7 +107,6 @@ static bool sServerIsUp = false;
|
|||||||
static List<RosterNotification> sNotificationList;
|
static List<RosterNotification> sNotificationList;
|
||||||
static BLocker sInitLocker("BMediaRoster::Roster locker");
|
static BLocker sInitLocker("BMediaRoster::Roster locker");
|
||||||
static List<LocalNode> sRegisteredNodes;
|
static List<LocalNode> sRegisteredNodes;
|
||||||
static sem_id sGlobalSynchro = -1;
|
|
||||||
|
|
||||||
|
|
||||||
class MediaRosterUndertaker {
|
class MediaRosterUndertaker {
|
||||||
@@ -3345,27 +3344,6 @@ BMediaRoster::IsRunning()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
BMediaRoster::SyncToServices(bigtime_t timeout)
|
|
||||||
{
|
|
||||||
if (!IsRunning())
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
TRACE("BMediaRoster::SyncToServer: Syncing to the media server");
|
|
||||||
|
|
||||||
// This sem is valid only when the server started
|
|
||||||
// but it's not ready to supply the services.
|
|
||||||
if (sGlobalSynchro > -1)
|
|
||||||
acquire_sem_etc(sGlobalSynchro, 1, B_RELATIVE_TIMEOUT, timeout);
|
|
||||||
|
|
||||||
// TODO: Ideally this function should take into account
|
|
||||||
// the startup latencies of the system nodes and sleep
|
|
||||||
// for the resulting sum.
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ssize_t
|
ssize_t
|
||||||
BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat,
|
BMediaRoster::AudioBufferSizeFor(int32 channelCount, uint32 sampleFormat,
|
||||||
float frameRate, bus_type busKind)
|
float frameRate, bus_type busKind)
|
||||||
@@ -3465,34 +3443,12 @@ BMediaRoster::MessageReceived(BMessage* message)
|
|||||||
|
|
||||||
TRACE("BMediaRoster::MessageReceived media services are going up.");
|
TRACE("BMediaRoster::MessageReceived media services are going up.");
|
||||||
|
|
||||||
// Send the notification to our subscribers
|
|
||||||
if (BMediaRoster::IsRunning()) {
|
if (BMediaRoster::IsRunning()) {
|
||||||
SyncToServices();
|
// Wait for media services to wake up and restore our friendship
|
||||||
sServerIsUp = true;
|
|
||||||
sGlobalSynchro = -1;
|
|
||||||
// Wait for media services to wake up
|
|
||||||
// TODO: This should be solved so that the server
|
|
||||||
// have a way to notify us when the system is really
|
|
||||||
// ready to run and we avoid sleeping.
|
|
||||||
snooze(2000000);
|
|
||||||
// Restore our friendship with the media servers
|
|
||||||
if (MediaRosterEx(this)->BuildConnections() != B_OK) {
|
if (MediaRosterEx(this)->BuildConnections() != B_OK) {
|
||||||
TRACE("BMediaRoster::MessageReceived can't reconnect"
|
TRACE("BMediaRoster::MessageReceived can't reconnect"
|
||||||
"to media_server.");
|
"to media_server.");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int32 i = 0; i < sNotificationList.CountItems(); i++) {
|
|
||||||
RosterNotification* current;
|
|
||||||
if (sNotificationList.Get(i, ¤t) != true)
|
|
||||||
return;
|
|
||||||
if (current->what == B_MEDIA_SERVER_STARTED) {
|
|
||||||
if (current->messenger.SendMessage(
|
|
||||||
B_MEDIA_SERVER_STARTED) != B_OK) {
|
|
||||||
if(!current->messenger.IsValid())
|
|
||||||
sNotificationList.Remove(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3527,6 +3483,31 @@ BMediaRoster::MessageReceived(BMessage* message)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case MEDIA_SERVER_ALIVE:
|
||||||
|
{
|
||||||
|
if (!BMediaRoster::IsRunning())
|
||||||
|
return;
|
||||||
|
|
||||||
|
sServerIsUp = true;
|
||||||
|
|
||||||
|
TRACE("BMediaRoster::MessageReceived media services are"
|
||||||
|
" finally up.");
|
||||||
|
|
||||||
|
// Send the notification to our subscribers
|
||||||
|
for (int32 i = 0; i < sNotificationList.CountItems(); i++) {
|
||||||
|
RosterNotification* current;
|
||||||
|
if (sNotificationList.Get(i, ¤t) != true)
|
||||||
|
return;
|
||||||
|
if (current->what == B_MEDIA_SERVER_STARTED) {
|
||||||
|
if (current->messenger.SendMessage(
|
||||||
|
B_MEDIA_SERVER_STARTED) != B_OK) {
|
||||||
|
if(!current->messenger.IsValid())
|
||||||
|
sNotificationList.Remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case NODE_FINAL_RELEASE:
|
case NODE_FINAL_RELEASE:
|
||||||
{
|
{
|
||||||
// This function is called by a BMediaNode to delete
|
// This function is called by a BMediaNode to delete
|
||||||
|
|||||||
@@ -50,14 +50,11 @@ AppManager::AppManager()
|
|||||||
:
|
:
|
||||||
BLocker("media app manager")
|
BLocker("media app manager")
|
||||||
{
|
{
|
||||||
fGlobalSynchro = create_sem(0, "media server global synchro");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AppManager::~AppManager()
|
AppManager::~AppManager()
|
||||||
{
|
{
|
||||||
if (fGlobalSynchro != -1)
|
|
||||||
delete_sem(fGlobalSynchro);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -70,8 +67,7 @@ AppManager::HasTeam(team_id team)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
AppManager::RegisterTeam(team_id team, const BMessenger& messenger,
|
AppManager::RegisterTeam(team_id team, const BMessenger& messenger)
|
||||||
sem_id* sync)
|
|
||||||
{
|
{
|
||||||
BAutolock lock(this);
|
BAutolock lock(this);
|
||||||
|
|
||||||
@@ -88,8 +84,6 @@ AppManager::RegisterTeam(team_id team, const BMessenger& messenger,
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
*sync = fGlobalSynchro;
|
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,9 +151,13 @@ AppManager::Dump()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AppManager::UnlockGlobalSynchro()
|
AppManager::NotifyRosters()
|
||||||
{
|
{
|
||||||
delete_sem(fGlobalSynchro);
|
BAutolock lock(this);
|
||||||
|
|
||||||
|
AppMap::iterator iterator = fMap.begin();
|
||||||
|
for (; iterator != fMap.end(); iterator++)
|
||||||
|
iterator->second.SendMessage(MEDIA_SERVER_ALIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public:
|
|||||||
~AppManager();
|
~AppManager();
|
||||||
|
|
||||||
status_t RegisterTeam(team_id team,
|
status_t RegisterTeam(team_id team,
|
||||||
const BMessenger& messenger, sem_id* sync);
|
const BMessenger& messenger);
|
||||||
status_t UnregisterTeam(team_id team);
|
status_t UnregisterTeam(team_id team);
|
||||||
bool HasTeam(team_id team);
|
bool HasTeam(team_id team);
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
|
|
||||||
void Dump();
|
void Dump();
|
||||||
|
|
||||||
void UnlockGlobalSynchro();
|
void NotifyRosters();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _CleanupTeam(team_id team);
|
void _CleanupTeam(team_id team);
|
||||||
@@ -37,7 +37,6 @@ private:
|
|||||||
typedef std::map<team_id, BMessenger> AppMap;
|
typedef std::map<team_id, BMessenger> AppMap;
|
||||||
|
|
||||||
AppMap fMap;
|
AppMap fMap;
|
||||||
sem_id fGlobalSynchro;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -413,9 +413,6 @@ DefaultManager::_RescanThread()
|
|||||||
add_on_server_rescan_finished_notify_command cmd;
|
add_on_server_rescan_finished_notify_command cmd;
|
||||||
SendToAddOnServer(ADD_ON_SERVER_RESCAN_FINISHED_NOTIFY, &cmd,
|
SendToAddOnServer(ADD_ON_SERVER_RESCAN_FINISHED_NOTIFY, &cmd,
|
||||||
sizeof(cmd));
|
sizeof(cmd));
|
||||||
|
|
||||||
BMessage msg(MEDIA_SERVER_RESCAN_COMPLETED);
|
|
||||||
be_app->PostMessage(&msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
locker.Lock();
|
locker.Lock();
|
||||||
@@ -423,6 +420,9 @@ DefaultManager::_RescanThread()
|
|||||||
|
|
||||||
fRescanThread = -1;
|
fRescanThread = -1;
|
||||||
|
|
||||||
|
BMessage msg(MEDIA_SERVER_RESCAN_COMPLETED);
|
||||||
|
be_app->PostMessage(&msg);
|
||||||
|
|
||||||
TRACE("DefaultManager::_RescanThread() leave\n");
|
TRACE("DefaultManager::_RescanThread() leave\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ SubDir HAIKU_TOP src servers media ;
|
|||||||
|
|
||||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
|
|
||||||
UsePrivateHeaders media shared storage app ;
|
UsePrivateHeaders app media shared storage ;
|
||||||
UsePrivateSystemHeaders ;
|
UsePrivateSystemHeaders ;
|
||||||
|
|
||||||
AddResources media_server : media_server.rdef ;
|
AddResources media_server : media_server.rdef ;
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ char __dont_remove_copyright_from_binary[] = "Copyright (c) 2002, 2003 "
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
#include <Server.h>
|
|
||||||
#include <Autolock.h>
|
#include <Autolock.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
#include <MediaDefs.h>
|
#include <MediaDefs.h>
|
||||||
#include <MediaFormats.h>
|
#include <MediaFormats.h>
|
||||||
#include <Messenger.h>
|
#include <Messenger.h>
|
||||||
|
#include <Server.h>
|
||||||
|
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
|
||||||
@@ -307,7 +307,7 @@ ServerApp::_HandleMessage(int32 code, const void* data, size_t size)
|
|||||||
server_register_app_reply reply;
|
server_register_app_reply reply;
|
||||||
|
|
||||||
status_t status = gAppManager->RegisterTeam(request.team,
|
status_t status = gAppManager->RegisterTeam(request.team,
|
||||||
request.messenger, &reply.global_synchro);
|
request.messenger);
|
||||||
request.SendReply(status, &reply, sizeof(reply));
|
request.SendReply(status, &reply, sizeof(reply));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -942,7 +942,7 @@ ServerApp::MessageReceived(BMessage* msg)
|
|||||||
|
|
||||||
case MEDIA_SERVER_RESCAN_COMPLETED:
|
case MEDIA_SERVER_RESCAN_COMPLETED:
|
||||||
{
|
{
|
||||||
gAppManager->UnlockGlobalSynchro();
|
gAppManager->NotifyRosters();
|
||||||
progress_startup(100, NULL, NULL);
|
progress_startup(100, NULL, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user