1 /* 2 * Copyright (c) 1999-2000, Eric Moon. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions, and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions, and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 // NodeSyncThread.cpp 33 34 #include "NodeSyncThread.h" 35 36 #include <cstring> 37 38 #include <Debug.h> 39 #include <MediaRoster.h> 40 41 __USE_CORTEX_NAMESPACE 42 43 // -------------------------------------------------------- // 44 // *** dtor/ctors 45 // -------------------------------------------------------- // 46 47 NodeSyncThread::~NodeSyncThread() { 48 status_t err; 49 50 // clean up 51 if(m_thread) { 52 err = kill_thread(m_thread); 53 if(err < B_OK) 54 PRINT(( 55 "! ~NodeSyncThread(): kill_thread(%" B_PRId32 "):\n" 56 " %s\n", 57 m_thread, 58 strerror(err))); 59 60 // +++++ is a wait_for_thread() necessary? 61 } 62 63 if(m_port) { 64 err = delete_port(m_port); 65 if(err < B_OK) 66 PRINT(( 67 "! ~NodeSyncThread(): delete_port(%" B_PRId32 "):\n" 68 " %s\n", 69 m_port, 70 strerror(err))); 71 } 72 73 if(m_portBuffer) 74 delete [] m_portBuffer; 75 if(m_messenger) 76 delete m_messenger; 77 } 78 79 NodeSyncThread::NodeSyncThread( 80 const media_node& node, 81 BMessenger* messenger) : 82 83 m_node(node), 84 m_messenger(messenger), 85 m_syncInProgress(false), 86 m_thread(0), 87 m_port(0), 88 m_portBuffer(0), 89 m_portBufferSize(sizeof(_sync_op)) { 90 91 ASSERT(m_messenger); 92 93 m_portBuffer = new char[m_portBufferSize]; 94 95 m_port = create_port( 96 m_portBufferSize * 16, 97 "NodeSyncThread___port"); 98 ASSERT(m_port >= B_OK); 99 100 m_thread = spawn_thread( 101 &_Sync, 102 "NodeSyncThread", 103 B_DISPLAY_PRIORITY, 104 this); 105 ASSERT(m_thread >= B_OK); 106 resume_thread(m_thread); 107 } 108 109 // -------------------------------------------------------- // 110 // *** operations 111 // -------------------------------------------------------- // 112 113 // trigger a sync operation: when 'perfTime' arrives 114 // for the node, a M_SYNC_COMPLETE message with the given 115 // position value will be sent, unless the sync operation 116 // times out, in which case M_TIMED_OUT will be sent. 117 118 status_t NodeSyncThread::sync( 119 bigtime_t perfTime, 120 bigtime_t position, 121 bigtime_t timeout) { 122 123 status_t err; 124 125 if(m_syncInProgress) 126 return B_NOT_ALLOWED; 127 128 _sync_op op = {perfTime, position, timeout}; 129 err = write_port( 130 m_port, 131 M_TRIGGER, 132 &op, 133 sizeof(_sync_op)); 134 135 return err; 136 } 137 138 // -------------------------------------------------------- // 139 // *** guts 140 // -------------------------------------------------------- // 141 142 /*static*/ 143 status_t NodeSyncThread::_Sync( 144 void* cookie) { 145 ((NodeSyncThread*)cookie)->_sync(); 146 return B_OK; 147 } 148 149 // THREAD BODY 150 // 151 void NodeSyncThread::_sync() { 152 ASSERT(m_port >= B_OK); 153 ASSERT(m_messenger); 154 155 bool done = false; 156 while(!done) { 157 158 // WAIT FOR A REQUEST 159 int32 code; 160 ssize_t readCount = read_port( 161 m_port, 162 &code, 163 m_portBuffer, 164 m_portBufferSize); 165 166 if(readCount < B_OK) { 167 PRINT(( 168 "! NodeSyncThread::_sync(): read_port():\n" 169 " %s\n", 170 strerror(readCount))); 171 continue; 172 } 173 174 if(code != M_TRIGGER) { 175 PRINT(( 176 "! NodeSyncThread::sync(): unknown message code %" B_PRId32 177 "\n", code)); 178 continue; 179 } 180 181 // SERVICE THE REQUEST 182 const _sync_op& op = *(_sync_op*)m_portBuffer; 183 184 // pre-fill the message 185 BMessage m(M_SYNC_COMPLETE); 186 m.AddInt32("nodeID", m_node.node); 187 m.AddInt64("perfTime", op.targetTime); 188 m.AddInt64("position", op.position); 189 190 // sync 191 status_t err = BMediaRoster::Roster()->SyncToNode( 192 m_node, 193 op.targetTime, 194 op.timeout); 195 196 // deliver reply 197 if(err < B_OK) { 198 m.what = M_SYNC_FAILED; 199 m.AddInt32("error", err); 200 } 201 202 err = m_messenger->SendMessage(&m); 203 if(err < B_OK) { 204 PRINT(( 205 "! NodeSyncThread::_sync(): m_messenger->SendMessage():\n" 206 " %s\n", 207 strerror(err))); 208 } 209 } 210 } 211 212 213 // END -- NodeSyncThread.cpp -- 214