vtkSMSession.cxx 15.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*=========================================================================

  Program:   ParaView
  Module:    $RCSfile$

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkSMSession.h"

17
#include "vtkCommand.h"
Sebastien Jourdain's avatar
Sebastien Jourdain committed
18
#include "vtkDebugLeaks.h"
19
#include "vtkObjectFactory.h"
20
#include "vtkPVCatalystSessionCore.h"
21
#include "vtkPVServerInformation.h"
22 23 24
#include "vtkPVSessionCore.h"
#include "vtkProcessModule.h"
#include "vtkProcessModuleAutoMPI.h"
25
#include "vtkReservedRemoteObjectIds.h"
26
#include "vtkSMDeserializerProtobuf.h"
27
#include "vtkSMMessage.h"
28
#include "vtkSMPluginManager.h"
29
#include "vtkSMPropertyHelper.h"
30
#include "vtkSMProxy.h"
31
#include "vtkSMProxyLocator.h"
32
#include "vtkSMProxyManager.h"
33
#include "vtkSMSessionClient.h"
34
#include "vtkSMSessionProxyManager.h"
35
#include "vtkSMStateLocator.h"
36
#include "vtkSMUndoStackBuilder.h"
37
#include "vtkWeakPointer.h"
38

39
#include <assert.h>
40
#include <sstream>
41
#include <vtkNew.h>
42

Sebastien Jourdain's avatar
Sebastien Jourdain committed
43 44 45
//----------------------------------------------------------------------------
// STATICS
vtkSmartPointer<vtkProcessModuleAutoMPI> vtkSMSession::AutoMPI =
Kitware Robot's avatar
Kitware Robot committed
46
  vtkSmartPointer<vtkProcessModuleAutoMPI>::New();
Sebastien Jourdain's avatar
Sebastien Jourdain committed
47
//----------------------------------------------------------------------------
48 49
vtkStandardNewMacro(vtkSMSession);
//----------------------------------------------------------------------------
Kitware Robot's avatar
Kitware Robot committed
50
vtkSMSession* vtkSMSession::New(vtkPVSessionBase* otherSession)
51
{
52 53 54
  return vtkSMSession::New(otherSession->GetSessionCore());
}
//----------------------------------------------------------------------------
Kitware Robot's avatar
Kitware Robot committed
55
vtkSMSession* vtkSMSession::New(vtkPVSessionCore* otherSessionCore)
56 57
{
  vtkSMSession* session = new vtkSMSession(true, otherSessionCore);
58
  session->InitializeObjectBase();
59 60 61 62
  return session;
}

//----------------------------------------------------------------------------
Kitware Robot's avatar
Kitware Robot committed
63 64
vtkSMSession::vtkSMSession(
  bool initialize_during_constructor /*=true*/, vtkPVSessionCore* preExistingSessionCore /*=NULL*/)
65 66
  : vtkPVSessionBase(preExistingSessionCore ? preExistingSessionCore : vtkPVSessionCore::New())
{
Kitware Robot's avatar
Kitware Robot committed
67 68
  if (!preExistingSessionCore)
  {
69
    this->SessionCore->UnRegister(NULL);
Kitware Robot's avatar
Kitware Robot committed
70
  }
71

72
  this->SessionProxyManager = NULL;
73
  this->StateLocator = vtkSMStateLocator::New();
74
  this->IsAutoMPI = false;
75

76 77 78 79 80 81 82 83
  // Create and setup deserializer for the local ProxyLocator
  vtkNew<vtkSMDeserializerProtobuf> deserializer;
  deserializer->SetStateLocator(this->StateLocator);

  // Create and setup proxy locator
  this->ProxyLocator = vtkSMProxyLocator::New();
  this->ProxyLocator->SetDeserializer(deserializer.GetPointer());
  this->ProxyLocator->UseSessionToLocateProxy(true);
84 85 86 87 88 89

  // don't set the session on ProxyLocator right now since the
  // SessionProxyManager is not setup until Initialize().
  // we will initialize it in this->Initialize().

  if (initialize_during_constructor)
Kitware Robot's avatar
Kitware Robot committed
90
  {
91
    this->Initialize();
Kitware Robot's avatar
Kitware Robot committed
92
  }
93 94 95 96 97
}

