Line data Source code
1 :
2 : /* Copyright (c) 2005-2014, Stefan Eilemann <eile@equalizergraphics.com>
3 : * 2011-2012, 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/compressor.h>
40 : #include <lunchbox/scopedMutex.h>
41 : #include <lunchbox/plugins/compressor.h>
42 : #include <iostream>
43 :
44 : namespace co
45 : {
46 : namespace detail
47 : {
48 61 : class Object
49 : {
50 : public:
51 61 : Object()
52 : : id( lunchbox::make_UUID( ))
53 : , instanceID( CO_INSTANCE_INVALID )
54 61 : , cm( ObjectCM::ZERO )
55 61 : {}
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 61 : Object::Object()
72 61 : : impl_( new detail::Object )
73 61 : {}
74 :
75 0 : Object::Object( const Object& object )
76 : : Dispatcher( object )
77 0 : , impl_( new detail::Object )
78 0 : {}
79 :
80 122 : Object::~Object()
81 : {
82 61 : LBASSERTINFO( !isAttached(),
83 : "Object " << impl_->id << " is still attached to node " <<
84 : impl_->localNode->getNodeID());
85 :
86 61 : if( impl_->localNode )
87 0 : impl_->localNode->releaseObject( this );
88 :
89 61 : impl_->localNode = 0;
90 61 : impl_->cm = 0;
91 61 : delete impl_;
92 61 : }
93 :
94 974 : bool Object::isAttached() const
95 : {
96 974 : return impl_->instanceID != CO_INSTANCE_INVALID;
97 : }
98 :
99 1113 : LocalNodePtr Object::getLocalNode()
100 : {
101 1113 : 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 405 : const uint128_t& Object::getID() const
112 : {
113 405 : return impl_->id;
114 : }
115 :
116 385 : uint32_t Object::getInstanceID() const
117 : {
118 385 : return impl_->instanceID;
119 : }
120 :
121 61 : void Object::attach( const uint128_t& id, const uint32_t instanceID )
122 : {
123 61 : LBASSERT( !isAttached() );
124 61 : LBASSERT( impl_->localNode );
125 61 : LBASSERT( instanceID <= CO_INSTANCE_MAX );
126 :
127 61 : impl_->id = id;
128 61 : impl_->instanceID = instanceID;
129 61 : LBLOG( LOG_OBJECTS )
130 61 : << impl_->id << '.' << impl_->instanceID << ": " << lunchbox::className( this )
131 183 : << (isMaster() ? " master" : " slave") << std::endl;
132 61 : }
133 :
134 61 : void Object::detach()
135 : {
136 61 : impl_->instanceID = CO_INSTANCE_INVALID;
137 61 : impl_->localNode = 0;
138 61 : }
139 :
140 60 : void Object::notifyDetach()
141 : {
142 60 : if( !isMaster( ))
143 98 : return;
144 :
145 : // unmap slaves
146 20 : const Nodes slaves = impl_->cm->getSlaveNodes();
147 20 : if( slaves.empty( ))
148 18 : return;
149 :
150 6 : LBWARN << slaves.size() << " slaves subscribed during deregisterObject of "
151 8 : << lunchbox::className( this ) << " id " << impl_->id << std::endl;
152 :
153 4 : for( NodesCIter i = slaves.begin(); i != slaves.end(); ++i )
154 : {
155 2 : NodePtr node = *i;
156 2 : node->send( CMD_NODE_UNMAP_OBJECT ) << impl_->id;
157 4 : }
158 : }
159 :
160 0 : void Object::transfer( Object* from )
161 : {
162 0 : impl_->id = from->impl_->id;
163 0 : impl_->instanceID = from->getInstanceID();
164 0 : impl_->cm = from->impl_->cm;
165 0 : impl_->localNode = from->impl_->localNode;
166 0 : impl_->cm->setObject( this );
167 :
168 0 : from->impl_->cm = ObjectCM::ZERO;
169 0 : from->impl_->localNode = 0;
170 0 : from->impl_->instanceID = CO_INSTANCE_INVALID;
171 0 : }
172 :
173 89 : void Object::_setChangeManager( ObjectCMPtr cm )
174 : {
175 89 : if( impl_->cm != ObjectCM::ZERO )
176 : {
177 28 : LBVERB
178 0 : << "Overriding existing object change manager, obj "
179 28 : << lunchbox::className( this ) << ", old cm "
180 28 : << lunchbox::className( impl_->cm ) << ", new cm "
181 84 : << lunchbox::className( cm ) << std::endl;
182 : }
183 :
184 89 : impl_->cm->exit();
185 89 : impl_->cm = cm;
186 89 : cm->init();
187 178 : LBLOG( LOG_OBJECTS ) << "set " << lunchbox::className( cm ) << " for "
188 267 : << lunchbox::className( this ) << std::endl;
189 89 : }
190 :
191 45 : ObjectCMPtr Object::_getChangeManager()
192 : {
193 45 : return impl_->cm;
194 : }
195 :
196 390 : ObjectOCommand Object::send( NodePtr node, const uint32_t cmd,
197 : const uint32_t instanceID )
198 : {
199 390 : Connections connections( 1, node->getConnection( ));
200 : return ObjectOCommand( connections, cmd, COMMANDTYPE_OBJECT, impl_->id,
201 390 : instanceID );
202 : }
203 :
204 4 : void Object::push( const uint128_t& groupID, const uint128_t& typeID,
205 : const Nodes& nodes )
206 : {
207 4 : impl_->cm->push( groupID, typeID, nodes );
208 4 : }
209 :
210 114 : uint128_t Object::commit( const uint32_t incarnation )
211 : {
212 114 : return impl_->cm->commit( incarnation );
213 : }
214 :
215 :
216 89 : void Object::setupChangeManager( const Object::ChangeType type,
217 : const bool master, LocalNodePtr localNode,
218 : const uint32_t masterInstanceID )
219 : {
220 89 : impl_->localNode = localNode;
221 :
222 89 : switch( type )
223 : {
224 : case Object::NONE:
225 28 : LBASSERT( !localNode );
226 28 : _setChangeManager( ObjectCM::ZERO );
227 28 : break;
228 :
229 : case Object::STATIC:
230 16 : LBASSERT( impl_->localNode );
231 16 : if( master )
232 8 : _setChangeManager( new StaticMasterCM( this ));
233 : else
234 8 : _setChangeManager( new StaticSlaveCM( this ));
235 16 : break;
236 :
237 : case Object::INSTANCE:
238 6 : LBASSERT( impl_->localNode );
239 6 : if( master )
240 3 : _setChangeManager( new FullMasterCM( this ));
241 : else
242 : _setChangeManager( new VersionedSlaveCM( this,
243 3 : masterInstanceID ));
244 6 : break;
245 :
246 : case Object::DELTA:
247 35 : LBASSERT( impl_->localNode );
248 35 : if( master )
249 7 : _setChangeManager( new DeltaMasterCM( this ));
250 : else
251 : _setChangeManager( new VersionedSlaveCM( this,
252 28 : masterInstanceID ));
253 35 : break;
254 :
255 : case Object::UNBUFFERED:
256 4 : LBASSERT( impl_->localNode );
257 4 : if( master )
258 2 : _setChangeManager( new UnbufferedMasterCM( this ));
259 : else
260 : _setChangeManager( new VersionedSlaveCM( this,
261 2 : masterInstanceID ));
262 4 : break;
263 :
264 0 : default: LBUNIMPLEMENTED;
265 : }
266 89 : }
267 :
268 : //---------------------------------------------------------------------------
269 : // ChangeManager forwarders
270 : //---------------------------------------------------------------------------
271 41 : void Object::applyMapData( const uint128_t& version )
272 : {
273 41 : impl_->cm->applyMapData( version );
274 41 : }
275 :
276 0 : void Object::sendInstanceData( Nodes& nodes )
277 : {
278 0 : impl_->cm->sendInstanceData( nodes );
279 0 : }
280 :
281 0 : bool Object::isBuffered() const
282 : {
283 0 : return impl_->cm->isBuffered();
284 : }
285 :
286 424 : bool Object::isMaster() const
287 : {
288 424 : return impl_->cm->isMaster();
289 : }
290 :
291 32 : void Object::removeSlave( NodePtr node, const uint32_t instanceID )
292 : {
293 32 : impl_->cm->removeSlave( node, instanceID );
294 32 : }
295 :
296 25 : void Object::removeSlaves( NodePtr node )
297 : {
298 25 : impl_->cm->removeSlaves( node );
299 25 : }
300 :
301 41 : void Object::setMasterNode( NodePtr node )
302 : {
303 41 : impl_->cm->setMasterNode( node );
304 41 : }
305 :
306 0 : void Object::addInstanceDatas( const ObjectDataIStreamDeque& cache,
307 : const uint128_t& version )
308 : {
309 0 : impl_->cm->addInstanceDatas( cache, version );
310 0 : }
311 :
312 1 : void Object::setAutoObsolete( const uint32_t count )
313 : {
314 1 : impl_->cm->setAutoObsolete( count );
315 1 : }
316 :
317 0 : uint32_t Object::getAutoObsolete() const
318 : {
319 0 : return impl_->cm->getAutoObsolete();
320 : }
321 :
322 308 : uint128_t Object::sync( const uint128_t& version )
323 : {
324 308 : if( version == VERSION_NONE )
325 0 : return getVersion();
326 308 : return impl_->cm->sync( version );
327 : }
328 :
329 0 : uint128_t Object::getHeadVersion() const
330 : {
331 0 : return impl_->cm->getHeadVersion();
332 : }
333 :
334 1559 : uint128_t Object::getVersion() const
335 : {
336 1559 : return impl_->cm->getVersion();
337 : }
338 :
339 145 : void Object::notifyNewHeadVersion( const uint128_t& version LB_UNUSED )
340 : {
341 145 : LBASSERTINFO( getVersion() == VERSION_NONE ||
342 : version < getVersion() + 100,
343 : lunchbox::className( this ));
344 145 : }
345 :
346 178 : uint32_t Object::chooseCompressor() const
347 : {
348 178 : return lunchbox::Compressor::choose( Global::getPluginRegistry(),
349 : EQ_COMPRESSOR_DATATYPE_BYTE, 1.f,
350 178 : false );
351 : }
352 :
353 40 : uint32_t Object::getMasterInstanceID() const
354 : {
355 40 : return impl_->cm->getMasterInstanceID();
356 : }
357 :
358 34 : NodePtr Object::getMasterNode()
359 : {
360 34 : return impl_->cm->getMasterNode();
361 : }
362 :
363 0 : std::ostream& operator << ( std::ostream& os, const Object& object )
364 : {
365 0 : os << lunchbox::className( &object ) << " " << object.getID() << "."
366 0 : << object.getInstanceID() << " v" << object.getVersion();
367 0 : return os;
368 : }
369 :
370 0 : std::ostream& operator << ( std::ostream& os,const Object::ChangeType& type )
371 : {
372 0 : return os << ( type == Object::NONE ? "none" :
373 0 : type == Object::STATIC ? "static" :
374 0 : type == Object::INSTANCE ? "instance" :
375 0 : type == Object::DELTA ? "delta" :
376 0 : type == Object::UNBUFFERED ? "unbuffered" : "ERROR" );
377 : }
378 :
379 60 : }
|