Commit 38cc4d21 authored by Utkarsh Ayachit's avatar Utkarsh Ayachit Committed by Kitware Robot
Browse files

Merge topic 'fix_representation_delivery_to_support_concurrency'

863cfacb Disable error macro on server when multi-client enable
e53a2946 Use MagicNumber to determine out-of-synch delivery manager state
8ff63775 Fix id management for representation delivery
parents 7d3b82d2 863cfacb
......@@ -54,6 +54,7 @@ vtkPVOptions::vtkPVOptions()
this->ClientMode = 0;
this->ServerMode = 0;
this->MultiClientMode = 0;
this->MultiClientModeWithErrorMacro = 0;
this->MultiServerMode = 0;
this->RenderServerMode = 0;
......@@ -165,6 +166,12 @@ void vtkPVOptions::Initialize()
"connect to it and share the same visualization session.",
vtkPVOptions::PVDATA_SERVER|vtkPVOptions::PVSERVER);
this->AddBooleanArgument("--multi-clients-debug", 0, &this->MultiClientModeWithErrorMacro,
"Allow server to keep listening for serveral client to"
"connect to it and share the same visualization session."
"While keeping the error macro on the server session for debug.",
vtkPVOptions::PVDATA_SERVER|vtkPVOptions::PVSERVER);
this->AddBooleanArgument("--multi-servers", 0, &this->MultiServerMode,
"Allow client to connect to several pvserver",
vtkPVOptions::PVCLIENT);
......
......@@ -123,7 +123,9 @@ public:
// Is this server was started for collaboration meaning that it allow
// several clients to connect to the same server and share the same
// pipeline and visualization.
vtkGetMacro(MultiClientMode, int);
virtual int GetMultiClientMode()
{ return (this->MultiClientMode || this->MultiClientModeWithErrorMacro) ?1:0; }
virtual int IsMultiClientModeDebug() { return this->MultiClientModeWithErrorMacro; }
// Description:
// Is this client allow multiple server connection in parallel
......@@ -216,6 +218,7 @@ protected:
int ClientMode;
int RenderServerMode;
int MultiClientMode;
int MultiClientModeWithErrorMacro;
int MultiServerMode;
int SymmetricMPIMode;
......
......@@ -77,6 +77,9 @@ void vtkCompositeRepresentation::AddRepresentation(
{
assert(repr != NULL && key != NULL);
// Make sure the representation that we register is already initialized
repr->Initialize(1,0); // Should abort if no initialized as 1 > 0
if (this->Internals->Representations.find(key) !=
this->Internals->Representations.end())
{
......
......@@ -370,3 +370,13 @@ vtkDataObject* vtkCompositeSliceRepresentation::GetRenderedDataObject(int vtkNot
{
return this->InternalSliceFilter->GetInputDataObject(0,0);
}
//----------------------------------------------------------------------------
unsigned int vtkCompositeSliceRepresentation::Initialize(unsigned int minIdAvailable,
unsigned int maxIdAvailable)
{
unsigned int newMin =
this->OutlineRepresentation->Initialize(minIdAvailable, maxIdAvailable);
return this->Superclass::Initialize(newMin, maxIdAvailable);
}
......@@ -72,6 +72,11 @@ public:
// Override to provide input array name regardless if any slice cut the actual data.
virtual vtkDataObject* GetRenderedDataObject(int port);
// Description:
// Override because of internal composite representations that need to be
// initilized as well.
virtual unsigned int Initialize(unsigned int minIdAvailable, unsigned int maxIdAvailable);
//BTX
protected:
vtkCompositeSliceRepresentation();
......
......@@ -235,3 +235,13 @@ void vtkPVCompositeRepresentation::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
unsigned int vtkPVCompositeRepresentation::Initialize(unsigned int minIdAvailable,
unsigned int maxIdAvailable)
{
unsigned int minId = minIdAvailable;
minId = this->CubeAxesRepresentation->Initialize(minId, maxIdAvailable);
minId = this->SelectionRepresentation->Initialize(minId, maxIdAvailable);
return this->Superclass::Initialize(minId, maxIdAvailable);
}
......@@ -79,6 +79,11 @@ public:
virtual void SetPointFieldDataArrayName(const char*);
virtual void SetCellFieldDataArrayName(const char*);
// Description:
// Override because of internal composite representations that need to be
// initilized as well.
virtual unsigned int Initialize(unsigned int minIdAvailable, unsigned int maxIdAvailable);
//BTX
protected:
vtkPVCompositeRepresentation();
......
......@@ -184,16 +184,7 @@ public:
vtkItem* GetItem(vtkPVDataRepresentation* repr, bool use_second)
{
RepresentationToIdMapType::iterator iter =
this->RepresentationToIdMap.find(repr);
if (iter != this->RepresentationToIdMap.end())
{
unsigned int index = iter->second;
return use_second? &(this->ItemsMap[index].second) :
&(this->ItemsMap[index].first);
}
return NULL;
return this->GetItem(repr->GetUniqueIdentifier(), use_second);
}
unsigned long GetVisibleDataSize(bool use_second_if_available)
......@@ -214,10 +205,6 @@ public:
return size;
}
typedef std::map<vtkPVDataRepresentation*, unsigned int>
RepresentationToIdMapType;
RepresentationToIdMapType RepresentationToIdMap;
ItemsMapType ItemsMap;
};
......@@ -256,47 +243,25 @@ unsigned long vtkPVDataDeliveryManager::GetVisibleDataSize(bool low_res)
}
//----------------------------------------------------------------------------
void vtkPVDataDeliveryManager::RegisterRepresentation(
unsigned int id, vtkPVDataRepresentation* repr)
void vtkPVDataDeliveryManager::RegisterRepresentation(vtkPVDataRepresentation* repr)
{
this->Internals->RepresentationToIdMap[repr] = id;
assert( "A representation must have a valid UniqueIdentifier"
&& repr->GetUniqueIdentifier());
vtkInternals::vtkItem item;
item.Representation = repr;
this->Internals->ItemsMap[id].first = item;
this->Internals->ItemsMap[repr->GetUniqueIdentifier()].first = item;
vtkInternals::vtkItem item2;
item2.Representation = repr;
this->Internals->ItemsMap[id].second= item2;
this->Internals->ItemsMap[repr->GetUniqueIdentifier()].second= item2;
}
//----------------------------------------------------------------------------
void vtkPVDataDeliveryManager::UnRegisterRepresentation(
vtkPVDataRepresentation* repr)
{
vtkInternals::RepresentationToIdMapType::iterator iter =
this->Internals->RepresentationToIdMap.find(repr);
if (iter == this->Internals->RepresentationToIdMap.end())
{
vtkErrorMacro("Invalid argument.");
return;
}
this->Internals->ItemsMap.erase(iter->second);
this->Internals->RepresentationToIdMap.erase(iter);
}
//----------------------------------------------------------------------------
unsigned int vtkPVDataDeliveryManager::GetRepresentationId(
vtkPVDataRepresentation* repr)
{
vtkInternals::RepresentationToIdMapType::iterator iter =
this->Internals->RepresentationToIdMap.find(repr);
if (iter == this->Internals->RepresentationToIdMap.end())
{
vtkErrorMacro("Invalid argument.");
return 0;
}
return iter->second;
this->Internals->ItemsMap.erase(repr->GetUniqueIdentifier());
}
//----------------------------------------------------------------------------
......@@ -743,3 +708,18 @@ void vtkPVDataDeliveryManager::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
int vtkPVDataDeliveryManager::GetSynchronizationMagicNumber()
{
const int prime = 31;
int result = 1;
result = prime * result + static_cast<int>(this->Internals->ItemsMap.size());
vtkInternals::ItemsMapType::iterator iter = this->Internals->ItemsMap.begin();
for(;iter != this->Internals->ItemsMap.end(); iter++)
{
result = prime * result + static_cast<int>(iter->first);
}
return result;
}
......@@ -46,14 +46,18 @@ public:
vtkTypeMacro(vtkPVDataDeliveryManager, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent);
// Description:
// Returned a hash number that can be used to verify that both client and
// server side are in synch representation wise for delivery.
int GetSynchronizationMagicNumber();
// Description:
// View uses these methods to register a representation with the storage. This
// makes it possible for representations to communicate with the storage
// directly using a self pointer, while enables views on different processes
// to communicate information about representations using their unique ids.
void RegisterRepresentation(unsigned int id, vtkPVDataRepresentation*);
void RegisterRepresentation(vtkPVDataRepresentation *repr);
void UnRegisterRepresentation(vtkPVDataRepresentation*);
unsigned int GetRepresentationId(vtkPVDataRepresentation*);
vtkPVDataRepresentation* GetRepresentation(unsigned int);
// Description:
......
......@@ -48,6 +48,8 @@ vtkPVDataRepresentation::vtkPVDataRepresentation()
this->ForcedCacheKey = 0.0;
this->NeedUpdate = true;
this->UniqueIdentifier = 0;
}
//----------------------------------------------------------------------------
......@@ -79,6 +81,7 @@ vtkExecutive* vtkPVDataRepresentation::CreateDefaultExecutive()
int vtkPVDataRepresentation::ProcessViewRequest(
vtkInformationRequestKey* request, vtkInformation*, vtkInformation*)
{
assert("We must have an ID at that time" && this->UniqueIdentifier);
assert(this->GetExecutive()->IsA("vtkPVDataRepresentationPipeline"));
if (this->GetVisibility() == false)
{
......@@ -100,6 +103,20 @@ void vtkPVDataRepresentation::MarkModified()
this->NeedUpdate = true;
}
//----------------------------------------------------------------------------
unsigned int vtkPVDataRepresentation::Initialize(unsigned int minIdAvailable, unsigned int maxIdAvailable)
{
// Already initialized ?
if(this->UniqueIdentifier)
{
return minIdAvailable;
}
assert("Invalid Representation Id. Not enough reserved ids." && (maxIdAvailable >= minIdAvailable));
this->UniqueIdentifier = minIdAvailable;
return (1 + this->UniqueIdentifier);
}
//----------------------------------------------------------------------------
int vtkPVDataRepresentation::RequestData(vtkInformation*,
vtkInformationVector**, vtkInformationVector*)
......
......@@ -63,6 +63,25 @@ public:
// update-suppressor.
virtual void MarkModified();
// Description:
// Initialize the representation with an identifier range so each internal
// representation can own a unique ID.
// If a representation requires more IDs than the set of ids provided,
// the representation MUST complains by an error or abort explaining how many
// ids where expected so the number of reserved ids could be easily adjust.
// Unless noted otherwise, this method must be called before calling any
// other methods on this class.
// @CallOnAllProcessess
// Internally you can pick an id that follow that condition
// minIdAvailable <= id <= maxIdAvailable
// Return the minIdAvailable after initialization so that new range could be used
virtual unsigned int Initialize(unsigned int minIdAvailable, unsigned int maxIdAvailable);
// Description:
// Return 0 if the Initialize() method was not called otherwise a unique ID
// that will be shared across the processes for that same object.
unsigned int GetUniqueIdentifier() { return this->UniqueIdentifier; }
// Description:
// Get/Set the visibility for this representation. When the visibility of
// representation of false, all view passes are ignored.
......@@ -172,6 +191,7 @@ protected:
double UpdateTime;
bool UpdateTimeValid;
unsigned int UniqueIdentifier;
private:
vtkPVDataRepresentation(const vtkPVDataRepresentation&); // Not implemented
void operator=(const vtkPVDataRepresentation&); // Not implemented
......
......@@ -84,12 +84,8 @@ class vtkPVRenderView::vtkInternals
std::map<int, vtkWeakPointer<vtkPVDataRepresentation> > PropMap;
public:
unsigned int UniqueId;
vtkNew<vtkPVDataDeliveryManager> DeliveryManager;
vtkInternals() : UniqueId(1)
{
}
void RegisterSelectionProp(
int id, vtkProp*, vtkPVDataRepresentation* rep)
{
......@@ -186,7 +182,6 @@ vtkPVRenderView::vtkPVRenderView()
this->UseInteractiveRenderingForSceenshots = false;
this->UseOffscreenRendering = (options->GetUseOffscreenRendering() != 0);
this->Selector = vtkPVHardwareSelector::New();
this->SynchronizationCounter = 0;
this->PreviousParallelProjectionStatus = 0;
this->NeedsOrderedCompositing = false;
......@@ -387,11 +382,7 @@ void vtkPVRenderView::AddRepresentationInternal(vtkDataRepresentation* rep)
vtkPVDataRepresentation* dataRep = vtkPVDataRepresentation::SafeDownCast(rep);
if (dataRep != NULL)
{
// We only increase that counter when widget are not involved as in
// collaboration mode only the master has the widget in its representation
this->SynchronizationCounter++;
unsigned int id = this->Internals->UniqueId++;
this->Internals->DeliveryManager->RegisterRepresentation(id, dataRep);
this->Internals->DeliveryManager->RegisterRepresentation(dataRep);
}
this->Superclass::AddRepresentationInternal(rep);
......@@ -404,10 +395,6 @@ void vtkPVRenderView::RemoveRepresentationInternal(vtkDataRepresentation* rep)
if (dataRep != NULL)
{
this->Internals->DeliveryManager->UnRegisterRepresentation(dataRep);
// We only increase that counter when widget are not involved as in
// collaboration mode only the master has the widget in its representation
this->SynchronizationCounter++;
}
this->Superclass::RemoveRepresentationInternal(rep);
......@@ -730,21 +717,23 @@ bool vtkPVRenderView::TestCollaborationCounter()
if (this->SynchronizedWindows->GetMode() == vtkPVSynchronizedRenderWindows::CLIENT)
{
r_controller->Send(&this->SynchronizationCounter, 1, 1, 41000);
unsigned int server_sync_counter;
int magicNumber = this->GetDeliveryManager()->GetSynchronizationMagicNumber();
r_controller->Send(&magicNumber, 1, 1, 41000);
int server_sync_counter;
r_controller->Receive(&server_sync_counter, 1, 1, 41001);
return (server_sync_counter == this->SynchronizationCounter);
return (server_sync_counter == magicNumber);
}
else
{
bool counterSynchronizedSuccessfully = false;
if (r_controller)
{
unsigned int client_sync_counter;
int client_sync_counter;
int magicNumber = this->GetDeliveryManager()->GetSynchronizationMagicNumber();
r_controller->Receive(&client_sync_counter, 1, 1, 41000);
r_controller->Send(&this->SynchronizationCounter, 1, 1, 41001 );
r_controller->Send(&magicNumber, 1, 1, 41001 );
counterSynchronizedSuccessfully =
(client_sync_counter == this->SynchronizationCounter);
(client_sync_counter == magicNumber);
}
if (p_controller)
......
......@@ -286,3 +286,13 @@ void vtkSelectionRepresentation::SetCellFieldDataArrayName(const char* val)
{
this->LabelRepresentation->SetCellFieldDataArrayName(val);
}
//----------------------------------------------------------------------------
unsigned int vtkSelectionRepresentation::Initialize(unsigned int minIdAvailable,
unsigned int maxIdAvailable)
{
unsigned int minId = minIdAvailable;
minId = this->LabelRepresentation->Initialize(minId, maxIdAvailable);
minId = this->GeometryRepresentation->Initialize(minId, maxIdAvailable);
return this->Superclass::Initialize(minId, maxIdAvailable);
}
......@@ -93,6 +93,11 @@ public:
virtual void SetPointFieldDataArrayName(const char* val);
virtual void SetCellFieldDataArrayName(const char* val);
// Description:
// Override because of internal composite representations that need to be
// initilized as well.
virtual unsigned int Initialize(unsigned int minIdAvailable, unsigned int maxIdAvailable);
//BTX
protected:
vtkSelectionRepresentation();
......
......@@ -19,29 +19,30 @@
#include "vtkClientServerInterpreterInitializer.h"
#include "vtkClientServerStream.h"
#include "vtkCollection.h"
#include "vtkPVInstantiator.h"
#include "vtkMPIMToNSocketConnection.h"
#include "vtkMemberFunctionCommand.h"
#include "vtkMultiProcessController.h"
#include "vtkMultiProcessStream.h"
#include "vtkObjectFactory.h"
#include "vtkSIProxy.h"
#include "vtkPVSession.h"
#include "vtkReservedRemoteObjectIds.h"
#include "vtkPVInformation.h"
#include "vtkPVInstantiator.h"
#include "vtkPVOptions.h"
#include "vtkPVSession.h"
#include "vtkPVSessionCoreInterpreterHelper.h"
#include "vtkProcessModule.h"
#include "vtkSMMessage.h"
#include "vtkReservedRemoteObjectIds.h"
#include "vtkSIProxy.h"
#include "vtkSIProxyDefinitionManager.h"
#include "vtkPVSessionCoreInterpreterHelper.h"
#include "vtkSMMessage.h"
#include "vtkSmartPointer.h"
#include "assert.h"
#include <assert.h>
#include <fstream>
#include <set>
#include <string>
#include <vtksys/ios/sstream>
#define LOG(x)\
if (this->LogStream)\
{\
......@@ -87,7 +88,17 @@ class vtkPVSessionCore::vtkInternals
public:
vtkInternals()
{
}
this->DisableErrorMacro = false;
vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
if(pm)
{
if(vtkPVOptions *options = pm->GetOptions())
{
this->DisableErrorMacro =
(options->GetMultiClientMode() && !options->IsMultiClientModeDebug());
}
}
}
~vtkInternals()
{
// Remove SIObjects inter-dependency
......@@ -232,6 +243,9 @@ public:
unsigned long InterpreterObserverID;
std::map<vtkTypeUInt32, vtkSMMessage > MessageCacheMap;
std::set<int> KnownClients;
// Used for collaboration as client may trigger invalid server request when
// they are in a transitional state.
bool DisableErrorMacro;
};
//****************************************************************************/
......@@ -259,6 +273,7 @@ vtkPVSessionCore::vtkPVSessionCore()
helper->Delete();
this->Internals = new vtkInternals();
helper->SetLogLevel(this->Internals->DisableErrorMacro ? 1 : 0);
vtkMemberFunctionCommand<vtkPVSessionCore>* observer =
vtkMemberFunctionCommand<vtkPVSessionCore>::New();
......@@ -365,13 +380,16 @@ void vtkPVSessionCore::OnInterpreterError( vtkObject*, unsigned long,
(last.GetCommand(0) == vtkClientServerStream::Error) &&
last.GetArgument(0, 0, &errorMessage) && this->Interpreter->GetGlobalWarningDisplay())
{
vtksys_ios::ostringstream error;
error << "\nwhile processing\n";
info->css->PrintMessage(error, info->message);
error << ends;
vtkErrorMacro(<< errorMessage << error.str().c_str());
vtkErrorMacro("Aborting execution for debugging purposes.");
cout << "############ ABORT #############" << endl;
if(!this->Internals->DisableErrorMacro)
{
vtksys_ios::ostringstream error;
error << "\nwhile processing\n";
info->css->PrintMessage(error, info->message);
error << ends;
vtkErrorMacro(<< errorMessage << error.str().c_str());
vtkErrorMacro("Aborting execution for debugging purposes.");
cout << "############ ABORT #############" << endl;
}
return;
//abort();
}
......@@ -420,11 +438,14 @@ void vtkPVSessionCore::PushStateInternal(vtkSMMessage* message)
if (!message->HasExtension(DefinitionHeader::server_class))
{
vtkErrorMacro("Message missing DefinitionHeader."
"Aborting for debugging purposes.");
if(!this->Internals->DisableErrorMacro)
{
vtkErrorMacro("Message missing DefinitionHeader."
"Aborting for debugging purposes.");
message->PrintDebugString();
cout << "############ ABORT #############" << endl;
message->PrintDebugString();
cout << "############ ABORT #############" << endl;
}
return;
//abort();
}
......@@ -802,7 +823,10 @@ bool vtkPVSessionCore::GatherInformationInternal( vtkPVInformation* information,
vtkSIObject* siObject = this->GetSIObject(globalid);
if (!siObject)
{
vtkErrorMacro("No object with global-id: " << globalid);
if(!this->Internals->DisableErrorMacro)
{
vtkErrorMacro("No object with global-id: " << globalid);
}
return false;
}
......
......@@ -25,6 +25,7 @@ vtkStandardNewMacro(vtkPVSessionCoreInterpreterHelper);
//----------------------------------------------------------------------------
vtkPVSessionCoreInterpreterHelper::vtkPVSessionCoreInterpreterHelper()
{
this->LogLevel = 0;
}
//----------------------------------------------------------------------------
......@@ -56,7 +57,14 @@ vtkObjectBase* vtkPVSessionCoreInterpreterHelper::GetVTKObject(vtkTypeUInt32 gid
this->Core->GetSIObject(gid));
if (!siProxy)
{
vtkErrorMacro("No vtkSIProxy for id : " << gid);
switch(this->LogLevel)
{
case 0:
vtkErrorMacro("No vtkSIProxy for id : " << gid);
break;
default:
vtkWarningMacro("No vtkSIProxy for id : " << gid);
}
return NULL;
}
return siProxy->GetVTKObject();
......
......@@ -69,12 +69,17 @@ public:
// Used by vtkPVSessionCore to pass the core. This is not reference counted.
void SetCore(vtkPVSessionCore*);
// Description:
// Switch from 0:vtkErrorMacro to 1:vtkWarningMacro
vtkSetMacro(LogLevel, int);
//BTX
protected:
vtkPVSessionCoreInterpreterHelper();
~vtkPVSessionCoreInterpreterHelper();
vtkWeakPointer<vtkPVSessionCore> Core;
int LogLevel;
private:
vtkPVSessionCoreInterpreterHelper(const vtkPVSessionCoreInterpreterHelper&); // Not implemented
void operator=(const vtkPVSessionCoreInterpreterHelper&); // Not implemented
......
......@@ -24,6 +24,8 @@
#include <assert.h>
#define MAX_NUMBER_OF_INTERNAL_REPRESENTATIONS 10
vtkStandardNewMacro(vtkSMRepresentationProxy);