//----------------------------------------------------------------------------
vtkSMSession::~vtkSMSession()
{
98
  if (vtkSMProxyManager::IsInitialized())
Kitware Robot's avatar
Kitware Robot committed
99
  {
100
    vtkSMProxyManager::GetProxyManager()->GetPluginManager()->UnRegisterSession(this);
Kitware Robot's avatar
Kitware Robot committed
101
  }
102

103
  this->StateLocator->Delete();
104
  this->ProxyLocator->Delete();
105
  if (this->SessionProxyManager)
Kitware Robot's avatar
Kitware Robot committed
106
  {
107 108
    this->SessionProxyManager->Delete();
    this->SessionProxyManager = NULL;
Kitware Robot's avatar
Kitware Robot committed
109
  }
110 111 112
}

//----------------------------------------------------------------------------
113 114
vtkSMSession::ServerFlags vtkSMSession::GetProcessRoles()
{
115
  if (vtkProcessModule::GetProcessModule() &&
116 117
    vtkProcessModule::GetProcessModule()->GetPartitionId() > 0 &&
    !vtkProcessModule::GetProcessModule()->GetSymmetricMPIMode())
Kitware Robot's avatar
Kitware Robot committed
118
  {
119
    return vtkPVSession::SERVERS;
Kitware Robot's avatar
Kitware Robot committed
120
  }
121

122
  return vtkPVSession::CLIENT_AND_SERVERS;
123 124 125
}

//----------------------------------------------------------------------------
126 127
void vtkSMSession::PushState(vtkSMMessage* msg)
{
128
  // Manage Undo/Redo if possible
129
  this->UpdateStateHistory(msg);
130

131
  this->Superclass::PushState(msg);
132 133
}

134
//----------------------------------------------------------------------------
135
void vtkSMSession::UpdateStateHistory(vtkSMMessage* msg)
136
{
137
  // check is global-undo-stack builder is set.
Kitware Robot's avatar
Kitware Robot committed
138
  vtkSMUndoStackBuilder* usb = vtkSMProxyManager::GetProxyManager()->GetUndoStackBuilder();
139

Kitware Robot's avatar
Kitware Robot committed
140 141
  if (usb == NULL || (this->GetProcessRoles() & vtkPVSession::CLIENT) == 0)
  {
142
    return;
Kitware Robot's avatar
Kitware Robot committed
143
  }
144

145
  vtkTypeUInt32 globalId = msg->global_id();
Kitware Robot's avatar
Kitware Robot committed
146
  vtkSMRemoteObject* remoteObj = vtkSMRemoteObject::SafeDownCast(this->GetRemoteObject(globalId));
147

Kitware Robot's avatar
Kitware Robot committed
148 149
  if (remoteObj && !remoteObj->IsPrototype() && remoteObj->GetFullState())
  {
150 151 152 153 154 155 156 157 158
    vtkSMMessage newState;
    newState.CopyFrom(*remoteObj->GetFullState());

    // Need to provide id/location as the full state may not have them yet
    newState.set_global_id(globalId);
    newState.set_location(msg->location());

    // Store state in cache
    vtkSMMessage oldState;
Kitware Robot's avatar
Kitware Robot committed
159 160
    bool createAction = !this->StateLocator->FindState(globalId, &oldState,
      /* We want only a local lookup => false */ false);
161 162 163

    // This is a filtering Hack, I don't like it. :-(
    if (newState.GetExtension(ProxyState::xml_name) != "Camera")
Kitware Robot's avatar
Kitware Robot committed
164
    {
165
      this->StateLocator->RegisterState(&newState);
Kitware Robot's avatar
Kitware Robot committed
166
    }
167 168 169

    // Propagate to undo stack builder if possible
    if (createAction)
Kitware Robot's avatar
Kitware Robot committed
170
    {
171
      usb->OnCreateObject(this, &newState);
Kitware Robot's avatar
Kitware Robot committed
172
    }
173
    else if (oldState.SerializeAsString() != newState.SerializeAsString())
Kitware Robot's avatar
Kitware Robot committed
174
    {
175
      // Update
Kitware Robot's avatar
Kitware Robot committed
176
      usb->OnStateChange(this, globalId, &oldState, &newState);
177
    }
Kitware Robot's avatar
Kitware Robot committed
178
  }
Utkarsh Ayachit's avatar
Utkarsh Ayachit committed
179 180
}

