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/data/Registry.h>
41 : #include <iostream>
42 :
43 : namespace co
44 : {
45 : namespace detail
46 : {
47 63 : class Object
48 : {
49 : public:
50 63 : Object()
51 63 : : id( lunchbox::make_UUID( ))
52 : , instanceID( CO_INSTANCE_INVALID )
53 63 : , cm( ObjectCM::ZERO )
54 63 : {}
55 :
56 : /** The session-unique object identifier. */
57 : uint128_t id;
58 :
59 : /** The node where this object is attached. */
60 : LocalNodePtr localNode;
61 :
62 : /** A session-unique identifier of the concrete instance. */
63 : uint32_t instanceID;
64 :
65 : /** The object's change manager. */
66 : ObjectCMPtr cm;
67 : };
68 : }
69 :
70 63 : Object::Object()
71 63 : : impl_( new detail::Object )
72 63 : {}
73 :
74 0 : Object::Object( const Object& object )
75 : : Dispatcher( object )
76 0 : , impl_( new detail::Object )
77 0 : {}
78 :
79 126 : Object::~Object()
80 : {
81 63 : LBASSERTINFO( !isAttached(),
82 : "Object " << impl_->id << " is still attached to node " <<
83 : impl_->localNode->getNodeID());
84 :
85 63 : if( impl_->localNode )
86 0 : impl_->localNode->releaseObject( this );
87 :
88 63 : impl_->localNode = 0;
89 63 : impl_->cm = 0;
90 63 : delete impl_;
91 63 : }
92 :
93 980 : bool Object::isAttached() const
94 : {
95 980 : return impl_->instanceID != CO_INSTANCE_INVALID;
96 : }
97 :
98 1116 : LocalNodePtr Object::getLocalNode()
99 : {
100 1116 : return impl_->localNode;
101 : }
102 :
103 0 : void Object::setID( const uint128_t& identifier )
104 : {
105 0 : LBASSERT( !isAttached( ));
106 0 : LBASSERT( identifier.isUUID( ));
107 0 : impl_->id = identifier;
108 0 : }
109 :
110 414 : const uint128_t& Object::getID() const
111 : {
112 414 : return impl_->id;
113 : }
114 :
115 399 : uint32_t Object::getInstanceID() const
116 : {
117 399 : return impl_->instanceID;
118 : }
119 :
120 63 : void Object::attach( const uint128_t& id, const uint32_t instanceID )
121 : {
122 63 : LBASSERTINFO( !isAttached(), *this );
123 63 : LBASSERT( impl_->localNode );
124 63 : LBASSERT( instanceID <= CO_INSTANCE_MAX );
125 :
126 63 : impl_->id = id;
127 63 : impl_->instanceID = instanceID;
128 63 : LBLOG( LOG_OBJECTS )
129 63 : << impl_->id << '.' << impl_->instanceID << ": " << lunchbox::className( this )
130 189 : << (isMaster() ? " master" : " slave") << std::endl;
131 63 : }
132 :
133 63 : void Object::detach()
134 : {
135 63 : impl_->instanceID = CO_INSTANCE_INVALID;
136 63 : impl_->localNode = 0;
137 63 : }
138 :
139 62 : void Object::notifyDetach()
140 : {
141 62 : if( !isMaster( ))
142 102 : return;
143 :
144 : // unmap slaves
145 22 : const Nodes slaves = impl_->cm->getSlaveNodes();
146 21 : if( slaves.empty( ))
147 20 : return;
148 :
149 3 : LBLOG( LOG_BUG ) << slaves.size() << " slaves subscribed during "
150 3 : << " deregister/unmap of " << lunchbox::className( this )
151 4 : << " id " << impl_->id << std::endl;
152 :
153 2 : for( NodesCIter i = slaves.begin(); i != slaves.end(); ++i )
154 : {
155 2 : NodePtr node = *i;
156 1 : node->send( CMD_NODE_UNMAP_OBJECT ) << impl_->id;
157 : }
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 92 : void Object::_setChangeManager( ObjectCMPtr cm )
174 : {
175 92 : if( impl_->cm != ObjectCM::ZERO )
176 : {
177 29 : LBVERB
178 : << "Overriding existing object change manager, obj "
179 29 : << lunchbox::className( this ) << ", old cm "
180 29 : << lunchbox::className( impl_->cm ) << ", new cm "
181 87 : << lunchbox::className( cm ) << std::endl;
182 : }
183 :
184 92 : impl_->cm->exit();
185 92 : impl_->cm = cm;
186 92 : cm->init();
187 184 : LBLOG( LOG_OBJECTS ) << "set " << lunchbox::className( cm ) << " for "
188 276 : << lunchbox::className( this ) << std::endl;
189 92 : }
190 :
191 46 : ObjectCMPtr Object::_getChangeManager()
192 : {
193 46 : return impl_->cm;
194 : }
195 :
196 389 : ObjectOCommand Object::send( NodePtr node, const uint32_t cmd,
197 : const uint32_t instanceID )
198 : {
199 777 : Connections connections( 1, node->getConnection( ));
200 390 : return ObjectOCommand( connections, cmd, COMMANDTYPE_OBJECT, impl_->id,
201 778 : instanceID );
202 : }
203 :
204 5 : void Object::push( const uint128_t& groupID, const uint128_t& typeID,
205 : const Nodes& nodes )
206 : {
207 5 : impl_->cm->push( groupID, typeID, nodes );
208 5 : }
209 :
210 112 : uint128_t Object::commit( const uint32_t incarnation )
211 : {
212 112 : return impl_->cm->commit( incarnation );
213 : }
214 :
215 :
216 92 : void Object::setupChangeManager( const Object::ChangeType type,
217 : const bool master, LocalNodePtr localNode,
218 : const uint32_t masterInstanceID )
219 : {
220 92 : impl_->localNode = localNode;
221 :
222 92 : switch( type )
223 : {
224 : case Object::NONE:
225 29 : LBASSERT( !localNode );
226 29 : _setChangeManager( ObjectCM::ZERO );
227 29 : 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 8 : LBASSERT( impl_->localNode );
239 8 : if( master )
240 4 : _setChangeManager( new FullMasterCM( this ));
241 : else
242 8 : _setChangeManager( new VersionedSlaveCM( this,
243 8 : masterInstanceID ));
244 8 : break;
245 :
246 : case Object::DELTA:
247 35 : LBASSERT( impl_->localNode );
248 35 : if( master )
249 7 : _setChangeManager( new DeltaMasterCM( this ));
250 : else
251 56 : _setChangeManager( new VersionedSlaveCM( this,
252 56 : 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 4 : _setChangeManager( new VersionedSlaveCM( this,
261 4 : masterInstanceID ));
262 4 : break;
263 :
264 0 : default: LBUNIMPLEMENTED;
265 : }
266 92 : }
267 :
268 : //---------------------------------------------------------------------------
269 : // ChangeManager forwarders
270 : //---------------------------------------------------------------------------
271 42 : void Object::applyMapData( const uint128_t& version )
272 : {
273 42 : impl_->cm->applyMapData( version );
274 42 : }
275 :
276 0 : void Object::sendInstanceData( const 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 438 : bool Object::isMaster() const
287 : {
288 438 : return impl_->cm->isMaster();
289 : }
290 :
291 33 : void Object::removeSlave( NodePtr node, const uint32_t instanceID )
292 : {
293 33 : impl_->cm->removeSlave( node, instanceID );
294 33 : }
295 :
296 25 : void Object::removeSlaves( NodePtr node )
297 : {
298 25 : impl_->cm->removeSlaves( node );
299 25 : }
300 :
301 42 : void Object::setMasterNode( NodePtr node )
302 : {
303 42 : impl_->cm->setMasterNode( node );
304 42 : }
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 309 : uint128_t Object::sync( const uint128_t& version )
323 : {
324 309 : if( version == VERSION_NONE )
325 0 : return getVersion();
326 309 : 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 144 : void Object::notifyNewHeadVersion( const uint128_t& version LB_UNUSED )
340 : {
341 144 : LBASSERTINFO( getVersion() == VERSION_NONE ||
342 : version < getVersion() + 100,
343 : lunchbox::className( this ));
344 144 : }
345 :
346 178 : CompressorInfo Object::chooseCompressor() const
347 : {
348 178 : return pression::data::Registry::getInstance().choose();
349 : }
350 :
351 41 : uint32_t Object::getMasterInstanceID() const
352 : {
353 41 : return impl_->cm->getMasterInstanceID();
354 : }
355 :
356 35 : NodePtr Object::getMasterNode()
357 : {
358 35 : return impl_->cm->getMasterNode();
359 : }
360 :
361 0 : std::ostream& operator << ( std::ostream& os, const Object& object )
362 : {
363 0 : os << lunchbox::className( &object ) << " " << object.getID() << "."
364 0 : << object.getInstanceID() << " v" << object.getVersion();
365 0 : return os;
366 : }
367 :
368 0 : std::ostream& operator << ( std::ostream& os,const Object::ChangeType& type )
369 : {
370 0 : return os << ( type == Object::NONE ? "none" :
371 0 : type == Object::STATIC ? "static" :
372 0 : type == Object::INSTANCE ? "instance" :
373 0 : type == Object::DELTA ? "delta" :
374 0 : type == Object::UNBUFFERED ? "unbuffered" : "ERROR" );
375 : }
376 :
377 66 : }
|