Line data Source code
1 :
2 : /* Copyright (c) 2005-2016, Stefan Eilemann <eile@equalizergraphics.com>
3 : * Daniel Nachbaur <danielnachbaur@gmail.com>
4 : *
5 : * This file is part of Collage <https://github.com/Eyescale/Collage>
6 : *
7 : * This library is free software; you can redistribute it and/or modify it under
8 : * the terms of the GNU Lesser General Public License version 2.1 as published
9 : * by the Free Software Foundation.
10 : *
11 : * This library is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 : * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14 : * details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public License
17 : * along with this library; if not, write to the Free Software Foundation, Inc.,
18 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 : */
20 :
21 : #include "object.h"
22 :
23 : #include "dataIStream.h"
24 : #include "dataOStream.h"
25 : #include "deltaMasterCM.h"
26 : #include "fullMasterCM.h"
27 : #include "global.h"
28 : #include "log.h"
29 : #include "nodeCommand.h"
30 : #include "nullCM.h"
31 : #include "objectCM.h"
32 : #include "objectOCommand.h"
33 : #include "staticMasterCM.h"
34 : #include "staticSlaveCM.h"
35 : #include "types.h"
36 : #include "unbufferedMasterCM.h"
37 : #include "versionedSlaveCM.h"
38 :
39 : #include <lunchbox/scopedMutex.h>
40 : #include <pression/compressor.h>
41 : #include <pression/plugins/compressor.h>
42 : #include <iostream>
43 :
44 : namespace co
45 : {
46 : namespace detail
47 : {
48 63 : class Object
49 : {
50 : public:
51 63 : Object()
52 : : id( lunchbox::make_UUID( ))
53 : , instanceID( CO_INSTANCE_INVALID )
54 63 : , cm( ObjectCM::ZERO )
55 63 : {}
56 :
57 : /** The session-unique object identifier. */
58 : uint128_t id;
59 :
60 : /** The node where this object is attached. */
61 : LocalNodePtr localNode;
62 :
63 : /** A session-unique identifier of the concrete instance. */
64 : uint32_t instanceID;
65 :
66 : /** The object's change manager. */
67 : ObjectCMPtr cm;
68 : };
69 : }
70 :
71 63 : Object::Object()
72 63 : : impl_( new detail::Object )
73 63 : {}
74 :
75 0 : Object::Object( const Object& object )
76 : : Dispatcher( object )
77 0 : , impl_( new detail::Object )
78 0 : {}
79 :
80 126 : Object::~Object()
81 : {
82 63 : LBASSERTINFO( !isAttached(),
83 : "Object " << impl_->id << " is still attached to node " <<
84 : impl_->localNode->getNodeID());
85 :
86 63 : if( impl_->localNode )
87 0 : impl_->localNode->releaseObject( this );
88 :
89 63 : impl_->localNode = 0;
90 63 : impl_->cm = 0;
91 63 : delete impl_;
92 63 : }
93 :
94 980 : bool Object::isAttached() const
95 : {
96 980 : return impl_->instanceID != CO_INSTANCE_INVALID;
97 : }
98 :
99 1116 : LocalNodePtr Object::getLocalNode()
100 : {
101 1116 : return impl_->localNode;
102 : }
103 :
104 0 : void Object::setID( const uint128_t& identifier )
105 : {
106 0 : LBASSERT( !isAttached( ));
107 0 : LBASSERT( identifier.isUUID( ));
108 0 : impl_->id = identifier;
109 0 : }
110 :
111 414 : const uint128_t& Object::getID() const
112 : {
113 414 : return impl_->id;
114 : }
115 :
116 399 : uint32_t Object::getInstanceID() const
117 : {
118 399 : return impl_->instanceID;
119 : }
120 :
121 63 : void Object::attach( const uint128_t& id, const uint32_t instanceID )
122 : {
123 63 : LBASSERTINFO( !isAttached(), *this );
124 63 : LBASSERT( impl_->localNode );
125 63 : LBASSERT( instanceID <= CO_INSTANCE_MAX );
126 :
127 63 : impl_->id = id;
128 63 : impl_->instanceID = instanceID;
129 63 : LBLOG( LOG_OBJECTS )
130 63 : << impl_->id << '.' << impl_->instanceID << ": " << lunchbox::className( this )
131 189 : << (isMaster() ? " master" : " slave") << std::endl;
132 63 : }
133 :
134 63 : void Object::detach()
135 : {
136 63 : impl_->instanceID = CO_INSTANCE_INVALID;
137 63 : impl_->localNode = 0;
138 63 : }
139 :
140 62 : void Object::notifyDetach()
141 : {
142 62 : if( !isMaster( ))
143 102 : return;
144 :
145 : // unmap slaves
146 21 : const Nodes slaves = impl_->cm->getSlaveNodes();
147 21 : if( slaves.empty( ))
148 20 : return;
149 :
150 3 : LBLOG( LOG_BUG ) << slaves.size() << " slaves subscribed during "
151 4 : << " deregister/unmap of " << lunchbox::className( this )
152 4 : << " id " << impl_->id << std::endl;
153 :
154 2 : for( NodesCIter i = slaves.begin(); i != slaves.end(); ++i )
155 : {
156 1 : NodePtr node = *i;
157 1 : node->send( CMD_NODE_UNMAP_OBJECT ) << impl_->id;
158 2 : }
159 : }
160 :
161 0 : void Object::transfer( Object* from )
162 : {
163 0 : impl_->id = from->impl_->id;
164 0 : impl_->instanceID = from->getInstanceID();
165 0 : impl_->cm = from->impl_->cm;
166 0 : impl_->localNode = from->impl_->localNode;
167 0 : impl_->cm->setObject( this );
168 :
169 0 : from->impl_->cm = ObjectCM::ZERO;
170 0 : from->impl_->localNode = 0;
171 0 : from->impl_->instanceID = CO_INSTANCE_INVALID;
172 0 : }
173 :
174 92 : void Object::_setChangeManager( ObjectCMPtr cm )
175 : {
176 92 : if( impl_->cm != ObjectCM::ZERO )
177 : {
178 29 : LBVERB
179 0 : << "Overriding existing object change manager, obj "
180 29 : << lunchbox::className( this ) << ", old cm "
181 29 : << lunchbox::className( impl_->cm ) << ", new cm "
182 87 : << lunchbox::className( cm ) << std::endl;
183 : }
184 :
185 92 : impl_->cm->exit();
186 92 : impl_->cm = cm;
187 92 : cm->init();
188 184 : LBLOG( LOG_OBJECTS ) << "set " << lunchbox::className( cm ) << " for "
189 276 : << lunchbox::className( this ) << std::endl;
190 92 : }
191 :
192 46 : ObjectCMPtr Object::_getChangeManager()
193 : {
194 46 : return impl_->cm;
195 : }
196 :
197 390 : ObjectOCommand Object::send( NodePtr node, const uint32_t cmd,
198 : const uint32_t instanceID )
199 : {
200 390 : Connections connections( 1, node->getConnection( ));
201 : return ObjectOCommand( connections, cmd, COMMANDTYPE_OBJECT, impl_->id,
202 389 : instanceID );
203 : }
204 :
205 5 : void Object::push( const uint128_t& groupID, const uint128_t& typeID,
206 : const Nodes& nodes )
207 : {
208 5 : impl_->cm->push( groupID, typeID, nodes );
209 5 : }
210 :
211 112 : uint128_t Object::commit( const uint32_t incarnation )
212 : {
213 112 : return impl_->cm->commit( incarnation );
214 : }
215 :
216 :
217 92 : void Object::setupChangeManager( const Object::ChangeType type,
218 : const bool master, LocalNodePtr localNode,
219 : const uint32_t masterInstanceID )
220 : {
221 92 : impl_->localNode = localNode;
222 :
223 92 : switch( type )
224 : {
225 : case Object::NONE:
226 29 : LBASSERT( !localNode );
227 29 : _setChangeManager( ObjectCM::ZERO );
228 29 : break;
229 :
230 : case Object::STATIC:
231 16 : LBASSERT( impl_->localNode );
232 16 : if( master )
233 8 : _setChangeManager( new StaticMasterCM( this ));
234 : else
235 8 : _setChangeManager( new StaticSlaveCM( this ));
236 16 : break;
237 :
238 : case Object::INSTANCE:
239 8 : LBASSERT( impl_->localNode );
240 8 : if( master )
241 4 : _setChangeManager( new FullMasterCM( this ));
242 : else
243 : _setChangeManager( new VersionedSlaveCM( this,
244 4 : masterInstanceID ));
245 8 : break;
246 :
247 : case Object::DELTA:
248 35 : LBASSERT( impl_->localNode );
249 35 : if( master )
250 7 : _setChangeManager( new DeltaMasterCM( this ));
251 : else
252 : _setChangeManager( new VersionedSlaveCM( this,
253 28 : masterInstanceID ));
254 35 : break;
255 :
256 : case Object::UNBUFFERED:
257 4 : LBASSERT( impl_->localNode );
258 4 : if( master )
259 2 : _setChangeManager( new UnbufferedMasterCM( this ));
260 : else
261 : _setChangeManager( new VersionedSlaveCM( this,
262 2 : masterInstanceID ));
263 4 : break;
264 :
265 0 : default: LBUNIMPLEMENTED;
266 : }
267 92 : }
268 :
269 : //---------------------------------------------------------------------------
270 : // ChangeManager forwarders
271 : //---------------------------------------------------------------------------
272 42 : void Object::applyMapData( const uint128_t& version )
273 : {
274 42 : impl_->cm->applyMapData( version );
275 42 : }
276 :
277 0 : void Object::sendInstanceData( const Nodes& nodes )
278 : {
279 0 : impl_->cm->sendInstanceData( nodes );
280 0 : }
281 :
282 0 : bool Object::isBuffered() const
283 : {
284 0 : return impl_->cm->isBuffered();
285 : }
286 :
287 438 : bool Object::isMaster() const
288 : {
289 438 : return impl_->cm->isMaster();
290 : }
291 :
292 33 : void Object::removeSlave( NodePtr node, const uint32_t instanceID )
293 : {
294 33 : impl_->cm->removeSlave( node, instanceID );
295 33 : }
296 :
297 25 : void Object::removeSlaves( NodePtr node )
298 : {
299 25 : impl_->cm->removeSlaves( node );
300 25 : }
301 :
302 42 : void Object::setMasterNode( NodePtr node )
303 : {
304 42 : impl_->cm->setMasterNode( node );
305 42 : }
306 :
307 0 : void Object::addInstanceDatas( const ObjectDataIStreamDeque& cache,
308 : const uint128_t& version )
309 : {
310 0 : impl_->cm->addInstanceDatas( cache, version );
311 0 : }
312 :
313 1 : void Object::setAutoObsolete( const uint32_t count )
314 : {
315 1 : impl_->cm->setAutoObsolete( count );
316 1 : }
317 :
318 0 : uint32_t Object::getAutoObsolete() const
319 : {
320 0 : return impl_->cm->getAutoObsolete();
321 : }
322 :
323 309 : uint128_t Object::sync( const uint128_t& version )
324 : {
325 309 : if( version == VERSION_NONE )
326 0 : return getVersion();
327 309 : return impl_->cm->sync( version );
328 : }
329 :
330 0 : uint128_t Object::getHeadVersion() const
331 : {
332 0 : return impl_->cm->getHeadVersion();
333 : }
334 :
335 1559 : uint128_t Object::getVersion() const
336 : {
337 1559 : return impl_->cm->getVersion();
338 : }
339 :
340 144 : void Object::notifyNewHeadVersion( const uint128_t& version LB_UNUSED )
341 : {
342 144 : LBASSERTINFO( getVersion() == VERSION_NONE ||
343 : version < getVersion() + 100,
344 : lunchbox::className( this ));
345 144 : }
346 :
347 178 : uint32_t Object::chooseCompressor() const
348 : {
349 178 : return pression::Compressor::choose( Global::getPluginRegistry(),
350 : EQ_COMPRESSOR_DATATYPE_BYTE, 1.f,
351 178 : false );
352 : }
353 :
354 41 : uint32_t Object::getMasterInstanceID() const
355 : {
356 41 : return impl_->cm->getMasterInstanceID();
357 : }
358 :
359 35 : NodePtr Object::getMasterNode()
360 : {
361 35 : return impl_->cm->getMasterNode();
362 : }
363 :
364 0 : std::ostream& operator << ( std::ostream& os, const Object& object )
365 : {
366 0 : os << lunchbox::className( &object ) << " " << object.getID() << "."
367 0 : << object.getInstanceID() << " v" << object.getVersion();
368 0 : return os;
369 : }
370 :
371 0 : std::ostream& operator << ( std::ostream& os,const Object::ChangeType& type )
372 : {
373 0 : return os << ( type == Object::NONE ? "none" :
374 0 : type == Object::STATIC ? "static" :
375 0 : type == Object::INSTANCE ? "instance" :
376 0 : type == Object::DELTA ? "delta" :
377 0 : type == Object::UNBUFFERED ? "unbuffered" : "ERROR" );
378 : }
379 :
380 66 : }
|