181
//----------------------------------------------------------------------------
182
void vtkSMSession::Initialize()
183
{
184
  assert(this->SessionProxyManager == NULL);
185

186 187 188 189
  // Remember, although vtkSMSession is always only created on the client side,
  // in batch mode, vtkSMSession is created on all nodes.

  // All these initializations need to be done on all nodes in symmetric-batch
Sebastien Jourdain's avatar
Sebastien Jourdain committed
190 191
  // mode. In non-symmetric-batch mode. Which means we are a CLIENT,
  // so if we are not then we stop the initialisation here !
Kitware Robot's avatar
Kitware Robot committed
192 193
  if (!(this->GetProcessRoles() & vtkPVSession::CLIENT))
  {
Sebastien Jourdain's avatar
Sebastien Jourdain committed
194
    return;
Kitware Robot's avatar
Kitware Robot committed
195
  }
196 197 198 199

  // Initialize the proxy manager.
  // this updates proxy definitions if we are connected to a remote server.
  this->SessionProxyManager = vtkSMSessionProxyManager::New(this);
200
  this->ProxyLocator->SetSession(this);
201 202

  // Initialize the plugin manager.
203
  vtkSMProxyManager::GetProxyManager()->GetPluginManager()->RegisterSession(this);
204 205

  // Setup default mapper parameters.
Kitware Robot's avatar
Kitware Robot committed
206 207 208
  const char* group = "misc";
  const char* name = "GlobalMapperProperties";

209 210
  // First try and get the prototype, if its NULL then the proxy is not
  // available.
Kitware Robot's avatar
Kitware Robot committed
211
  vtkSMProxy* prototype = this->SessionProxyManager->GetPrototypeProxy(group, name);
212 213 214
  if (!prototype)
    return;

Kitware Robot's avatar
Kitware Robot committed
215
  vtkSMProxy* globalMapperProperties = this->SessionProxyManager->NewProxy(group, name);
216
  if (globalMapperProperties)
Kitware Robot's avatar
Kitware Robot committed
217
  {
218 219 220 221
    vtkSMPropertyHelper(globalMapperProperties, "Mode").Set("ShiftZBuffer");
    vtkSMPropertyHelper(globalMapperProperties, "ZShift").Set(2.0e-3);
    globalMapperProperties->UpdateVTKObjects();
    globalMapperProperties->Delete();
Kitware Robot's avatar
Kitware Robot committed
222
  }
223 224
}

Utkarsh Ayachit's avatar
Utkarsh Ayachit committed
225 226 227 228
//----------------------------------------------------------------------------
int vtkSMSession::GetNumberOfProcesses(vtkTypeUInt32 servers)
{
  (void)servers;
229
  return vtkProcessModule::GetProcessModule()->GetNumberOfLocalPartitions();
Utkarsh Ayachit's avatar
Utkarsh Ayachit committed
230 231
}

232 233 234 235 236 237
//----------------------------------------------------------------------------
bool vtkSMSession::IsMPIInitialized(vtkTypeUInt32)
{
  return vtkProcessModule::GetProcessModule()->IsMPIInitialized();
}

