diff --git a/IO/ParallelXML/CMakeLists.txt b/IO/ParallelXML/CMakeLists.txt index f32a47dc33ac58dbc846f1e19447833f667bea57..6d25a7b202f24dddee59ac9297cf84f2bbe31ab9 100644 --- a/IO/ParallelXML/CMakeLists.txt +++ b/IO/ParallelXML/CMakeLists.txt @@ -1,5 +1,6 @@ set(Module_SRCS vtkXMLPDataSetWriter.cxx + vtkXMLPDataObjectWriter.cxx vtkXMLPDataWriter.cxx vtkXMLPImageDataWriter.cxx vtkXMLPPolyDataWriter.cxx diff --git a/IO/ParallelXML/vtkXMLPDataObjectWriter.cxx b/IO/ParallelXML/vtkXMLPDataObjectWriter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..956d432a3feb1fd667ea7bb86f0e2efc0b250489 --- /dev/null +++ b/IO/ParallelXML/vtkXMLPDataObjectWriter.cxx @@ -0,0 +1,382 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkXMLPDataObjectWriter.cxx + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkXMLPDataObjectWriter.h" + +#include "vtkCallbackCommand.h" +#include "vtkErrorCode.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMultiProcessController.h" +#include "vtkStreamingDemandDrivenPipeline.h" + +#include <vtksys/SystemTools.hxx> + +#include <cassert> + +vtkCxxSetObjectMacro(vtkXMLPDataObjectWriter, Controller, vtkMultiProcessController); +//---------------------------------------------------------------------------- +vtkXMLPDataObjectWriter::vtkXMLPDataObjectWriter() +{ + this->StartPiece = 0; + this->EndPiece = 0; + this->NumberOfPieces = 1; + this->GhostLevel = 0; + this->WriteSummaryFile = 1; + + this->UseSubdirectory = false; + + this->PathName = nullptr; + this->FileNameBase = nullptr; + this->FileNameExtension = nullptr; + this->PieceFileNameExtension = nullptr; + + // Setup a callback for the internal writer to report progress. + this->InternalProgressObserver = vtkCallbackCommand::New(); + this->InternalProgressObserver->SetCallback(&vtkXMLPDataObjectWriter::ProgressCallbackFunction); + this->InternalProgressObserver->SetClientData(this); + + this->Controller = nullptr; + this->SetController(vtkMultiProcessController::GetGlobalController()); + + this->ContinuingExecution = false; + this->CurrentPiece = -1; + this->PieceWrittenFlags = nullptr; +} + +//---------------------------------------------------------------------------- +vtkXMLPDataObjectWriter::~vtkXMLPDataObjectWriter() +{ + delete[] this->PathName; + delete[] this->FileNameBase; + delete[] this->FileNameExtension; + delete[] this->PieceFileNameExtension; + delete[] this->PieceWrittenFlags; + this->SetController(nullptr); + this->InternalProgressObserver->Delete(); +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataObjectWriter::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n"; + os << indent << "StartPiece: " << this->StartPiece << "\n"; + os << indent << "EndPiece: " << this->EndPiece << "\n"; + os << indent << "GhostLevel: " << this->GhostLevel << "\n"; + os << indent << "UseSubdirectory: " << this->UseSubdirectory << "\n"; + os << indent << "WriteSummaryFile: " << this->WriteSummaryFile << "\n"; +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataObjectWriter::ProcessRequest( + vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) +{ + if (request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) + { + return this->RequestUpdateExtent(request, inputVector, outputVector); + } + + int retVal = this->Superclass::ProcessRequest(request, inputVector, outputVector); + if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) + { + if (retVal && this->ContinuingExecution) + { + request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1); + } + else + { + request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING()); + this->ContinuingExecution = false; + } + } + return retVal; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataObjectWriter::SetWriteSummaryFile(int flag) +{ + vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting WriteSummaryFile to " + << flag); + if (this->WriteSummaryFile != flag) + { + this->WriteSummaryFile = flag; + this->Modified(); + } +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataObjectWriter::RequestUpdateExtent(vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, vtkInformationVector* vtkNotUsed(outputVector)) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + int piece = 0; + if (this->ContinuingExecution) + { + assert(this->CurrentPiece >= this->StartPiece && this->CurrentPiece <= this->EndPiece && + this->CurrentPiece < this->NumberOfPieces); + piece = this->CurrentPiece; + } + else + { + piece = this->StartPiece; + } + + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), piece); + inInfo->Set( + vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), this->GetNumberOfPieces()); + inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), this->GhostLevel); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataObjectWriter::WriteInternal() +{ + bool beginning = this->ContinuingExecution == false; + bool end = true; + + this->ContinuingExecution = false; + this->CurrentPiece = beginning ? this->StartPiece : this->CurrentPiece; + + assert(this->CurrentPiece >= this->StartPiece && this->CurrentPiece <= this->EndPiece); + end = this->CurrentPiece == this->EndPiece; + + if (beginning) + { + // Prepare the file name. + this->SplitFileName(); + delete[] this->PieceWrittenFlags; + this->PieceWrittenFlags = new unsigned char[this->NumberOfPieces]; + memset(this->PieceWrittenFlags, 0, sizeof(unsigned char) * this->NumberOfPieces); + + // Prepare the extension. + this->SetupPieceFileNameExtension(); + } + + // Write the current piece. + + // Split progress range by piece. Just assume all pieces are the + // same size. + float progressRange[2] = { 0.f, 0.f }; + this->GetProgressRange(progressRange); + + this->SetProgressRange( + progressRange, this->CurrentPiece - this->StartPiece, this->EndPiece - this->StartPiece + 1); + + if (!this->WritePieceInternal()) + { + return 0; + } + + // Write the summary file if requested. + if (end && this->WriteSummaryFile) + { + // Decide whether to write the summary file. + bool writeSummaryLocally = + (this->Controller == nullptr || this->Controller->GetLocalProcessId() == 0); + + // Let subclasses collect information, if any to write the summary file. + this->PrepareSummaryFile(); + + if (writeSummaryLocally) + { + if (!this->Superclass::WriteInternal()) + { + vtkErrorMacro("Ran out of disk space; deleting file(s) already written"); + this->DeleteFiles(); + return 0; + } + } + } + + if (end == false) + { + this->CurrentPiece++; + assert(this->CurrentPiece <= this->EndPiece); + this->ContinuingExecution = true; + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataObjectWriter::PrepareSummaryFile() +{ + if (this->Controller && this->Controller->GetNumberOfProcesses() > 1) + { + assert(this->PieceWrittenFlags != nullptr); + // Reduce information about which pieces were written out to rank 0. + int myId = this->Controller->GetLocalProcessId(); + unsigned char* recvBuffer = (myId == 0) ? new unsigned char[this->NumberOfPieces] : nullptr; + this->Controller->Reduce( + this->PieceWrittenFlags, recvBuffer, this->NumberOfPieces, vtkCommunicator::MAX_OP, 0); + if (myId == 0) + { + std::swap(this->PieceWrittenFlags, recvBuffer); + } + delete[] recvBuffer; + } +} + +//---------------------------------------------------------------------------- +int vtkXMLPDataObjectWriter::WriteData() +{ + // Write the summary file. + ostream& os = *(this->Stream); + vtkIndent indent = vtkIndent().GetNextIndent(); + vtkIndent nextIndent = indent.GetNextIndent(); + + this->StartFile(); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + + os << indent << "<" << this->GetDataSetName(); + this->WritePrimaryElementAttributes(os, indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + os << ">\n"; + + // Write the information needed for a reader to produce the output's + // information during UpdateInformation without reading a piece. + this->WritePData(indent.GetNextIndent()); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + + // Write the elements referencing each piece and its file. + for (int i = 0; i < this->NumberOfPieces; ++i) + { + if (this->PieceWrittenFlags[i] == 0) + { + continue; + } + os << nextIndent << "<Piece"; + this->WritePPieceAttributes(i); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) + { + return 0; + } + os << "/>\n"; + } + + os << indent << "</" << this->GetDataSetName() << ">\n"; + + this->EndFile(); + return (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) ? 0 : 1; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataObjectWriter::WritePPieceAttributes(int index) +{ + char* fileName = this->CreatePieceFileName(index); + this->WriteStringAttribute("Source", fileName); + delete[] fileName; +} + +//---------------------------------------------------------------------------- +char* vtkXMLPDataObjectWriter::CreatePieceFileName(int index, const char* path) +{ + std::ostringstream s; + if (path) + { + s << path; + } + s << this->FileNameBase; + if (this->UseSubdirectory) + { + s << "/" << this->FileNameBase; + } + s << "_" << index; + if (this->PieceFileNameExtension) + { + s << this->PieceFileNameExtension; + } + + size_t len = s.str().length(); + char* buffer = new char[len + 1]; + strncpy(buffer, s.str().c_str(), len); + buffer[len] = '\0'; + + return buffer; +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataObjectWriter::SplitFileName() +{ + // Split the FileName into its PathName, FileNameBase, and + // FileNameExtension components. + + std::string pathname = vtksys::SystemTools::GetProgramPath(this->FileName); + // Pathname may be empty if FileName is simply a filename without any leading + // "/". + if (!pathname.empty()) + { + pathname += "/"; + } + std::string filename_wo_ext = vtksys::SystemTools::GetFilenameWithoutExtension(this->FileName); + std::string ext = vtksys::SystemTools::GetFilenameExtension(this->FileName); + + delete[] this->PathName; + delete[] this->FileNameBase; + delete[] this->FileNameExtension; + + this->PathName = vtksys::SystemTools::DuplicateString(pathname.c_str()); + this->FileNameBase = vtksys::SystemTools::DuplicateString(filename_wo_ext.c_str()); + this->FileNameExtension = vtksys::SystemTools::DuplicateString(ext.c_str()); +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataObjectWriter::ProgressCallbackFunction( + vtkObject* caller, unsigned long, void* clientdata, void*) +{ + vtkAlgorithm* w = vtkAlgorithm::SafeDownCast(caller); + if (w) + { + reinterpret_cast<vtkXMLPDataObjectWriter*>(clientdata)->ProgressCallback(w); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataObjectWriter::ProgressCallback(vtkAlgorithm* w) +{ + float width = this->ProgressRange[1] - this->ProgressRange[0]; + float internalProgress = w->GetProgress(); + float progress = this->ProgressRange[0] + internalProgress * width; + this->UpdateProgressDiscrete(progress); + if (this->AbortExecute) + { + w->SetAbortExecute(1); + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataObjectWriter::DeleteFiles() +{ + for (int i = this->StartPiece; i < this->EndPiece; ++i) + { + char* fileName = this->CreatePieceFileName(i, this->PathName); + this->DeleteAFile(fileName); + delete[] fileName; + } +} + +//---------------------------------------------------------------------------- +void vtkXMLPDataObjectWriter::SetupPieceFileNameExtension() +{ + delete[] this->PieceFileNameExtension; +} diff --git a/IO/ParallelXML/vtkXMLPDataObjectWriter.h b/IO/ParallelXML/vtkXMLPDataObjectWriter.h new file mode 100644 index 0000000000000000000000000000000000000000..e2518b828dc38f026dc868414412aa75432cfb48 --- /dev/null +++ b/IO/ParallelXML/vtkXMLPDataObjectWriter.h @@ -0,0 +1,234 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkXMLPDataObjectWriter.h + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm 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. + +=========================================================================*/ +/** + * @class vtkXMLPDataObjectWriter + * @brief Write data in a parallel XML format. + * + * vtkXMLPDataWriter is the superclass for all XML parallel data object + * writers. It provides functionality needed for writing parallel + * formats, such as the selection of which writer writes the summary + * file and what range of pieces are assigned to each serial writer. + * + * @sa + * vtkXMLDataObjectWriter +*/ + +#ifndef vtkXMLPDataObjectWriter_h +#define vtkXMLPDataObjectWriter_h + +#include "vtkIOParallelXMLModule.h" // For export macro +#include "vtkXMLWriter.h" + +class vtkCallbackCommand; +class vtkMultiProcessController; + +class VTKIOPARALLELXML_EXPORT vtkXMLPDataObjectWriter : public vtkXMLWriter +{ +public: + vtkTypeMacro(vtkXMLPDataObjectWriter, vtkXMLWriter); + void PrintSelf(ostream& os, vtkIndent indent) VTK_OVERRIDE; + + //@{ + /** + * Get/Set the number of pieces that are being written in parallel. + */ + vtkSetMacro(NumberOfPieces, int); + vtkGetMacro(NumberOfPieces, int); + //@} + + //@{ + /** + * Get/Set the range of pieces assigned to this writer. + */ + vtkSetMacro(StartPiece, int); + vtkGetMacro(StartPiece, int); + vtkSetMacro(EndPiece, int); + vtkGetMacro(EndPiece, int); + //@} + + //@{ + /** + * Get/Set the ghost level used for this writer's piece. + */ + vtkSetMacro(GhostLevel, int); + vtkGetMacro(GhostLevel, int); + //@} + + //@{ + /** + * Get/Set whether to use a subdirectory to store the pieces + */ + vtkSetMacro(UseSubdirectory, bool); + vtkGetMacro(UseSubdirectory, bool); + //@} + + //@{ + /** + * Get/Set whether the writer should write the summary file that + * refers to all of the pieces' individual files. + * This is on by default. Note that only the first process writes + * the summary file. + */ + virtual void SetWriteSummaryFile(int flag); + vtkGetMacro(WriteSummaryFile, int); + vtkBooleanMacro(WriteSummaryFile, int); + //@} + + //@{ + /** + * Controller used to communicate data type of blocks. + * By default, the global controller is used. If you want another + * controller to be used, set it with this. + */ + virtual void SetController(vtkMultiProcessController*); + vtkGetObjectMacro(Controller, vtkMultiProcessController); + //@} + + /** + * Overridden to handle passing the CONTINUE_EXECUTING() flags to the + * executive. + */ + int ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector, + vtkInformationVector* outputVector) VTK_OVERRIDE; + +protected: + vtkXMLPDataObjectWriter(); + ~vtkXMLPDataObjectWriter() VTK_OVERRIDE; + + /** + * Override writing method from superclass. + */ + int WriteInternal() VTK_OVERRIDE; + + /** + * Write data from the input dataset. Call WritePData(vtkIndent indent) + */ + int WriteData() VTK_OVERRIDE; + + /** + * Write Data associated with the input dataset. It needs to be overriden by subclass + */ + virtual void WritePData(vtkIndent indent) = 0; + + /** + * Write a piece of the dataset on disk. Called by WritePieceInternal(). + * It needs to be overriden by subclass + */ + virtual int WritePiece(int index) = 0; + + /** + * Method called by WriteInternal(). It's used for writing a piece of the dataset. + * It needs to be overriden by subclass. + */ + virtual int WritePieceInternal() = 0; + + /** + * Overridden to make appropriate piece request from upstream. + */ + virtual int RequestUpdateExtent(vtkInformation* request, vtkInformationVector** inputVector, + vtkInformationVector* outputVector); + + /** + * Collect information between ranks before writing the summary file. + * This method is called on all ranks while summary file is only written on 1 + * rank (rank 0). + */ + virtual void PrepareSummaryFile(); + + /** + * Write the attributes of the piece at the given index + */ + virtual void WritePPieceAttributes(int index); + + //@{ + /** + * Methods for creating a filename for each piece in the dataset + */ + char* CreatePieceFileName(int index, const char* path = nullptr); + void SplitFileName(); + //@} + + /** + * Callback registered with the InternalProgressObserver. + */ + static void ProgressCallbackFunction(vtkObject*, unsigned long, void*, void*); + + /** + * Valid at end of WriteInternal to indicate if we're going to continue + * execution. + */ + vtkGetMacro(ContinuingExecution, bool); + + /** + * Get the current piece to write + */ + vtkGetMacro(CurrentPiece, int); + + /** + * Progress callback from internal writer. + */ + virtual void ProgressCallback(vtkAlgorithm* w); + + /** + * Method used to delete all written files. + */ + void DeleteFiles(); + + /** + * The observer to report progress from the internal writer. + */ + vtkCallbackCommand* InternalProgressObserver; + + vtkMultiProcessController* Controller; + + int StartPiece; + int EndPiece; + int NumberOfPieces; + int GhostLevel; + int WriteSummaryFile; + bool UseSubdirectory; + + char* PathName; + char* FileNameBase; + char* FileNameExtension; + char* PieceFileNameExtension; + + /** + * Flags used to keep track of which pieces were written out. + */ + unsigned char* PieceWrittenFlags; + + /** + * Initializes PieceFileNameExtension. + */ + virtual void SetupPieceFileNameExtension(); + +private: + vtkXMLPDataObjectWriter(const vtkXMLPDataObjectWriter&) VTK_DELETE_FUNCTION; + void operator=(const vtkXMLPDataObjectWriter&) VTK_DELETE_FUNCTION; + + /** + * Indicates the piece currently being written. + */ + int CurrentPiece; + + /** + * Set in WriteInternal() to request continued execution from the executive to + * write more pieces. + */ + bool ContinuingExecution; +}; + +#endif diff --git a/IO/ParallelXML/vtkXMLPDataWriter.cxx b/IO/ParallelXML/vtkXMLPDataWriter.cxx index 7ee4414e472e8b1972ce4b2b22ef33208b495330..ceaa68e86ff164d250a16aaf2e39097e5a637615 100644 --- a/IO/ParallelXML/vtkXMLPDataWriter.cxx +++ b/IO/ParallelXML/vtkXMLPDataWriter.cxx @@ -17,369 +17,58 @@ #include "vtkCallbackCommand.h" #include "vtkDataSet.h" #include "vtkErrorCode.h" -#include "vtkInformation.h" -#include "vtkInformationVector.h" -#include "vtkMultiProcessController.h" #include "vtkStreamingDemandDrivenPipeline.h" -#include <algorithm> -#include <cassert> -#include <sstream> #include <vtksys/SystemTools.hxx> -vtkCxxSetObjectMacro(vtkXMLPDataWriter, Controller, vtkMultiProcessController); //---------------------------------------------------------------------------- vtkXMLPDataWriter::vtkXMLPDataWriter() { - this->StartPiece = 0; - this->EndPiece = 0; - this->NumberOfPieces = 1; - this->GhostLevel = 0; - this->WriteSummaryFile = 1; - - this->UseSubdirectory = false; - - this->PathName = nullptr; - this->FileNameBase = nullptr; - this->FileNameExtension = nullptr; - this->PieceFileNameExtension = nullptr; - - // Setup a callback for the internal writer to report progress. - this->InternalProgressObserver = vtkCallbackCommand::New(); - this->InternalProgressObserver->SetCallback( - &vtkXMLPDataWriter::ProgressCallbackFunction); - this->InternalProgressObserver->SetClientData(this); - - this->Controller = nullptr; - this->SetController(vtkMultiProcessController::GetGlobalController()); - - this->ContinuingExecution = false; - this->CurrentPiece = -1; - this->PieceWrittenFlags = nullptr; } //---------------------------------------------------------------------------- vtkXMLPDataWriter::~vtkXMLPDataWriter() { - delete [] this->PathName; - delete [] this->FileNameBase; - delete [] this->FileNameExtension; - delete [] this->PieceFileNameExtension; - delete [] this->PieceWrittenFlags; - this->SetController(nullptr); - this->InternalProgressObserver->Delete(); } //---------------------------------------------------------------------------- void vtkXMLPDataWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); - os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n"; - os << indent << "StartPiece: " << this->StartPiece << "\n"; - os << indent << "EndPiece: " << this->EndPiece << "\n"; - os << indent << "GhostLevel: " << this->GhostLevel << "\n"; - os << indent << "WriteSummaryFile: " << this->WriteSummaryFile << "\n"; -} - -//---------------------------------------------------------------------------- -int vtkXMLPDataWriter::ProcessRequest(vtkInformation* request, - vtkInformationVector** inputVector, - vtkInformationVector* outputVector) -{ - if (request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) - { - return this->RequestUpdateExtent(request, inputVector, outputVector); - } - - int retVal = this->Superclass::ProcessRequest(request, inputVector, outputVector); - if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) - { - if (retVal && this->ContinuingExecution) - { - request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1); - } - else - { - request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING()); - this->ContinuingExecution = false; - } - } - return retVal; } //---------------------------------------------------------------------------- -int vtkXMLPDataWriter::RequestUpdateExtent(vtkInformation *vtkNotUsed(request), - vtkInformationVector **inputVector, vtkInformationVector *vtkNotUsed(outputVector)) -{ - vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); - int piece = 0; - if (this->ContinuingExecution) - { - assert(this->CurrentPiece >= this->StartPiece && - this->CurrentPiece <= this->EndPiece && - this->CurrentPiece < this->NumberOfPieces); - piece = this->CurrentPiece; - } - else - { - piece = this->StartPiece; - } - - inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), piece); - inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), - this->GetNumberOfPieces()); - inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), - this->GhostLevel); - return 1; -} - -//---------------------------------------------------------------------------- -void vtkXMLPDataWriter::SetWriteSummaryFile(int flag) +void vtkXMLPDataWriter::WritePData(vtkIndent indent) { - vtkDebugMacro(<< this->GetClassName() << " (" - << this << "): setting WriteSummaryFile to " << flag); - if (this->WriteSummaryFile != flag) + vtkDataSet* input = this->GetInputAsDataSet(); + this->WritePPointData(input->GetPointData(), indent); + if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) { - this->WriteSummaryFile = flag; - this->Modified(); + return; } + this->WritePCellData(input->GetCellData(), indent); } //---------------------------------------------------------------------------- -int vtkXMLPDataWriter::WriteInternal() +int vtkXMLPDataWriter::WritePieceInternal() { - bool the_beginning = (this->ContinuingExecution == false); - bool the_end = true; - - this->ContinuingExecution = false; - this->CurrentPiece = the_beginning? this->StartPiece : this->CurrentPiece; - - assert(this->CurrentPiece >= this->StartPiece && this->CurrentPiece <= this->EndPiece); - the_end = (this->CurrentPiece == this->EndPiece); + int piece = this->GetCurrentPiece(); - if (the_beginning) - { - // Prepare the file name. - this->SplitFileName(); - delete [] this->PieceWrittenFlags; - this->PieceWrittenFlags = new unsigned char[this->NumberOfPieces]; - memset(this->PieceWrittenFlags, 0, sizeof(unsigned char)*this->NumberOfPieces); - - // Prepare the extension. - this->SetupPieceFileNameExtension(); - } - - // Write the current piece. - - // Split progress range by piece. Just assume all pieces are the - // same size. - float progressRange[2] = { 0.f, 0.f }; - this->GetProgressRange(progressRange); - - this->SetProgressRange(progressRange, this->CurrentPiece - this->StartPiece, - this->EndPiece - this->StartPiece + 1); vtkDataSet* inputDS = this->GetInputAsDataSet(); if (inputDS && (inputDS->GetNumberOfPoints() > 0 || inputDS->GetNumberOfCells() > 0)) { - if (!this->WritePiece(this->CurrentPiece)) + if (!this->WritePiece(piece)) { vtkErrorMacro("Ran out of disk space; deleting file(s) already written"); this->DeleteFiles(); return 0; } - this->PieceWrittenFlags[this->CurrentPiece] = static_cast<unsigned char>(0x1); - } - - // Write the summary file if requested. - if (the_end && this->WriteSummaryFile) - { - // Decide whether to write the summary file. - bool writeSummaryLocally = (this->Controller == nullptr || this->Controller->GetLocalProcessId() == 0); - - // Let subclasses collect information, if any to write the summary file. - this->PrepareSummaryFile(); - - if (writeSummaryLocally) - { - if (!this->Superclass::WriteInternal()) - { - vtkErrorMacro("Ran out of disk space; deleting file(s) already written"); - this->DeleteFiles(); - return 0; - } - } + this->PieceWrittenFlags[piece] = static_cast<unsigned char>(0x1); } - if (the_end == false) - { - this->CurrentPiece++; - assert(this->CurrentPiece <= this->EndPiece); - this->ContinuingExecution = true; - } return 1; } -//---------------------------------------------------------------------------- -void vtkXMLPDataWriter::DeleteFiles() -{ - for (int i = this->StartPiece; i < this->EndPiece; ++i) - { - char* fileName = this->CreatePieceFileName(i, this->PathName); - this->DeleteAFile(fileName); - delete [] fileName; - } -} - -//---------------------------------------------------------------------------- -void vtkXMLPDataWriter::PrepareSummaryFile() -{ - if (this->Controller && this->Controller->GetNumberOfProcesses() > 1) - { - assert(this->PieceWrittenFlags != nullptr); - // Reduce information about which pieces were written out to rank 0. - int myId = this->Controller->GetLocalProcessId(); - unsigned char* recvBuffer = (myId == 0)? new unsigned char[this->NumberOfPieces] : nullptr; - this->Controller->Reduce( - this->PieceWrittenFlags, recvBuffer, this->NumberOfPieces, - vtkCommunicator::MAX_OP, 0); - if (myId == 0) - { - std::swap(this->PieceWrittenFlags, recvBuffer); - } - delete [] recvBuffer; - } -} - -//---------------------------------------------------------------------------- -void vtkXMLPDataWriter::WritePrimaryElementAttributes(ostream &, vtkIndent) -{ - this->WriteScalarAttribute("GhostLevel", this->GhostLevel); -} - -//---------------------------------------------------------------------------- -int vtkXMLPDataWriter::WriteData() -{ - // Write the summary file. - ostream& os = *(this->Stream); - vtkIndent indent = vtkIndent().GetNextIndent(); - vtkIndent nextIndent = indent.GetNextIndent(); - - this->StartFile(); - if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) - { - return 0; - } - - os << indent << "<" << this->GetDataSetName(); - this->WritePrimaryElementAttributes(os, indent); - if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) - { - return 0; - } - os << ">\n"; - - // Write the information needed for a reader to produce the output's - // information during UpdateInformation without reading a piece. - this->WritePData(indent.GetNextIndent()); - if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) - { - return 0; - } - - // Write the elements referencing each piece and its file. - for (int i = 0; i < this->NumberOfPieces; ++i) - { - if (this->PieceWrittenFlags[i] == 0) - { - continue; - } - os << nextIndent << "<Piece"; - this->WritePPieceAttributes(i); - if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) - { - return 0; - } - os << "/>\n"; - } - - os << indent << "</" << this->GetDataSetName() << ">\n"; - - this->EndFile(); - return (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) ? 0 : 1; -} - -//---------------------------------------------------------------------------- -void vtkXMLPDataWriter::WritePData(vtkIndent indent) -{ - vtkDataSet* input = this->GetInputAsDataSet(); - this->WritePPointData(input->GetPointData(), indent); - if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) - { - return; - } - this->WritePCellData(input->GetCellData(), indent); -} - -//---------------------------------------------------------------------------- -void vtkXMLPDataWriter::WritePPieceAttributes(int index) -{ - char* fileName = this->CreatePieceFileName(index); - this->WriteStringAttribute("Source", fileName); - delete [] fileName; -} - -//---------------------------------------------------------------------------- -void vtkXMLPDataWriter::SplitFileName() -{ - // Split the FileName into its PathName, FileNameBase, and - // FileNameExtension components. - - std::string pathname = vtksys::SystemTools::GetProgramPath(this->FileName); - // Pathname may be empty if FileName is simply a filename without any leading - // "/". - if (!pathname.empty()) - { - pathname += "/"; - } - std::string filename_wo_ext = vtksys::SystemTools::GetFilenameWithoutExtension(this->FileName); - std::string ext = vtksys::SystemTools::GetFilenameExtension(this->FileName); - - delete [] this->PathName; - delete [] this->FileNameBase; - delete [] this->FileNameExtension; - - this->PathName = vtksys::SystemTools::DuplicateString(pathname.c_str()); - this->FileNameBase = vtksys::SystemTools::DuplicateString(filename_wo_ext.c_str()); - this->FileNameExtension = vtksys::SystemTools::DuplicateString(ext.c_str()); -} - -//---------------------------------------------------------------------------- -char* vtkXMLPDataWriter::CreatePieceFileName(int index, const char* path) -{ - std::ostringstream s; - if (path) - { - s << path; - } - s << this->FileNameBase; - if (this->UseSubdirectory) - { - s << "/" << this->FileNameBase; - } - s << "_" << index; - if (this->PieceFileNameExtension) - { - s << this->PieceFileNameExtension; - } - - size_t len = s.str().length(); - char *buffer = new char[len + 1]; - strncpy(buffer, s.str().c_str(), len); - buffer[len] = '\0'; - - return buffer; -} - //---------------------------------------------------------------------------- int vtkXMLPDataWriter::WritePiece(int index) { @@ -395,7 +84,7 @@ int vtkXMLPDataWriter::WritePiece(int index) vtksys::SystemTools::MakeDirectory(path); } pWriter->SetFileName(fileName); - delete [] fileName; + delete[] fileName; // Copy the writer settings. pWriter->SetDebug(this->Debug); @@ -418,40 +107,21 @@ int vtkXMLPDataWriter::WritePiece(int index) } //---------------------------------------------------------------------------- -void vtkXMLPDataWriter::ProgressCallbackFunction(vtkObject* caller, - unsigned long, - void* clientdata, void*) +void vtkXMLPDataWriter::WritePrimaryElementAttributes(std::ostream& vtkNotUsed(os), vtkIndent vtkNotUsed(indent)) { - vtkAlgorithm* w = vtkAlgorithm::SafeDownCast(caller); - if(w) - { - reinterpret_cast<vtkXMLPDataWriter*>(clientdata)->ProgressCallback(w); - } -} - -//---------------------------------------------------------------------------- -void vtkXMLPDataWriter::ProgressCallback(vtkAlgorithm* w) -{ - float width = this->ProgressRange[1]-this->ProgressRange[0]; - float internalProgress = w->GetProgress(); - float progress = this->ProgressRange[0] + internalProgress*width; - this->UpdateProgressDiscrete(progress); - if(this->AbortExecute) - { - w->SetAbortExecute(1); - } + this->WriteScalarAttribute("GhostLevel", this->GhostLevel); } //---------------------------------------------------------------------------- void vtkXMLPDataWriter::SetupPieceFileNameExtension() { - delete [] this->PieceFileNameExtension; + this->Superclass::SetupPieceFileNameExtension(); // Create a temporary piece writer and then initialize the extension. vtkXMLWriter* writer = this->CreatePieceWriter(0); const char* ext = writer->GetDefaultFileExtension(); - this->PieceFileNameExtension = new char[strlen(ext)+2]; + this->PieceFileNameExtension = new char[strlen(ext) + 2]; this->PieceFileNameExtension[0] = '.'; - strcpy(this->PieceFileNameExtension+1, ext); + strcpy(this->PieceFileNameExtension + 1, ext); writer->Delete(); } diff --git a/IO/ParallelXML/vtkXMLPDataWriter.h b/IO/ParallelXML/vtkXMLPDataWriter.h index a09465b240bd93cd0530ff5b6e5bc8f00970abe7..b2dd3919a4e98db2cc9ee425414d58fe6ac69968 100644 --- a/IO/ParallelXML/vtkXMLPDataWriter.h +++ b/IO/ParallelXML/vtkXMLPDataWriter.h @@ -26,162 +26,39 @@ #define vtkXMLPDataWriter_h #include "vtkIOParallelXMLModule.h" // For export macro -#include "vtkXMLWriter.h" +#include "vtkXMLPDataObjectWriter.h" class vtkCallbackCommand; class vtkMultiProcessController; -class VTKIOPARALLELXML_EXPORT vtkXMLPDataWriter : public vtkXMLWriter +class VTKIOPARALLELXML_EXPORT vtkXMLPDataWriter : public vtkXMLPDataObjectWriter { public: - vtkTypeMacro(vtkXMLPDataWriter,vtkXMLWriter); + vtkTypeMacro(vtkXMLPDataWriter, vtkXMLPDataObjectWriter); void PrintSelf(ostream& os, vtkIndent indent) VTK_OVERRIDE; - //@{ - /** - * Get/Set the number of pieces that are being written in parallel. - */ - vtkSetMacro(NumberOfPieces, int); - vtkGetMacro(NumberOfPieces, int); - //@} - - //@{ - /** - * Get/Set the range of pieces assigned to this writer. - */ - vtkSetMacro(StartPiece, int); - vtkGetMacro(StartPiece, int); - vtkSetMacro(EndPiece, int); - vtkGetMacro(EndPiece, int); - //@} - - //@{ - /** - * Get/Set the ghost level used for this writer's piece. - */ - vtkSetMacro(GhostLevel, int); - vtkGetMacro(GhostLevel, int); - //@} - - //@{ - /** - * Get/Set whether to use a subdirectory to store the pieces - */ - vtkSetMacro(UseSubdirectory, bool); - vtkGetMacro(UseSubdirectory, bool); - //@} - - //@{ - /** - * Get/Set whether the writer should write the summary file that - * refers to all of the pieces' individual files. - * This is on by default. Note that only the first process writes - * the summary file. - */ - virtual void SetWriteSummaryFile(int flag); - vtkGetMacro(WriteSummaryFile, int); - vtkBooleanMacro(WriteSummaryFile, int); - //@} - - //@{ - /** - * Controller used to communicate data type of blocks. - * By default, the global controller is used. If you want another - * controller to be used, set it with this. - */ - virtual void SetController(vtkMultiProcessController*); - vtkGetObjectMacro(Controller, vtkMultiProcessController); - //@} - - - /** - * Overridden to handle passing the CONTINUE_EXECUTING() flags to the - * executive. - */ - int ProcessRequest(vtkInformation* request, - vtkInformationVector** inputVector, vtkInformationVector* outputVector) VTK_OVERRIDE; - protected: vtkXMLPDataWriter(); ~vtkXMLPDataWriter() VTK_OVERRIDE; - /** - * Overridden to make appropriate piece request from upstream. - */ - virtual int RequestUpdateExtent(vtkInformation *request, - vtkInformationVector **inputVector, vtkInformationVector *outputVector); - - // Override writing method from superclass. - int WriteInternal() VTK_OVERRIDE; - - // Subclasses can override this method to collect information between ranks - // before writing the summary file. This method is called on all ranks while - // summary file is only written on 1 rank (rank 0). - virtual void PrepareSummaryFile(); - - virtual vtkXMLWriter* CreatePieceWriter(int index)=0; - - void WritePrimaryElementAttributes(ostream &os, vtkIndent indent) VTK_OVERRIDE; - int WriteData() VTK_OVERRIDE; - virtual void WritePData(vtkIndent indent); - virtual void WritePPieceAttributes(int index); - - char* CreatePieceFileName(int index, const char* path=nullptr); - void SplitFileName(); - virtual int WritePiece(int index); - - // Callback registered with the InternalProgressObserver. - static void ProgressCallbackFunction(vtkObject*, unsigned long, void*, - void*); - // Progress callback from internal writer. - virtual void ProgressCallback(vtkAlgorithm* w); + virtual vtkXMLWriter* CreatePieceWriter(int index) = 0; - int StartPiece; - int EndPiece; - int NumberOfPieces; - int GhostLevel; - int WriteSummaryFile; - bool UseSubdirectory; + virtual void WritePData(vtkIndent indent) VTK_OVERRIDE; - char* PathName; - char* FileNameBase; - char* FileNameExtension; - char* PieceFileNameExtension; + virtual int WritePieceInternal() VTK_OVERRIDE; - // The observer to report progress from the internal writer. - vtkCallbackCommand* InternalProgressObserver; + virtual int WritePiece(int index) VTK_OVERRIDE; - vtkMultiProcessController* Controller; - - /** - * Valid at end of WriteInternal to indicate if we're going to continue - * execution. - */ - vtkGetMacro(ContinuingExecution, bool); + void WritePrimaryElementAttributes(ostream& os, vtkIndent indent) VTK_OVERRIDE; private: vtkXMLPDataWriter(const vtkXMLPDataWriter&) VTK_DELETE_FUNCTION; void operator=(const vtkXMLPDataWriter&) VTK_DELETE_FUNCTION; - /** - * Method used to delete all written files. - */ - void DeleteFiles(); - /** * Initializes PieceFileNameExtension. */ - void SetupPieceFileNameExtension(); - - // Indicates the piece currently being written. - int CurrentPiece; - - // Set in WriteInternal() to request continued execution from the executive to - // write more pieces. - bool ContinuingExecution; - - // Flags used to keep track of which pieces were written out. - unsigned char *PieceWrittenFlags; + void SetupPieceFileNameExtension() VTK_OVERRIDE; }; #endif diff --git a/IO/ParallelXML/vtkXMLPTableWriter.cxx b/IO/ParallelXML/vtkXMLPTableWriter.cxx index 22d6b294d41ef8f28720c9526146d79579f5649c..5111d99b1f96f7fcfc98f238e3bfa2f2fb06cebc 100644 --- a/IO/ParallelXML/vtkXMLPTableWriter.cxx +++ b/IO/ParallelXML/vtkXMLPTableWriter.cxx @@ -19,9 +19,7 @@ #include "vtkErrorCode.h" #include "vtkInformation.h" #include "vtkInformationVector.h" -#include "vtkMultiProcessController.h" #include "vtkObjectFactory.h" -#include "vtkStreamingDemandDrivenPipeline.h" #include "vtkTable.h" #include "vtkXMLTableWriter.h" @@ -30,58 +28,21 @@ #include <cassert> vtkStandardNewMacro(vtkXMLPTableWriter); -vtkCxxSetObjectMacro(vtkXMLPTableWriter, Controller, vtkMultiProcessController); //---------------------------------------------------------------------------- vtkXMLPTableWriter::vtkXMLPTableWriter() { - this->StartPiece = 0; - this->EndPiece = 0; - this->NumberOfPieces = 1; - this->GhostLevel = 0; - this->WriteSummaryFile = 1; - - this->UseSubdirectory = false; - - this->PathName = nullptr; - this->FileNameBase = nullptr; - this->FileNameExtension = nullptr; - this->PieceFileNameExtension = nullptr; - - // Setup a callback for the internal writer to report progress. - this->InternalProgressObserver = vtkCallbackCommand::New(); - this->InternalProgressObserver->SetCallback(&vtkXMLPTableWriter::ProgressCallbackFunction); - this->InternalProgressObserver->SetClientData(this); - - this->Controller = nullptr; - this->SetController(vtkMultiProcessController::GetGlobalController()); - - this->ContinuingExecution = false; - this->CurrentPiece = -1; - this->PieceWrittenFlags = nullptr; } //---------------------------------------------------------------------------- vtkXMLPTableWriter::~vtkXMLPTableWriter() { - delete[] this->PathName; - delete[] this->FileNameBase; - delete[] this->FileNameExtension; - delete[] this->PieceFileNameExtension; - delete[] this->PieceWrittenFlags; - this->SetController(nullptr); - this->InternalProgressObserver->Delete(); } //---------------------------------------------------------------------------- void vtkXMLPTableWriter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); - os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n"; - os << indent << "StartPiece: " << this->StartPiece << "\n"; - os << indent << "EndPiece: " << this->EndPiece << "\n"; - os << indent << "GhostLevel: " << this->GhostLevel << "\n"; - os << indent << "WriteSummaryFile: " << this->WriteSummaryFile << "\n"; } //---------------------------------------------------------------------------- @@ -90,31 +51,6 @@ vtkTable* vtkXMLPTableWriter::GetInput() return vtkTable::SafeDownCast(this->Superclass::GetInput()); } -//---------------------------------------------------------------------------- -int vtkXMLPTableWriter::ProcessRequest( - vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector) -{ - if (request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT())) - { - return this->RequestUpdateExtent(request, inputVector, outputVector); - } - - int retVal = this->Superclass::ProcessRequest(request, inputVector, outputVector); - if (request->Has(vtkDemandDrivenPipeline::REQUEST_DATA())) - { - if (retVal && this->ContinuingExecution) - { - request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1); - } - else - { - request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING()); - this->ContinuingExecution = false; - } - } - return retVal; -} - //---------------------------------------------------------------------------- const char* vtkXMLPTableWriter::GetDataSetName() { @@ -127,18 +63,6 @@ const char* vtkXMLPTableWriter::GetDefaultFileExtension() return "pvtt"; } -//---------------------------------------------------------------------------- -void vtkXMLPTableWriter::SetWriteSummaryFile(int flag) -{ - vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting WriteSummaryFile to " - << flag); - if (this->WriteSummaryFile != flag) - { - this->WriteSummaryFile = flag; - this->Modified(); - } -} - //---------------------------------------------------------------------------- vtkXMLWriter* vtkXMLPTableWriter::CreatePieceWriter(int index) { @@ -159,241 +83,24 @@ void vtkXMLPTableWriter::WritePData(vtkIndent indent) } //---------------------------------------------------------------------------- -int vtkXMLPTableWriter::RequestUpdateExtent(vtkInformation* vtkNotUsed(request), - vtkInformationVector** inputVector, vtkInformationVector* vtkNotUsed(outputVector)) -{ - vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); - int piece = 0; - if (this->ContinuingExecution) - { - assert(this->CurrentPiece >= this->StartPiece && this->CurrentPiece <= this->EndPiece && - this->CurrentPiece < this->NumberOfPieces); - piece = this->CurrentPiece; - } - else - { - piece = this->StartPiece; - } - - inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), piece); - inInfo->Set( - vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), this->GetNumberOfPieces()); - inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), this->GhostLevel); - return 1; -} - -//---------------------------------------------------------------------------- -int vtkXMLPTableWriter::WriteInternal() +int vtkXMLPTableWriter::WritePieceInternal() { - bool beginning = (this->ContinuingExecution == false); - bool end = true; - - this->ContinuingExecution = false; - this->CurrentPiece = beginning ? this->StartPiece : this->CurrentPiece; - - assert(this->CurrentPiece >= this->StartPiece && this->CurrentPiece <= this->EndPiece); - end = (this->CurrentPiece == this->EndPiece); - - if (beginning) - { - // Prepare the file name. - this->SplitFileName(); - delete[] this->PieceWrittenFlags; - this->PieceWrittenFlags = new unsigned char[this->NumberOfPieces]; - memset(this->PieceWrittenFlags, 0, sizeof(unsigned char) * this->NumberOfPieces); - - // Prepare the extension. - this->SetupPieceFileNameExtension(); - } - - // Write the current piece. - - // Split progress range by piece. Just assume all pieces are the - // same size. - float progressRange[2] = { 0.f, 0.f }; - this->GetProgressRange(progressRange); - - this->SetProgressRange( - progressRange, this->CurrentPiece - this->StartPiece, this->EndPiece - this->StartPiece + 1); + int piece = this->GetCurrentPiece(); vtkTable* inputTable = this->GetInput(); if (inputTable && inputTable->GetNumberOfRows() > 0) { - if (!this->WritePiece(this->CurrentPiece)) + if (!this->WritePiece(piece)) { vtkErrorMacro("Could not write the current piece."); this->DeleteFiles(); return 0; } - this->PieceWrittenFlags[this->CurrentPiece] = static_cast<unsigned char>(0x1); - } - - // Write the summary file if requested. - if (end && this->WriteSummaryFile) - { - // Decide whether to write the summary file. - bool writeSummaryLocally = - (this->Controller == nullptr || this->Controller->GetLocalProcessId() == 0); - - // Let subclasses collect information, if any to write the summary file. - this->PrepareSummaryFile(); - - if (writeSummaryLocally) - { - if (!this->Superclass::WriteInternal()) - { - vtkErrorMacro("Ran out of disk space; deleting file(s) already written"); - this->DeleteFiles(); - return 0; - } - } + this->PieceWrittenFlags[piece] = static_cast<unsigned char>(0x1); } - if (end == false) - { - this->CurrentPiece++; - assert(this->CurrentPiece <= this->EndPiece); - this->ContinuingExecution = true; - } return 1; } -//---------------------------------------------------------------------------- -void vtkXMLPTableWriter::PrepareSummaryFile() -{ - if (this->Controller && this->Controller->GetNumberOfProcesses() > 1) - { - assert(this->PieceWrittenFlags != nullptr); - // Reduce information about which pieces were written out to rank 0. - int myId = this->Controller->GetLocalProcessId(); - unsigned char* recvBuffer = (myId == 0) ? new unsigned char[this->NumberOfPieces] : nullptr; - this->Controller->Reduce( - this->PieceWrittenFlags, recvBuffer, this->NumberOfPieces, vtkCommunicator::MAX_OP, 0); - if (myId == 0) - { - std::swap(this->PieceWrittenFlags, recvBuffer); - } - delete[] recvBuffer; - } -} - -//---------------------------------------------------------------------------- -void vtkXMLPTableWriter::WritePrimaryElementAttributes(std::ostream& os, vtkIndent indent) -{ - this->WriteScalarAttribute("GhostLevel", this->GhostLevel); -} - -//---------------------------------------------------------------------------- -int vtkXMLPTableWriter::WriteData() -{ - // Write the summary file. - ostream& os = *(this->Stream); - vtkIndent indent = vtkIndent().GetNextIndent(); - vtkIndent nextIndent = indent.GetNextIndent(); - - this->StartFile(); - if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) - { - return 0; - } - - os << indent << "<" << this->GetDataSetName(); - this->WritePrimaryElementAttributes(os, indent); - if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) - { - return 0; - } - os << ">\n"; - - // Write the information needed for a reader to produce the output's - // information during UpdateInformation without reading a piece. - this->WritePData(indent.GetNextIndent()); - if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) - { - return 0; - } - - // Write the elements referencing each piece and its file. - for (int i = 0; i < this->NumberOfPieces; ++i) - { - if (this->PieceWrittenFlags[i] == 0) - { - continue; - } - os << nextIndent << "<Piece"; - this->WritePPieceAttributes(i); - if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) - { - return 0; - } - os << "/>\n"; - } - - os << indent << "</" << this->GetDataSetName() << ">\n"; - - this->EndFile(); - return (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError) ? 0 : 1; -} - -//---------------------------------------------------------------------------- -void vtkXMLPTableWriter::WritePPieceAttributes(int index) -{ - char* fileName = this->CreatePieceFileName(index); - this->WriteStringAttribute("Source", fileName); - delete[] fileName; -} - -//---------------------------------------------------------------------------- -char* vtkXMLPTableWriter::CreatePieceFileName(int index, const char* path) -{ - std::ostringstream s; - if (path) - { - s << path; - } - s << this->FileNameBase; - if (this->UseSubdirectory) - { - s << "/" << this->FileNameBase; - } - s << "_" << index; - if (this->PieceFileNameExtension) - { - s << this->PieceFileNameExtension; - } - - size_t len = s.str().length(); - char* buffer = new char[len + 1]; - strncpy(buffer, s.str().c_str(), len); - buffer[len] = '\0'; - - return buffer; -} - -//---------------------------------------------------------------------------- -void vtkXMLPTableWriter::SplitFileName() -{ - // Split the FileName into its PathName, FileNameBase, and - // FileNameExtension components. - - std::string pathname = vtksys::SystemTools::GetProgramPath(this->FileName); - // Pathname may be empty if FileName is simply a filename without any leading - // "/". - if (!pathname.empty()) - { - pathname += "/"; - } - std::string filename_wo_ext = vtksys::SystemTools::GetFilenameWithoutExtension(this->FileName); - std::string ext = vtksys::SystemTools::GetFilenameExtension(this->FileName); - - delete[] this->PathName; - delete[] this->FileNameBase; - delete[] this->FileNameExtension; - - this->PathName = vtksys::SystemTools::DuplicateString(pathname.c_str()); - this->FileNameBase = vtksys::SystemTools::DuplicateString(filename_wo_ext.c_str()); - this->FileNameExtension = vtksys::SystemTools::DuplicateString(ext.c_str()); -} - //---------------------------------------------------------------------------- int vtkXMLPTableWriter::WritePiece(int index) { @@ -431,30 +138,6 @@ int vtkXMLPTableWriter::WritePiece(int index) return result; } -//---------------------------------------------------------------------------- -void vtkXMLPTableWriter::ProgressCallbackFunction( - vtkObject* caller, unsigned long, void* clientdata, void*) -{ - vtkAlgorithm* w = vtkAlgorithm::SafeDownCast(caller); - if (w) - { - reinterpret_cast<vtkXMLPTableWriter*>(clientdata)->ProgressCallback(w); - } -} - -//---------------------------------------------------------------------------- -void vtkXMLPTableWriter::ProgressCallback(vtkAlgorithm* w) -{ - float width = this->ProgressRange[1] - this->ProgressRange[0]; - float internalProgress = w->GetProgress(); - float progress = this->ProgressRange[0] + internalProgress * width; - this->UpdateProgressDiscrete(progress); - if (this->AbortExecute) - { - w->SetAbortExecute(1); - } -} - //---------------------------------------------------------------------------- void vtkXMLPTableWriter::WritePRowData(vtkDataSetAttributes* ds, vtkIndent indent) { @@ -462,7 +145,7 @@ void vtkXMLPTableWriter::WritePRowData(vtkDataSetAttributes* ds, vtkIndent inden { return; } - ostream& os = *(this->Stream); + ostream& os = *this->Stream; char** names = this->CreateStringArray(ds->GetNumberOfArrays()); os << indent << "<PRowData"; @@ -494,21 +177,10 @@ void vtkXMLPTableWriter::WritePRowData(vtkDataSetAttributes* ds, vtkIndent inden this->DestroyStringArray(ds->GetNumberOfArrays(), names); } -//---------------------------------------------------------------------------- -void vtkXMLPTableWriter::DeleteFiles() -{ - for (int i = this->StartPiece; i < this->EndPiece; ++i) - { - char* fileName = this->CreatePieceFileName(i, this->PathName); - this->DeleteAFile(fileName); - delete[] fileName; - } -} - //---------------------------------------------------------------------------- void vtkXMLPTableWriter::SetupPieceFileNameExtension() { - delete[] this->PieceFileNameExtension; + this->Superclass::SetupPieceFileNameExtension(); // Create a temporary piece writer and then initialize the extension. vtkXMLWriter* writer = this->CreatePieceWriter(0); diff --git a/IO/ParallelXML/vtkXMLPTableWriter.h b/IO/ParallelXML/vtkXMLPTableWriter.h index 12f2166ba3c9ff6f2ad5816c784a106264cd554f..f4ad149cb5c6abaa9249d480443802622ebc8dd6 100644 --- a/IO/ParallelXML/vtkXMLPTableWriter.h +++ b/IO/ParallelXML/vtkXMLPTableWriter.h @@ -31,18 +31,19 @@ #define vtkXMLPTableWriter_h #include "vtkIOParallelXMLModule.h" // For export macro -#include "vtkXMLWriter.h" +#include "vtkXMLPDataObjectWriter.h" class vtkCallbackCommand; class vtkMultiProcessController; class vtkTable; class vtkXMLTableWriter; +class vtkXMLPDataObjectWriter; -class VTKIOPARALLELXML_EXPORT vtkXMLPTableWriter : public vtkXMLWriter +class VTKIOPARALLELXML_EXPORT vtkXMLPTableWriter : public vtkXMLPDataObjectWriter { public: static vtkXMLPTableWriter* New(); - vtkTypeMacro(vtkXMLPTableWriter, vtkXMLWriter); + vtkTypeMacro(vtkXMLPTableWriter, vtkXMLPDataObjectWriter); void PrintSelf(ostream& os, vtkIndent indent) VTK_OVERRIDE; /** @@ -55,69 +56,6 @@ public: */ const char* GetDefaultFileExtension() VTK_OVERRIDE; - //@{ - /** - * Get/Set the number of pieces that are being written in parallel. - */ - vtkSetMacro(NumberOfPieces, int); - vtkGetMacro(NumberOfPieces, int); - //@} - - //@{ - /** - * Get/Set the range of pieces assigned to this writer. - */ - vtkSetMacro(StartPiece, int); - vtkGetMacro(StartPiece, int); - vtkSetMacro(EndPiece, int); - vtkGetMacro(EndPiece, int); - //@} - - //@{ - /** - * Get/Set the ghost level used for this writer's piece. - */ - vtkSetMacro(GhostLevel, int); - vtkGetMacro(GhostLevel, int); - //@} - - //@{ - /** - * Get/Set whether to use a subdirectory to store the pieces - */ - vtkSetMacro(UseSubdirectory, bool); - vtkGetMacro(UseSubdirectory, bool); - //@} - - //@{ - /** - * Get/Set whether the writer should write the summary file that - * refers to all of the pieces' individual files. - * This is on by default. Note that only the first process writes - * the summary file. - */ - virtual void SetWriteSummaryFile(int flag); - vtkGetMacro(WriteSummaryFile, int); - vtkBooleanMacro(WriteSummaryFile, int); - //@} - - //@{ - /** - * Controller used to communicate data type of blocks. - * By default, the global controller is used. If you want another - * controller to be used, set it with this. - */ - virtual void SetController(vtkMultiProcessController*); - vtkGetObjectMacro(Controller, vtkMultiProcessController); - //@} - - /** - * Overridden to handle passing the CONTINUE_EXECUTING() flags to the - * executive. - */ - int ProcessRequest(vtkInformation* request, vtkInformationVector** inputVector, - vtkInformationVector* outputVector) VTK_OVERRIDE; - protected: vtkXMLPTableWriter(); ~vtkXMLPTableWriter() VTK_OVERRIDE; @@ -127,103 +65,51 @@ protected: */ int FillInputPortInformation(int port, vtkInformation* info) VTK_OVERRIDE; + /** + * Return the type of data being actually written + */ const char* GetDataSetName() VTK_OVERRIDE; - vtkXMLTableWriter* CreateTablePieceWriter(); - - vtkXMLWriter* CreatePieceWriter(int index); - void WritePData(vtkIndent indent); /** - * Overridden to make appropriate piece request from upstream. + * Create a writer for the piece at a given index */ - virtual int RequestUpdateExtent(vtkInformation* request, vtkInformationVector** inputVector, - vtkInformationVector* outputVector); - /** - * Override writing method from superclass. - */ - int WriteInternal() VTK_OVERRIDE; + vtkXMLWriter* CreatePieceWriter(int index); /** - * Collect information between ranks before writing the summary file. - * This method is called on all ranks while summary file is only written on 1 - * rank (rank 0). - */ - virtual void PrepareSummaryFile(); - - void WritePrimaryElementAttributes(ostream& os, vtkIndent indent) VTK_OVERRIDE; - int WriteData() VTK_OVERRIDE; - virtual void WritePPieceAttributes(int index); - - char* CreatePieceFileName(int index, const char* path = nullptr); - void SplitFileName(); - virtual int WritePiece(int index); + * Create a table writer for the actual piece. Used by + * CreatePieceWriter(int index) + */ + vtkXMLTableWriter* CreateTablePieceWriter(); /** - * Callback registered with the InternalProgressObserver. - */ - static void ProgressCallbackFunction(vtkObject*, unsigned long, void*, void*); + * Write a piece of the dataset on disk. Called by WritePieceInternal() + */ + int WritePiece(int index) VTK_OVERRIDE; /** - * Valid at end of WriteInternal to indicate if we're going to continue - * execution. + * Method called by the superclass::WriteInternal(). Write a piece using + * WritePiece(int index). */ - vtkGetMacro(ContinuingExecution, bool); + int WritePieceInternal() VTK_OVERRIDE; - void WritePRowData(vtkDataSetAttributes* ds, vtkIndent indent); /** - * Progress callback from internal writer. - */ + * Write Data associated with the input dataset + */ + void WritePData(vtkIndent indent) VTK_OVERRIDE; /** - * The observer to report progress from the internal writer. - */ - vtkCallbackCommand* InternalProgressObserver; - - vtkMultiProcessController* Controller; - - virtual void ProgressCallback(vtkAlgorithm* w); - - int StartPiece; - int EndPiece; - int NumberOfPieces; - int GhostLevel; - int WriteSummaryFile; - bool UseSubdirectory; - - char* PathName; - char* FileNameBase; - char* FileNameExtension; - char* PieceFileNameExtension; + * Write RowData. Called by WritePData(vtkIndent indent) + */ + void WritePRowData(vtkDataSetAttributes* ds, vtkIndent indent); private: vtkXMLPTableWriter(const vtkXMLPTableWriter&) VTK_DELETE_FUNCTION; void operator=(const vtkXMLPTableWriter&) VTK_DELETE_FUNCTION; - /** - * Method used to delete all written files. - */ - void DeleteFiles(); - /** * Initializes PieceFileNameExtension. */ - void SetupPieceFileNameExtension(); - - /** - * Indicates the piece currently being written. - */ - int CurrentPiece; - - /** - * Set in WriteInternal() to request continued execution from the executive to - * write more pieces. - */ - bool ContinuingExecution; - - /** - * Flags used to keep track of which pieces were written out. - */ - unsigned char* PieceWrittenFlags; + void SetupPieceFileNameExtension() VTK_OVERRIDE; }; #endif