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 %ld\n", team); 81 if (HasTeam(team)) { 82 ERROR("AppManager::RegisterTeam: team %ld already registered\n", team); 83 return B_ERROR; 84 } 85 86 try { 87 fMap.insert(std::make_pair(team, messenger)); 88 } catch (std::bad_alloc& exception) { 89 return B_NO_MEMORY; 90 } 91 92 return B_OK; 93 } 94 95 96 status_t 97 AppManager::UnregisterTeam(team_id team) 98 { 99 TRACE("AppManager::UnregisterTeam %ld\n", team); 100 101 Lock(); 102 bool isRemoved = fMap.erase(team) != 0; 103 Unlock(); 104 105 _CleanupTeam(team); 106 107 return isRemoved ? B_OK : B_ERROR; 108 } 109 110 111 team_id 112 AppManager::AddOnServerTeam() 113 { 114 team_id id = be_roster->TeamFor(B_MEDIA_ADDON_SERVER_SIGNATURE); 115 if (id < 0) { 116 ERROR("media_server: Trouble, media_addon_server is dead!\n"); 117 return -1; 118 } 119 return id; 120 } 121 122 123 status_t 124 AppManager::SendMessage(team_id team, BMessage* message) 125 { 126 BAutolock lock(this); 127 128 AppMap::iterator found = fMap.find(team); 129 if (found == fMap.end()) 130 return B_NAME_NOT_FOUND; 131 132 return found->second.SendMessage(message); 133 } 134 135 136 void 137 AppManager::Dump() 138 { 139 BAutolock lock(this); 140 141 printf("\n"); 142 printf("AppManager: list of applications follows:\n"); 143 144 app_info info; 145 AppMap::iterator iterator = fMap.begin(); 146 for (; iterator != fMap.end(); iterator++) { 147 app_info info; 148 be_roster->GetRunningAppInfo(iterator->first, &info); 149 printf(" team %ld \"%s\", messenger %svalid\n", iterator->first, 150 info.ref.name, iterator->second.IsValid() ? "" : "NOT "); 151 } 152 153 printf("AppManager: list end\n"); 154 } 155 156 157 void 158 AppManager::_CleanupTeam(team_id team) 159 { 160 ASSERT(!IsLocked()); 161 162 TRACE("AppManager: cleaning up team %ld\n", team); 163 164 gNodeManager->CleanupTeam(team); 165 gBufferManager->CleanupTeam(team); 166 gNotificationManager->CleanupTeam(team); 167 } 168 169 170 void 171 AppManager::_TeamDied(team_id team) 172 { 173 UnregisterTeam(team); 174 } 175 176 177 status_t 178 AppManager::_BigBrotherEntry(void* self) 179 { 180 static_cast<AppManager*>(self)->_BigBrother(); 181 return 0; 182 } 183 184 185 /*! The BigBrother thread send ping messages to the BMediaRoster of 186 all currently running teams. If the reply times out or is wrong, 187 the team cleanup function _TeamDied() will be called. 188 */ 189 void 190 AppManager::_BigBrother() 191 { 192 status_t status = B_TIMED_OUT; 193 BMessage ping('PING'); 194 BMessage reply; 195 196 do { 197 if (!Lock()) 198 break; 199 200 bool startOver = false; 201 AppMap::iterator iterator = fMap.begin(); 202 for (; iterator != fMap.end(); iterator++) { 203 reply.what = 0; 204 status = iterator->second.SendMessage(&ping, &reply, 5000000, 205 2000000); 206 if (status != B_OK || reply.what != 'PONG') { 207 team_id team = iterator->first; 208 Unlock(); 209 210 _TeamDied(team); 211 startOver = true; 212 break; 213 } 214 } 215 216 if (startOver) 217 continue; 218 219 Unlock(); 220 status = acquire_sem_etc(fQuit, 1, B_RELATIVE_TIMEOUT, 2000000); 221 } while (status == B_TIMED_OUT || status == B_INTERRUPTED); 222 } 223