238 239 240 241
//----------------------------------------------------------------------------
void vtkSMSession::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
242
}
243

244 245 246 247
//----------------------------------------------------------------------------
void vtkSMSession::Disconnect(vtkSMSession* session)
{
  if (!session)
Kitware Robot's avatar
Kitware Robot committed
248
  {
249
    return;
Kitware Robot's avatar
Kitware Robot committed
250
  }
251

252 253 254 255 256 257
  if (session->IsMultiClients())
  {
    // Ensure that the session no longer sends state updates to the server-side.
    // This is critical to ensure we don't mess up the collaboration state.
    session->PreDisconnection();
  }
258 259 260 261 262 263 264 265

  // Unregister all proxies.
  session->GetSessionProxyManager()->UnRegisterProxies();

  vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
  pm->UnRegisterSession(session);
  // Although I'd like to have this check, when Disconnect() is called from
  // Python, we have 1 reference that gets cleared with the Python call returns.
Kitware Robot's avatar
Kitware Robot committed
266
  // if (session != NULL)
267 268 269 270 271 272 273 274 275 276 277 278 279 280
  //  {
  //  vtkGenericWarningMacro(
  //    "vtkSMSession wasn't destroyed after UnRegisterSession. "
  //    "This indicates a development problem. Please notify the "
  //    "developers.");
  //  }
}

//----------------------------------------------------------------------------
void vtkSMSession::Disconnect(vtkIdType sid)
{
  vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
  vtkWeakPointer<vtkSMSession> session = vtkSMSession::SafeDownCast(pm->GetSession(sid));
  if (!session)
Kitware Robot's avatar
Kitware Robot committed
281 282
  {
    vtkGenericWarningMacro("Failed to locate session " << sid << ". Cannot disconnect.");
283
    return;
Kitware Robot's avatar
Kitware Robot committed
284
  }
285 286 287 288

  vtkSMSession::Disconnect(session);
}

289
//----------------------------------------------------------------------------
290
vtkIdType vtkSMSession::ConnectToSelf(int timeout)
291
{
292
  vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
Sebastien Jourdain's avatar
Sebastien Jourdain committed
293 294
  vtkIdType sid = 0;

295
  if (vtkSMSession::AutoMPI->IsPossible())
Kitware Robot's avatar
Kitware Robot committed
296
  {
Sebastien Jourdain's avatar
Sebastien Jourdain committed
297
    int port = vtkSMSession::AutoMPI->ConnectToRemoteBuiltInSelf();
298
    if (port > 0)
Kitware Robot's avatar
Kitware Robot committed
299
    {
300
      sid = vtkSMSession::ConnectToRemoteInternal("localhost", port, true, timeout);
301
      if (sid > 0)
Kitware Robot's avatar
Kitware Robot committed
302
      {
303 304
        return sid;
      }
Sebastien Jourdain's avatar
Sebastien Jourdain committed
305
    }
Kitware Robot's avatar
Kitware Robot committed
306 307 308
    vtkGenericWarningMacro("Failed to automatically launch 'pvserver' for multi-core support. "
                           "Defaulting to local session.");
  }
Sebastien Jourdain's avatar
Sebastien Jourdain committed
309

310 311 312
  vtkSMSession* session = vtkSMSession::New();
  sid = pm->RegisterSession(session);
  session->Delete();
313 314 315
  return sid;
}

316 317 318 319 320 321 322 323 324 325 326 327
//----------------------------------------------------------------------------
vtkIdType vtkSMSession::ConnectToCatalyst()
{
  vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
  vtkIdType sid = 0;
  vtkNew<vtkPVCatalystSessionCore> sessionCore;
  vtkSMSession* session = vtkSMSession::New(sessionCore.GetPointer());
  sid = pm->RegisterSession(session);
  session->Delete();
  return sid;
}

