1 /* 2 * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de> 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining 5 * a copy of this software and associated documentation files or portions 6 * thereof (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, subject 10 * to the following conditions: 11 * 12 * * Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * * Redistributions in binary form must reproduce the above copyright notice 16 * in the binary, as well as this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided with 18 * the distribution. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 * THE SOFTWARE. 27 * 28 */ 29 30 31 #include "AppManager.h" 32 33 #include <stdio.h> 34 35 #include <Application.h> 36 #include <Autolock.h> 37 #include <OS.h> 38 #include <Roster.h> 39 40 #include <debug.h> 41 #include <MediaMisc.h> 42 43 #include "BufferManager.h" 44 #include "media_server.h" 45 #include "NodeManager.h" 46 #include "NotificationManager.h" 47 48 49 AppManager::AppManager() 50 : 51 BLocker("media app manager") 52 { 53 fQuit = create_sem(0, "big brother waits"); 54 fBigBrother = spawn_thread(_BigBrotherEntry, "big brother is watching you", 55 B_NORMAL_PRIORITY, this); 56 resume_thread(fBigBrother); 57 } 58 59 60 AppManager::~AppManager() 61 { 62 delete_sem(fQuit); 63 wait_for_thread(fBigBrother, NULL); 64 } 65 66 67 bool 68 AppManager::HasTeam(team_id team) 69 { 70 BAutolock lock(this); 71 return fMap.find(team) != fMap.end(); 72 } 73 74 75 status_t 76 AppManager::RegisterTeam(team_id team, const BMessenger& messenger) 77 { 78 BAutolock lock(this); 79 80 TRACE("AppManager::RegisterTeam %" B_PRId32 "\n", team); 81 if (HasTeam(team)) { 82 ERROR("AppManager::RegisterTeam: team %" B_PRId32 " already" 83 " registered\n", team); 84 return B_ERROR; 85 } 86 87 try { 88 fMap.insert(std::make_pair(team, messenger)); 89 } catch (std::bad_alloc& exception) { 90 return B_NO_MEMORY; 91 } 92 93 return B_OK; 94 } 95 96 97 status_t 98 AppManager::UnregisterTeam(team_id team) 99 { 100 TRACE("AppManager::UnregisterTeam %" B_PRId32 "\n", team); 101 102 Lock(); 103 bool isRemoved = fMap.erase(team) != 0; 104 Unlock(); 105 106 _CleanupTeam(team); 107 108 return isRemoved ? B_OK : B_ERROR; 109 } 110 111 112 team_id 113 AppManager::AddOnServerTeam() 114 { 115 team_id id = be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE); 116 if (id < 0) { 117 ERROR("media_server: Trouble, media_addon_server is dead!\n"); 118 return -1; 119 } 120 return id; 121 } 122 123 124 status_t 125 AppManager::SendMessage(team_id team, BMessage* message) 126 { 127 BAutolock lock(this); 128 129 AppMap::iterator found = fMap.find(team); 130 if (found == fMap.end()) 131 return B_NAME_NOT_FOUND; 132 133 return found->second.SendMessage(message); 134 } 135 136 137 void 138 AppManager::Dump() 139 { 140 BAutolock lock(this); 141 142 printf("\n"); 143 printf("AppManager: list of applications follows:\n"); 144 145 app_info info; 146 AppMap::iterator iterator = fMap.begin(); 147 for (; iterator != fMap.end(); iterator++) { 148 app_info info; 149 be_roster->GetRunningAppInfo(iterator->first, &info); 150 printf(" team %" B_PRId32 " \"%s\", messenger %svalid\n", 151 iterator->first, info.ref.name, 152 iterator->second.IsValid() ? "" : "NOT "); 153 } 154 155 printf("AppManager: list end\n"); 156 } 157 158 159 void 160 AppManager::_CleanupTeam(team_id team) 161 { 162 ASSERT(!IsLocked()); 163 164 TRACE("AppManager: cleaning up team %" B_PRId32 "\n", team); 165 166 gNodeManager->CleanupTeam(team); 167 gBufferManager->CleanupTeam(team); 168 gNotificationManager->CleanupTeam(team); 169 } 170 171 172 void 173 AppManager::_TeamDied(team_id team) 174 { 175 UnregisterTeam(team); 176 } 177 178 179 status_t 180 AppManager::_BigBrotherEntry(void* self) 181 { 182 static_cast<AppManager*>(self)->_BigBrother(); 183 return 0; 184 } 185 186 187 /*! The BigBrother thread send ping messages to the BMediaRoster of 188 all currently running teams. If the reply times out or is wrong, 189 the team cleanup function _TeamDied() will be called. 190 */ 191 void 192 AppManager::_BigBrother() 193 { 194 status_t status = B_TIMED_OUT; 195 BMessage ping('PING'); 196 BMessage reply; 197 198 do { 199 if (!Lock()) 200 break; 201 202 bool startOver = false; 203 AppMap::iterator iterator = fMap.begin(); 204 for (; iterator != fMap.end(); iterator++) { 205 reply.what = 0; 206 status = iterator->second.SendMessage(&ping, &reply, 5000000, 207 2000000); 208 if (status != B_OK || reply.what != 'PONG') { 209 team_id team = iterator->first; 210 Unlock(); 211 212 _TeamDied(team); 213 startOver = true; 214 break; 215 } 216 } 217 218 if (startOver) 219 continue; 220 221 Unlock(); 222 status = acquire_sem_etc(fQuit, 1, B_RELATIVE_TIMEOUT, 2000000); 223 } while (status == B_TIMED_OUT || status == B_INTERRUPTED); 224 } 225