DcmSCP in multiprocess mode (Windows)

All other questions regarding DCMTK

Moderator: Moderator Team

Message
Author
martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

DcmSCP in multiprocess mode (Windows)

#1 Post by martinrame »

Hi, I created a DcmSCP descendant and enabled its MultiProcess Mode.

The program runs, when an association is requested, a new process is started, but the association isn't handled. What I'm doing wrong?.

I'm working on Windows.

Here is the code:

Code: Select all

MyDcmSCP m_scp;

// add transfer syntaxes and presentation contexts
// ....

// here port and AETitle are hardcoded for this example
// the real program uses the arguments passed from command line.
m_scp.setPort(104);
m_scp.setAETitle("PACSSERVER");
char * lStr = "c:\\server\\dicomscp.exe PACSSERVER 104";
if(m_scp.enableMultiProcessMode(2, &lStr) == EC_Normal)
{
  COUT << "Ok" << OFendl;
}
m_scp.listen();
P.S.: my class has an handleIncomingCommand handler implemented, and tested in single mode, it works ok.

martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

#2 Post by martinrame »

Sorry, found the solution.

It worked by just calling m_scp.enableMultiProcessMode(); without params.

martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

#3 Post by martinrame »

No, m_scp.enableMultiProcessMode() without params forces running in single process mode.

J. Riesmeier
DCMTK Developer
Posts: 2517
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

#4 Post by J. Riesmeier »

You know what a "char*[]" is? In your case, you need an array with two char pointers ...

martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

#5 Post by martinrame »

Yes, I also passed m_scp.enableMultiProcess(argc, argv) to create a process with exactly the original parameters, and the new process is created, but it doesn't handle the association.

J. Riesmeier
DCMTK Developer
Posts: 2517
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

#6 Post by J. Riesmeier »

I personally never tried the multi-process mode of the (still experimental) DcmSCP class under Windows, but as far as I can see, you need to call the following DcmSCP method in the child process (before any network initializiation):

Code: Select all

  /** Marks this SCP as being a forked child under Windows, i.e. it handles an association
   *  received by the parent.
   *  @return EC_Normal if marking was successful, an error code otherwise
   */
  OFCondition markAsForkedChild();

martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

#7 Post by martinrame »

Thanks.

Now, after the association is requested, the child process receives the string "--forked-child" as argv[1], knowing this, I call m_scp.markAsForkedChild(), hoping it to return EC_Normal, but it doesn't. Then, the SCU keeps waiting for the association response.

Any hint?

J. Riesmeier
DCMTK Developer
Posts: 2517
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

#8 Post by J. Riesmeier »

DcmSCP::markAsForkedChild() checks whether the DcmSCP class is in multi-process mode, so you should call this method after enableMultiProcessMode(). Whether this really makes sense is another story, but this is how it is currently implemented. I've added this issue to the to-do list ...

martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

#9 Post by martinrame »

Now my code looks like this:

Code: Select all

  if(m_scp.enableMultiProcessMode(argc, argv) == EC_Normal)
  {
    COUT << "Ok" << OFendl;
    if(m_scp.markAsForkedChild() == EC_Normal)
    {
      COUT << "forked child" << OFendl;
    }
  }

  m_scp.listen();
But this way, I get an "Association Request Failed" message from the SCU side.

J. Riesmeier
DCMTK Developer
Posts: 2517
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

#10 Post by J. Riesmeier »

Since you are writing your own program: What about using a debugger or adding debug output (to the logger)? ;-)

martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

#11 Post by martinrame »

Thanks for the hint Jörg. I've added a logger to file, in debug mode, but it only writes:
W: (notice: dcmdata auto correction disabled.)
Here is my program (without the handleIncomingCommand part):

Code: Select all

