I am getting an error when I call the DomainParticipant enable() method. Here are some lines of code in Java that I am using.
final DomainParticipant = participant;
DomainParticipantFactoryQos factoryQos = new DomainParticipantFactoryQos();
DomainParticipantFactory.The ParticipantFactory.get_qos( factoryQos );
factoryQos.entity_factory.autoenable_created_entities = false;
DomainParticipantFactory.The ParticipantFactory.set_qos( factoryQos );
participant = DomainParticipantFactory.get_instance().create_participant( 14, DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT, null, 0 );
participant.enable();
The code blows up here. Here is the first part of the stack trace:
com.rti.dds.intrastructure.RETCODE_ERROR
at com.rti.dds.util.Utilities.rethrow(Unknown Source)
at com.rti.dds.intrastructure.EntityImpl.enable(Unknown Source)
. . .
Any ideas what this error means?
Thanks.
Hi,
The line:
looks like a copy-paste error as it does not compile.
Other than that the code you have seems fine. I created similar code by modifying the Java example that rtiddsgen creates and it runs with no errors.
You could add the following line to the beginning of your program and then re-run it:
This will enable a high level of verbosity messages. Perhaps the printouts it produces will shed some light on what the error is...
Gerardo
Thanks Gerardo,
You are correct. The "=" sign should not be there. The line should be:
final DomainParticipant participant;
I should also add that the problem occurs as I add more "participants" (i.e. more domains). It could be a resource problem, and that could be why RTI DDS is seeing this participant as an Unknown Source - (not sure???).
I don't have any compile problems. The code even runs a little, but this participant does not get enabled. I am still not sure why.
Hello Herb,
Sorry, I did not mean compile errors. I meant that I executed the Java code you provided and it run, enabling the DomainParticipant and sending messages without generating any errors.
I think the "Unknown Source" indicates that the error was generated in the core C library and not in the Java layer. It seems like the DomainParticipant.enable() is returning RETCODE_ERROR. The question is why...
When you said:
Do you mean this happens (1) when you create multiple DomainParticipant entities from within the same Java application? Or (2) do you mean different Java applications in the same machine? Or (3) do you mean something else?
If (1), is it always the same DomainParticipant that does not get enabled (e.g. when you start the 3rd participant)?
You are right in that it could be a resouce problem... In order to troubleshoot it would be helpful to have additional information. Did you try adding the line of code I suggested in the previous posting to configure Logging with high verbosity prior to enabling the DomainParticipant? If so, can you copy and paste the relavant output here?
Gerardo
We are using both multiple DomainParticipant entities from within the same Java application and different Java applications in the same machine.
With verbose logging, I am actually seeing 2 errors, and both seem to be resource related. On the hunch that it is resource related, I tried changing max_object_per_thread from 1024 to 2048, but I received RETCODE_IMMUTABLE when I tried that. I do not know what to do about that. Here is the stac trace for the other 2 errors:
DDS_StringSeq_ensure_length:memory allocation: originaException in thread "main" com.rti.dds.infrastructure.RETCODE_ERROR: error creating entity
at com.rti.dds.util.Utilities.rethrow(Unknown Source)
at com.rti.dds.infrastructure.NativeFactoryMixin.create_entityI(Unknown Source)
at com.rti.dds.domain.DomainParticipantFactoryImpl.create_participant(Unknown Source)
at com.ng.etesim.dds.wrapper.DDS$RTIClasses.<init>(DDS.java:601)
at com.ng.etesim.dds.wrapper.DDS$RTIClasses.<init>(DDS.java:538)
at com.ng.etesim.dds.wrapper.DDS.init(DDS.java:105)
at com.ng.etesim.dds.monitor.DDSMonitor.init(DDSMonitor.java:187)
at com.ng.etesim.dds.logger.DDSLogger.<init>(DDSLogger.java:118)
at com.ng.etesim.dds.logger.DDSLogger.<init>(DDSLogger.java:82)
at com.ng.etesim.framework.api.SimulationController.startDDSLoggers(SimulationController.java:126)
at com.ng.etesim.simcontrol.TTxSimController.config(TTxSimController.java:146)
at com.ng.etesim.simcontrol.TTxSimController.main(TTxSimController.java:111)
com.rti.dds.infrastructure.RETCODE_ERROR: error creating entity
at com.rti.dds.util.Utilities.rethrow(Unknown Source)
at com.rti.dds.infrastructure.NativeFactoryMixin.create_entityI(Unknown Source)
at com.rti.dds.domain.DomainParticipantFactoryImpl.create_participant(Unknown Source)
at com.ng.etesim.dds.wrapper.DDS$RTIClasses.<init>(DDS.java:601)
at com.ng.etesim.dds.wrapper.DDS$RTIClasses.<init>(DDS.java:538)
at com.ng.etesim.dds.wrapper.DDS.init(DDS.java:105)
at com.ng.etesim.dds.router.Port.<init>(Port.java:68)
at com.ng.etesim.dds.router.DDSRouter.addPort(DDSRouter.java:67)
at com.ng.etesim.sim.commmodel.CommModel.initModelConfig(CommModel.java:167)
at com.ng.etesim.sim.commmodel.CommModel.register(CommModel.java:86)
at com.ng.etesim.sim.commmodel.CommModel.main(CommModel.java:257)
Hello Herb,
It does appear resource related. But it is not so easy to figure our which resource without additional information.
One thing that confuses me is that I am not seeing any of the outoput I would expect it should be coming out of the logger. I am only seeing the exceptions but with the high versobity we should be seeing a lot of other things. Maybe your application or Java VM is redirectiong the output somewhere else as this is why we are not seeing it... If that is the case a way around that would be to configure logging to output to a file. You an do this by adding the line:
After this the "MyLogOutput.txt" should contain the logging output I was hoping to see... Gerardo
Gerardo,
The file is 5 megabytes. That is too big for here. Let me know what to do.
We can drop this for a while. I will be on vacation for a couple of weeks, and I will get back to you.
Thanks,
Herb
Gerardo,
I have supplied the log file you needed at a safe location. I hope you were able to access it. Please let me know if you received the file.
Thanks,
Herb
Apparently the safe location method did not work, and with your suggestion, I used the unix zip utility which resulted in a MUCH smaller file. I will add the file in this post. It was compressed with the following command on RedHat Linux:
zip MyLogOutput.zip MyLogOutput.txt
Thanks.
Hello,
Thank for for including the ZIP file. I took a look at it and I could only find twio kinds of errors:
Several ones that start with
[D0014|ENABLE]NDDS_Transport_UDPv4_create_recvresource_rrEA:!create socket
for example in line 6074, 6087, etc.And the one that starts with
[D0014|ENABLE]REDADatabase_createCursorPerWorker:!create worker-specific object
as found in line 6258The
!create socket
is not fatal. This happens because you must have started multiple participants in that domain and it is not finding a free port. So it keeps iterating trying teh different ports that correspond to domain 14 in sequence (that is ports 10910, 10912, 10914, and so on) until it finds a free one at 10936 and it continues.The second one, the
!create worker-specific object
is the one that causes the domain creation to fail. You were right to suspect the max_object_per_thread. Looking at the source this would be the resource limot that is causing the!create worker-specific object
to fail.The reason you were getting a RETCODE_IMMUTABLE on the set_qos is that you must change this on the DomainParticipantFactory prior to creating any DomainParticipant on that process (i.e. from that instance of TheDomainParticipantFactory) . Once you have created a DomainParticipant from the facture the max_object_per_thread is "fixed" and can no longer be changed.
From your posting I think you already know how to change it, but I will add it here for completeness:
Let us know if this works!
Gerardo
I have tried that code before, and it did not work (compiles and runs but does not fix the problem). I have tried it again, and the
!create worker-specific object
error is still there.The new log file is attached. It was created thusly:
zip MyLogOutput2.zip MyLogOutput.txt
Thanks.
I think it is the max_objects_per_thread that is immutable. I changed it and then re-fetched the factoryQos to see if it changed, and it was still set to 1024 instead of 2048. Something is keeping me from changing max_objects_per_thread. Could this be some kind of license or configuration issue?
Thanks.
Gerardo,
This is new code, and I looked around a found some code in another place that looks like this:
DomainParticipantFactory.get_instance().load_profiles();
domainParticipant = DomainParticipantFactory.get_instance().create_instance_with_profile(...);
domainParticipant.set_default_topic_qos_with_profile(...);
Is there a way I can change the max_objects_per_thread in this section of code?
Thanks.
Hello,
Yes, you can add the code I pasted in my previous posting right before, or right after the DomainParticipantFactory.get_instance().load_profiles();
It should work as long as it is called before you create the first DomainParticipant which is done in the line
domainParticipant = DomainParticipantFactory.get_instance().create_participant_with_profile(...);
If the call to DomainParticipantFactory.TheParticipantFactory.set_qos( factoryQos ) fails then it should throw the com.rti.dds.infrastructure.RETCODE_IMMUTABLE_POLICY exception right there, so you should be able to see if that works immediately. And you can also re-fetch the DomainParticipantFactory and check it as you mentioned.
The max_objects_per_thread is can be changed as long as it is done before the first DomainParticipant is created. I just tested that with a simple snipped of Java code just in case... So perhaps there are other places where you are creating DomainParticipants that you did not notice? Is there a way to set a breakpoint or use the log messages to make sure you are changing the DomainParticipantFactoryQos before you create the first Participant?
Gerardo
Gerardo,
I have a unit test that tests this method directly as the very 1st test. We are using JUnit. The constructor not shown just initializes some class variables. Here is the pertinent part of the JUnit code:
@BeforeClass
public static void setUpClass()
{
Participant participant =
new Participant_RT( "Unit_Testing_TopicWrapperTest", 42 );
participant.setupDds( true );
}
Here is the setupDds method code:
void setupDds( final boolean debugDDS )
{
// only turn this on to try to debug a problem with the DDS core
if ( debugDDS )
{
com.rti.ndds.config.Logger.get_instance().set_verbosity( LogVerbosity.NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL );
}
DomainParticipantFactory.get_instance().load_profiles();
DomainParticipantFactoryQos factoryQos = new DomainParticipantFactoryQos();
DomainParticipantFactory.TheParticipantFactory.get_qos( factoryQos );
factoryQos.resource_limits.max_objects_per_thread=2048;
DomainParticipantFactory.TheParticipantFactory.set_qos( factoryQos );
...
}
Here is what happems with the set_qos call:
DDS_DomainParticipantFactoryQos_check_immutableI:ERROR: Trying to change immutable policy resource_limits.max_objects_per_thread
This is about as basic as I can get it. Why can't I change the max_objects_per_thread value? Is there something in the load _profiles() that can cause a problem? Are there environment variables at play here?
Thanks,
Herb
Gerardo,
I finally wrote a simple routine in this environment that increased max_objects_per_thread to 2048 and it worked, so I am pretty sure the RTI-DDS environment is working correctly.
I put the code you suggested at the very beginning of the program, and I removed it from everywhere else. I started getting all of my log files - one for every channel, and I no longer received the IMMUTABLE error. It appears this code can only be executed once successfully, so it could not be in a loop or where multiple participants were created.
I think it is working now. Thank you.
Herb
Hello Herb,
Glad to hear you finally got that working! Yes, as we were discussing the
max_objects_per_thread
is and immutable property of theDomainParticipantFactory
and for this reason it can only be modified prior to creating any DomainParticipants in that process.Regards,
Gerardo
Dear Gerardo,
I was also encountered with the following error:
DDS_DomainParticipantFactoryQos_check_immutableI:ERROR: Trying to change immutable policy resource_limits.max_objects_per_thread
DomainParticipantFactory
prior to creating any DomainParticipants did not work for me. After inspecting my code, I realized that two entities (Waitset and GuardCondition) implicitly create a domainparticipant in my program. So I decide to get a pointer to them instead of an object in my class definition. Now my program works fine (at least the previous error has gone!). But now according to the following link, https://community.rti.com/best-practices/modern-c-api-don%E2%80%99t-declare-entities-pointers, I don't know whether it's a good work to do that or not. Please help me.In general you should be able to initialize reference types with
dds::core::null
, like the article explains. However there seems to be a bug and that constructor is not compiling forWaitset
andCondition
. For that reason, in this particular case it is a valid workaround to declare your variable as a pointer.Hi Alex,
Thanks for your answer. But I was wondering why waitset and guardcondition implicitly creat a domain participant and prevent me to change the factoryqos. Can you explain that? Also, as you know, waitset and guardcondition don't provide the operations close(). So by defining them as pointer in my class definition, I think I would have some dangled pointers somewhere in my program. How should I handle the destruction of these entities?
Best Regards,
Bonjefir