328
//----------------------------------------------------------------------------
329
vtkIdType vtkSMSession::ConnectToRemote(const char* hostname, int port, int timeout)
330
{
331
  return vtkSMSession::ConnectToRemoteInternal(hostname, port, false, timeout);
332 333
}

334
//----------------------------------------------------------------------------
335 336
vtkIdType vtkSMSession::ConnectToRemoteInternal(
  const char* hostname, int port, bool is_auto_mpi, int timeout)
337
{
338
  std::ostringstream sname;
339 340
  sname << "cs://" << hostname << ":" << port;
  vtkSMSessionClient* session = vtkSMSessionClient::New();
341
  session->IsAutoMPI = is_auto_mpi;
342
  vtkIdType sid = 0;
343
  if (session->Connect(sname.str().c_str(), timeout))
Kitware Robot's avatar
Kitware Robot committed
344
  {
345
    vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
346
    sid = pm->RegisterSession(session);
Kitware Robot's avatar
Kitware Robot committed
347
  }
348 349 350 351 352
  session->Delete();
  return sid;
}

//----------------------------------------------------------------------------
Kitware Robot's avatar
Kitware Robot committed
353
vtkIdType vtkSMSession::ConnectToRemote(
354
  const char* dshost, int dsport, const char* rshost, int rsport, int timeout)
355
{
356
  std::ostringstream sname;
Kitware Robot's avatar
Kitware Robot committed
357
  sname << "cdsrs://" << dshost << ":" << dsport << "/" << rshost << ":" << rsport;
358 359
  vtkSMSessionClient* session = vtkSMSessionClient::New();
  vtkIdType sid = 0;
360
  if (session->Connect(sname.str().c_str(), timeout))
Kitware Robot's avatar
Kitware Robot committed
361
  {
362
    vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
363
    sid = pm->RegisterSession(session);
Kitware Robot's avatar
Kitware Robot committed
364
  }
365 366 367
  session->Delete();
  return sid;
}
368

369
//----------------------------------------------------------------------------
370 371
namespace
{
Kitware Robot's avatar
Kitware Robot committed
372 373 374 375 376 377 378 379 380 381 382 383 384
class vtkTemp
{
public:
  bool (*Callback)();
  vtkSMSessionClient* Session;
  vtkTemp()
  {
    this->Callback = NULL;
    this->Session = NULL;
  }
  void OnEvent()
  {
    if (this->Callback != NULL)
385
    {
Kitware Robot's avatar
Kitware Robot committed
386 387
      bool continue_waiting = (*this->Callback)();
      if (!continue_waiting && this->Session)
388
      {
Kitware Robot's avatar
Kitware Robot committed
389
        this->Session->SetAbortConnect(true);
390
      }
Kitware Robot's avatar
Kitware Robot committed
391 392 393
    }
  }
};
394 395 396 397 398 399 400 401 402
}

//----------------------------------------------------------------------------
vtkIdType vtkSMSession::ReverseConnectToRemote(int port, bool (*callback)())
{
  return vtkSMSession::ReverseConnectToRemote(port, -1, callback);
}