int main(int argc, char *argv[])
{
  //OFLog::configure(OFLogger::DEBUG_LOG_LEVEL);
  OFauto_ptr<log4cplus::Layout> layout(new log4cplus::PatternLayout("%D{%Y-%m-%d %H:%M:%S.%q} %5p: %m%n"));
  log4cplus::SharedAppenderPtr logfile(new log4cplus::FileAppender("dicomscp.log"));
  logfile->setLayout(layout);
  /* make sure that only the file logger is used */
  log4cplus::Logger log = log4cplus::Logger::getRoot();
  //log.removeAllAppenders();
  log.addAppender(logfile);
  log.setLogLevel(OFLogger::DEBUG_LOG_LEVEL);

  // show parameters
  for(int i = 1; i < argc; i++)
  {
    COUT << i << ":" << argv[i] << OFendl;
  }

  OFList<OFString> transfer_syntax;
  OFString lDir;
  OFString lAETitle;
  bool lForkedChild = false;
  int lPort;
  if(strcmp(argv[1], "--forked-child") == 0)
  {
    lDir = argv[2];
    lAETitle = argv[3];
    lPort = atoi(argv[4]);
  }
  else
  {
    lDir = argv[1];
    lAETitle = argv[2];
    lPort = atoi(argv[3]);
  }

  DJDecoderRegistration::registerCodecs();
  DcmRLEDecoderRegistration::registerCodecs();

  DicomSCP m_scp(lDir, lPort); 
  transfer_syntax.push_back(UID_LittleEndianImplicitTransferSyntax); 
  transfer_syntax.push_back(UID_DeflatedExplicitVRLittleEndianTransferSyntax); 
  transfer_syntax.push_back(UID_JPEGProcess1TransferSyntax);
  m_scp.setPort(lPort); 
  m_scp.setAETitle(lAETitle.c_str()); 
  m_scp.addPresentationContext(UID_MOVEPatientRootQueryRetrieveInformationModel, transfer_syntax); 
  m_scp.addPresentationContext(UID_VerificationSOPClass, transfer_syntax);
  m_scp.addPresentationContext(UID_CTImageStorage, transfer_syntax);
  m_scp.addPresentationContext(UID_EnhancedCTImageStorage, transfer_syntax);
  m_scp.addPresentationContext(UID_MRImageStorage, transfer_syntax);
  m_scp.addPresentationContext(UID_UltrasoundImageStorage, transfer_syntax);
  m_scp.addPresentationContext(UID_SecondaryCaptureImageStorage, transfer_syntax);
  m_scp.addPresentationContext(UID_ComputedRadiographyImageStorage, transfer_syntax);
  m_scp.addPresentationContext(UID_DigitalXRayImageStorageForPresentation, transfer_syntax);
  m_scp.addPresentationContext(UID_DigitalXRayImageStorageForProcessing, transfer_syntax);
  m_scp.addPresentationContext(UID_DigitalMammographyXRayImageStorageForPresentation, transfer_syntax);
  m_scp.addPresentationContext(UID_DigitalMammographyXRayImageStorageForProcessing, transfer_syntax);

  if(m_scp.enableMultiProcessMode(argc, argv) == EC_Normal)
  {
    COUT << "Ok" << OFendl;
    if(m_scp.markAsForkedChild() == EC_Normal)
    {
      COUT << "forked child" << OFendl;
    }
  }
  m_scp.listen();

  // Desregistramos codecs
  DJDecoderRegistration::cleanup();
  DcmRLEDecoderRegistration::cleanup();
}
Hopefully you can see something wrong in it.

J. Riesmeier
DCMTK Developer
Posts: 2517
Joined: Tue, 2011-05-03, 14:38
Location: Oldenburg, Germany
Contact:

#12 Post by J. Riesmeier »

Maybe, it's too obvious but only the --forked-child process should be marked as a forked child.

Btw, why are you setting the listening port twice?

martinrame
Posts: 347
Joined: Mon, 2009-02-23, 19:57

#13 Post by martinrame »

After marking as forked child only the --forked-child process it started to work as expected.

Regarding the listening por twice, it was an non needed extra parameter in the constructor, now it was removed.

Thank you.

st80rules
Posts: 190
Joined: Tue, 2007-05-08, 17:45

#14 Post by st80rules »

Tagging along this thread, I'm trying to subclass DcmSCP and because all its attributes are private, it makes it difficult to try overriding any protocol (like waitForAssociation).

For now I'll change the DcmSCP class to make protected the attributes I need, I think you need to adjust your code as well.

Michael Onken
DCMTK Developer
Posts: 2055
Joined: Fri, 2004-11-05, 13:47
Location: Oldenburg, Germany
Contact:

#15 Post by Michael Onken »

Hi,

that is exactly the idea of the current API: Do _not_ use the private data elements. Use the public and protected methods and overwrite them as necessary in your own derived class. If this is not possible tell me why -- then I have to adapt non-private part of the DcmSCP API.

Michael

Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 1 guest