xref: /haiku/src/apps/cortex/NodeManager/NodeSyncThread.cpp (revision 9642f7705b27e5c270c15fa526d14e1848c2c27d)
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