//----------------------------------------------------------------------------
Kitware Robot's avatar
Kitware Robot committed
403
vtkIdType vtkSMSession::ReverseConnectToRemote(int dsport, int rsport, bool (*callback)())
404 405 406 407
{
  vtkTemp temp;
  temp.Callback = callback;

408
  std::ostringstream sname;
409
  if (rsport <= -1)
Kitware Robot's avatar
Kitware Robot committed
410
  {
411
    sname << "csrc://localhost:" << dsport;
Kitware Robot's avatar
Kitware Robot committed
412
  }
413
  else
Kitware Robot's avatar
Kitware Robot committed
414 415 416
  {
    sname << "cdsrsrc://localhost:" << dsport << "/localhost:" << rsport;
  }
417 418 419

  vtkSMSessionClient* session = vtkSMSessionClient::New();
  temp.Session = session;
Kitware Robot's avatar
Kitware Robot committed
420
  unsigned long id = session->AddObserver(vtkCommand::ProgressEvent, &temp, &vtkTemp::OnEvent);
421 422 423

  vtkIdType sid = 0;
  if (session->Connect(sname.str().c_str()))
Kitware Robot's avatar
Kitware Robot committed
424
  {
425 426
    vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
    sid = pm->RegisterSession(session);
Kitware Robot's avatar
Kitware Robot committed
427
  }
428 429 430 431
  session->RemoveObserver(id);
  session->Delete();
  return sid;
}
432 433 434 435
//----------------------------------------------------------------------------
unsigned int vtkSMSession::GetRenderClientMode()
{
  if (this->GetIsAutoMPI())
Kitware Robot's avatar
Kitware Robot committed
436
  {
437
    return vtkSMSession::RENDERING_SPLIT;
Kitware Robot's avatar
Kitware Robot committed
438
  }
439
  if (this->GetController(vtkPVSession::DATA_SERVER_ROOT) !=
Kitware Robot's avatar
Kitware Robot committed
440 441
    this->GetController(vtkPVSession::RENDER_SERVER_ROOT))
  {
442 443 444
    // when the two controller are different, we have a separate render-server
    // and data-server session.
    return vtkSMSession::RENDERING_SPLIT;
Kitware Robot's avatar
Kitware Robot committed
445
  }
446 447 448

  vtkPVServerInformation* server_info = this->GetServerInformation();
  if (server_info && server_info->GetNumberOfMachines() > 0)
Kitware Robot's avatar
Kitware Robot committed
449
  {
450
    return vtkSMSession::RENDERING_SPLIT;
Kitware Robot's avatar
Kitware Robot committed
451
  }
452 453 454

  return vtkSMSession::RENDERING_UNIFIED;
}
455 456 457 458 459 460 461

//----------------------------------------------------------------------------
void vtkSMSession::ProcessNotification(const vtkSMMessage* message)
{
  vtkTypeUInt32 id = message->global_id();

  // Find the object for whom this message is meant.
Kitware Robot's avatar
Kitware Robot committed
462
  vtkSMRemoteObject* remoteObj = vtkSMRemoteObject::SafeDownCast(this->GetRemoteObject(id));
463

Kitware Robot's avatar
Kitware Robot committed
464 465
  // cout << "##########     Server notification    ##########" << endl;
  // cout << id << " = " << remoteObj << "(" << (remoteObj?
466
  //    remoteObj->GetClassName() : "null") << ")" << endl;
Kitware Robot's avatar
Kitware Robot committed
467 468
  // state.PrintDebugString();
  // cout << "###################################################" << endl;
469 470 471 472 473

  // ProcessingRemoteNotification = true prevent
  // "ignore_synchronization" properties to be loaded...
  // Therefore camera properties won't be shared
  // (I don't understand this comment, but copying it from the original code).
Kitware Robot's avatar
Kitware Robot committed
474 475
  if (remoteObj)
  {
476 477 478
    bool previousValue = this->StartProcessingRemoteNotification();
    remoteObj->EnableLocalPushOnly();
    remoteObj->LoadState(message, this->GetProxyLocator());
Kitware Robot's avatar
Kitware Robot committed
479

480 481
    vtkSMProxy* proxy = vtkSMProxy::SafeDownCast(remoteObj);
    if (proxy)
Kitware Robot's avatar
Kitware Robot committed
482
    {
483
      proxy->UpdateVTKObjects();
Kitware Robot's avatar
Kitware Robot committed
484
    }
485 486 487

    remoteObj->DisableLocalPushOnly();
    this->StopProcessingRemoteNotification(previousValue);
Kitware Robot's avatar
Kitware Robot committed
488
  }
489
}