Bug 946 - IFR does not handle recursive types.
Summary: IFR does not handle recursive types.
Status: RESOLVED FIXED
Alias: None
Product: TAO
Classification: Unclassified
Component: Interface Repository (show other bugs)
Version: 1.7.8
Hardware: x86 Linux
: P3 normal
Assignee: Jeff Parsons
URL:
: 1579 1657 (view as bug list)
Depends on:
Blocks:
 
Reported: 2001-06-19 06:50 CDT by Bogdan Jeram
Modified: 2010-05-31 04:18 CDT (History)
3 users (show)

See Also:


Attachments
Example with recursive structure which causes problerm (3.46 KB, application/octet-stream)
2007-12-07 03:34 CST, Bogdan Jeram
Details
Patch for forwad declared unions and strcuts (1.40 KB, patch)
2010-01-18 06:54 CST, Bogdan Jeram
Details
Test IDL file for testing forward declaration support (458 bytes, text/plain)
2010-02-02 04:43 CST, Bogdan Jeram
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Bogdan Jeram 2001-06-19 06:50:04 CDT
Dear,

I have IFR_Service running and I try to fill it 

tao_ifr -I$INTROOT/idl -I$ACE_ROOT/TAO/orbsvcs/orbsvcs baci.idl

and I got:

(ifr_adding_visitor.cpp:1506) ifr_adding_visitor::element_type - lookup_id 
failed
(24861|1024) EXCEPTION, visit_sequence
system exception, ID 'IDL:omg.org/CORBA/BAD_PARAM:1.0'
TAO exception, minor code = 0 (unknown location; unspecified errno), completed = 
NO

(ifr_adding_visitor_structure.cpp:109) ifr_adding_visitor_structure::visit_scope 
- failed to accept visitor
(ifr_adding_visitor_structure.cpp:169) 
ifr_adding_visitor_structure::visit_structure - visit_scope failed
(ifr_adding_visitor.cpp:65) ifr_adding_visitor::visit_scope - failed to accept 
visitor
(ifr_adding_visitor.cpp:191) ifr_adding_visitor::visit_module - visit_scope 
failed
(ifr_adding_visitor.cpp:65) ifr_adding_visitor::visit_scope - failed to accept 
visitor
(ifr_adding_visitor.cpp:1189) ifr_adding_visitor::visit_root - visit_scope 
failed
(be_produce.cpp:279) BE_produce - failed to accept visitor
Fatal Error - Aborting
-----------------------------------
The IDL file is:

#ifndef _BACI_IDL_
#define _BACI_IDL_

//#include <CosPropertyService.idl>

#pragma prefix "ALMA"

module ACS {

typedef unsigned long long Time;
typedef unsigned long long TimeInterval;
typedef unsigned long UID;
typedef sequence<string> stringSeq;
typedef sequence<Time> TimeSeq;
typedef unsigned long Tag;
typedef unsigned long pattern;

enum Condition {
  RED,
  YELLOW,
  GREEN,
  GREY
};

typedef sequence<Condition> ConditionSeq;

typedef sequence<pattern> patternSeq;
typedef sequence<double> doubleSeq;
typedef sequence<long> longSeq;

typedef sequence<doubleSeq> doubleSeqSeq;
typedef sequence<longSeq> longSeqSeq;


interface Property;

struct PropertyDesc{
	Property property_ref;
	string name;
	UID id;
  //	CosPropertyService::PropertySet characteristics;
};

typedef sequence<PropertyDesc> PropertyDescSeq;

interface DO;

struct DODesc{
	DO DO_ref;
	string name;
	UID id;
	PropertyDescSeq properties;
  //	CosPropertyService::PropertySet characteristics;
};

interface StateTags{
	const short CURRENT = -1;
};

exception NoSuchState {};

interface NamedComponent{
  readonly attribute string name;   // @static
  readonly attribute UID id;   // @static
  string get_interface();       // OE support
  any get_characteristic_by_name(in string name);  // generic access to 
characteristics
  stringSeq find_characteristic(in string reg_exp);
};

interface Property: NamedComponent{   // @parameter_root
  readonly attribute string DO_name;
  //  CosPropertyService::PropertySet characteristics(in short state_id) raises 
(NoSuchState);
};



interface DO: NamedComponent{   // @DO_root
  DODesc descriptor();
  //  CosPropertyService::PropertySet characteristics(in short state_id) raises 
(NoSuchState);
};



struct CBDescIn{
  TimeInterval normal_timeout;
  TimeInterval negotiable_timeout;
  Tag id_tag;
};

struct CBDescOut{
  TimeInterval estimated_timeout;
  Tag id_tag;
};

struct Completion{
  string description;
  short type;
  short code;
  UID source_id;
  Time timestamp;
  sequence<Completion, 1> error;
};

typedef sequence<Completion> completionSeq;

interface Callback{
  boolean negotiate(in TimeInterval time_to_transmit, in CBDescOut desc);
};

interface CBvoid: Callback{   // @callback
  oneway void working(in Completion c, in CBDescOut desc);
  oneway void done(in Completion c, in CBDescOut desc);
};

interface CBpattern: Callback{   // @callback
  oneway void working(in pattern value, in Completion c, in CBDescOut desc);   
// @events
  oneway void done(in pattern value, in Completion c, in CBDescOut desc);   // 
@events
};

interface CBdouble: Callback{   // @callback
  oneway void working(in double value, in Completion c, in CBDescOut desc);   // 
@events
  oneway void done(in double value, in Completion c, in CBDescOut desc);   // 
@events
};

interface CBstring: Callback{   // @callback
  oneway void working(in string value, in Completion c, in CBDescOut desc);   // 
@events
  oneway void done(in string value, in Completion c, in CBDescOut desc);   // 
@events
};

interface CBlong: Callback{   // @callback
  oneway void working(in long value, in Completion c, in CBDescOut desc);   // 
@events
  oneway void done(in long value, in Completion c, in CBDescOut desc);   // 
@events
};

interface CBdoubleSeq: Callback{   // @callback
  oneway void working(in doubleSeq value, in Completion c, in CBDescOut desc);   
// @events
  oneway void done(in doubleSeq value, in Completion c, in CBDescOut desc);   // 
@events
};
	
interface CBlongSeq: Callback{   // @callback
  oneway void working(in longSeq value, in Completion c, in CBDescOut desc);   
// @events
  oneway void done(in longSeq value, in Completion c, in CBDescOut desc);   // 
@events
};


interface Alarmpattern : Callback{
	oneway void alarm_raised(in pattern value, in Completion c, in CBDescOut 
desc);
	oneway void alarm_cleared(in pattern value, in Completion c, in 
CBDescOut desc);
};

interface Alarmdouble : Callback{
	oneway void alarm_raised(in double value, in Completion c, in CBDescOut 
desc);
	oneway void alarm_cleared(in double value, in Completion c, in CBDescOut 
desc);
};

interface Alarmlong : Callback{
	oneway void alarm_raised(in long value, in Completion c, in CBDescOut 
desc);
	oneway void alarm_cleared(in long value, in Completion c, in CBDescOut 
desc);
};

interface Alarmstring : Callback{
	oneway void alarm_raised(in string value, in Completion c, in CBDescOut 
desc);
	oneway void alarm_cleared(in string value, in Completion c, in CBDescOut 
desc);
};

interface Subscription{
  void suspend();
  void resume();
  void destroy();
};

interface Monitor: Subscription{
  void set_time_trigger(in TimeInterval timer);
  void get_time_trigger(out TimeInterval timer);
  readonly attribute Time transmit_time;
};

interface Monitordouble: Monitor{
  void set_value_trigger(in double delta, in boolean enable);
  void get_value_trigger(out double delta, out boolean enable);
};

interface Monitorlong : Monitor{
  void set_value_trigger(in long delta, in boolean enable);
  void get_value_trigger(out long delta, out boolean enable);
};

interface TypelessProperty : Property {
	readonly attribute string description;
	readonly attribute string format;
	readonly attribute string units;
	readonly attribute pattern resolution;
};

interface Ppattern: TypelessProperty{   // @Property
  pattern get_sync(out Completion c);   // @accessors @sync
  void get_async(in CBpattern cb, in CBDescIn desc);   // @accessors @async
  long get_history(in long n_last_values, out patternSeq vs, out TimeSeq ts);   
// @history
  Monitor create_monitor(in CBpattern cb, in CBDescIn desc);   // @monitorable
  Monitor create_postponed_monitor(in CBpattern cb, in CBDescIn desc, in Time 
transmit_time);   //@monitorable
  readonly attribute TimeInterval default_timer_trigger;
  readonly attribute TimeInterval min_timer_trigger;
  readonly attribute pattern default_value;   // @static
  readonly attribute stringSeq bitDescription;   // @static
  readonly attribute ConditionSeq whenSet;   // @static
  readonly attribute ConditionSeq whenCleared;   // @static
};

interface Pdouble: TypelessProperty{   // @Property
  double get_sync(out Completion c);   // @accessors @sync
  void get_async(in CBdouble cb, in CBDescIn desc);   // @accessors @async
  long get_history(in long n_last_values, out doubleSeq vs, out TimeSeq ts);   
// @history
  Monitordouble create_monitor(in CBdouble cb, in CBDescIn desc);   // 
@monitorable
  Monitordouble create_postponed_monitor(in CBdouble cb, in CBDescIn desc, in 
Time transmit_time);   //@monitorable
  readonly attribute TimeInterval default_timer_trigger;
  readonly attribute TimeInterval min_timer_trigger;
  readonly attribute double min_delta_trigger;   // @static
  readonly attribute double default_value;   // @static
  readonly attribute double graph_min;   // @static
  readonly attribute double graph_max;   // @static
  readonly attribute double min_step;   // @static
};

interface Plong: TypelessProperty{   // @Property
  long get_sync(out Completion c);   // @accessors @sync
  void get_async(in CBlong cb, in CBDescIn desc);   // @accessors @async
  long get_history(in long n_last_values, out longSeq vs, out TimeSeq ts);   // 
@history
  Monitorlong create_monitor(in CBlong cb, in CBDescIn desc);   // @monitorable
  Monitorlong create_postponed_monitor(in CBlong cb, in CBDescIn desc, in Time 
transmit_time);   //@monitorable
  readonly attribute TimeInterval default_timer_trigger;
  readonly attribute TimeInterval min_timer_trigger;
  readonly attribute long min_delta_trigger;   // @static
  readonly attribute long default_value;   // @static
  readonly attribute long graph_min;   // @static
  readonly attribute long graph_max;   // @static
  readonly attribute long min_step;   // @static
};

interface Pstring : TypelessProperty{
  string get_sync(out Completion c);   // @accessors @sync
  void get_async(in CBstring cb, in CBDescIn desc);   // @accessors @async
  long get_history(in long n_last_values, out stringSeq vs, out TimeSeq ts);   
// @history
  Monitor create_monitor(in CBstring cb, in CBDescIn desc);   // @monitorable
  Monitor create_postponed_monitor(in CBstring cb, in CBDescIn desc, in Time 
transmit_time);   //@monitorable
  readonly attribute TimeInterval default_timer_trigger;
  readonly attribute TimeInterval min_timer_trigger;
  readonly attribute string default_value;   // @static

};

interface PdoubleSeq: TypelessProperty{   // @Property
  doubleSeq get_sync(out Completion c);   // @accessors @sync
  void get_async(in CBdoubleSeq cb, in CBDescIn desc);   // @accessors @async
  long get_history(in long n_last_values, out doubleSeqSeq vs, out TimeSeq ts);   
// @history
  Monitordouble create_monitor(in CBdoubleSeq cb, in CBDescIn desc);   // 
@monitorable
  Monitordouble create_postponed_monitor(in CBdouble cb, in CBDescIn desc, in 
Time transmit_time);   //@monitorable
  readonly attribute TimeInterval default_timer_trigger;
  readonly attribute TimeInterval min_timer_trigger;
  readonly attribute double min_delta_trigger;   // @static
  readonly attribute double default_value;   // @static
  readonly attribute double graph_min;   // @static
  readonly attribute double graph_max;   // @static
  readonly attribute double min_step;   // @static
};

interface PlongSeq: TypelessProperty{   // @Property
  longSeq get_sync(out Completion c);   // @accessors @sync
  void get_async(in CBlongSeq cb, in CBDescIn desc);   // @accessors @async
  long get_history(in long n_last_values, out longSeqSeq vs, out TimeSeq ts);   
// @history
  Monitorlong create_monitor(in CBlongSeq cb, in CBDescIn desc);   // 
@monitorable
  Monitorlong create_postponed_monitor(in CBlong cb, in CBDescIn desc, in Time 
transmit_time);   //@monitorable
  readonly attribute TimeInterval default_timer_trigger;
  readonly attribute TimeInterval min_timer_trigger;
  readonly attribute long min_delta_trigger;   // @static
  readonly attribute long default_value;   // @static
  readonly attribute long graph_min;   // @static
  readonly attribute long graph_max;   // @static
  readonly attribute long min_step;   // @static
};



interface ROstring : Pstring{
  Subscription new_subscription_Alarmstring(in Alarmstring cb, in CBDescIn 
desc);
};

interface RWstring: Pstring{   // @Property
  Completion set_sync(in string value);   // @mutators @sync
  void set_async(in string value, in CBvoid cb, in CBDescIn desc);   // 
@mutators @async
  void set_nonblocking(in string value);   // @nonblocking
};

interface ROpattern: Ppattern{   // @Property
  Subscription new_subscription_Alarmpattern(in Alarmpattern cb, in CBDescIn 
desc);   // @eventable
};

interface ROdouble: Pdouble{   // @Property
  Subscription new_subscription_Alarmdouble(in Alarmdouble cb, in CBDescIn 
desc);   // @eventable
  readonly attribute double alarm_low_on;   // @static
  readonly attribute double alarm_low_off;   // @static
  readonly attribute double alarm_high_on;   // @static
  readonly attribute double alarm_high_off;   // @static
};

interface RWdouble: Pdouble{   // @Property
  Completion set_sync(in double value);   // @mutators @sync
  void set_async(in double value, in CBvoid cb, in CBDescIn desc);   // 
@mutators @async
  void set_nonblocking(in double value);   // @nonblocking
  void increment(in CBvoid cb, in CBDescIn desc);   // @step
  void decrement(in CBvoid cb, in CBDescIn desc);   // @step
  readonly attribute double min_value;   // @static
  readonly attribute double max_value;   // @static
};

interface ROlong: Plong{   // @Property
  Subscription new_subscription_Alarmlong(in Alarmlong cb, in CBDescIn desc);   
// @eventable
  readonly attribute long alarm_low_on;   // @static
  readonly attribute long alarm_low_off;   // @static
  readonly attribute long alarm_high_on;   // @static
  readonly attribute long alarm_high_off;   // @static
};

interface RWlong: Plong{   // @Property
  Completion set_sync(in long value);   // @mutators @sync
  void set_async(in long value, in CBvoid cb, in CBDescIn desc);   // @mutators 
@async
  void set_nonblocking(in long value);   // @nonblocking
  void increment(in CBvoid cb, in CBDescIn desc);   // @step
  void decrement(in CBvoid cb, in CBDescIn desc);   // @step
  readonly attribute long min_value;   // @static
  readonly attribute long max_value;   // @static
};

interface ROdoubleSeq: PdoubleSeq{   // @Property
  Subscription new_subscription_Alarmdouble(in Alarmdouble cb, in CBDescIn 
desc);   // @eventable
  readonly attribute double alarm_low_on;   // @static
  readonly attribute double alarm_low_off;   // @static
  readonly attribute double alarm_high_on;   // @static
  readonly attribute double alarm_high_off;   // @static
};

interface RWdoubleSeq: PdoubleSeq{   // @Property
  Completion set_sync(in doubleSeq value);   // @mutators @sync
  void set_async(in double valueSeq, in CBvoid cb, in CBDescIn desc);   // 
@mutators @async
  void set_nonblocking(in doubleSeq value);   // @nonblocking
  void increment(in CBvoid cb, in CBDescIn desc);   // @step
  void decrement(in CBvoid cb, in CBDescIn desc);   // @step
  readonly attribute double min_value;   // @static
  readonly attribute double max_value;   // @static
};

interface ROlongSeq: PlongSeq{   // @Property
  Subscription new_subscription_Alarmlong(in Alarmlong cb, in CBDescIn desc);   
// @eventable
  readonly attribute long alarm_low_on;   // @static
  readonly attribute long alarm_low_off;   // @static
  readonly attribute long alarm_high_on;   // @static
  readonly attribute long alarm_high_off;   // @static
};

interface RWlongSeq: PlongSeq{   // @Property
  Completion set_sync(in longSeq value);   // @mutators @sync
  void set_async(in longSeq value, in CBvoid cb, in CBDescIn desc);   // 
@mutators @async
  void set_nonblocking(in longSeq value);   // @nonblocking
  void increment(in CBvoid cb, in CBDescIn desc);   // @step
  void decrement(in CBvoid cb, in CBDescIn desc);   // @step
  readonly attribute long min_value;   // @static
  readonly attribute long max_value;   // @static
};


};

#endif

***********************************************************************

Using Orbacus's InterfaceRpository (irserv) I don't have such a problem.

Test orbsvcs/test/InterfaceRepository/Application_Test and
IFR_Test passed.

Best Rgards


Bogdan Jeram
Comment 1 Jeff Parsons 2001-06-19 08:40:43 CDT
I've changed the summary of this bug to the more general and appropriate 
statement that the IFR does not handle recursive types. It's on my TODO list,
but this is as good a time as any to make the Bugzilla entry. I'm leaving the
long example IDL file, but a much shorter one will do to reproduce the problem.
Comment 2 Jeff Parsons 2001-06-19 08:41:33 CDT
Accepted.
Comment 3 Ossama Othman 2001-06-19 17:08:32 CDT
Corrected the TAO component.  This is an Interface Repository problem, not an
Implementation Repository problem.
Comment 4 Jeff Parsons 2003-08-21 10:30:06 CDT
*** Bug 1579 has been marked as a duplicate of this bug. ***
Comment 5 Jeff Parsons 2003-10-02 11:27:42 CDT
*** Bug 1604 has been marked as a duplicate of this bug. ***
Comment 6 Jeff Parsons 2003-11-26 09:29:08 CST
*** Bug 1657 has been marked as a duplicate of this bug. ***
Comment 7 Jeff Parsons 2006-02-10 10:49:45 CST
Support added some time ago by Simon Massey <sma@prismtech.com>.
Comment 8 Bogdan Jeram 2007-12-07 03:34:58 CST
Created attachment 885 [details]
Example with recursive structure which causes problerm

It looks like IFR still does not support recursive types.
Comment 9 Bogdan Jeram 2007-12-07 03:35:48 CST
It looks like IFR still has problem with IFR. Please try to load the attached IDL.
Comment 10 Bogdan Jeram 2010-01-13 10:08:54 CST
Here is a simpler exaple that causes the problem to IFR:



struct ET; 
typedef sequence<ET> LinkedList; /* this is the problematic part */
typedef string RTY;
struct ET
{
  double value;
};

 
interface Ex
{
    LinkedList testOp();   /* but here it fails */
};

In case of loading the above IDL the command "tao_ifr" fails with the following messages:


(21839|3086829264) EXCEPTION, ifr_adding_visitor_operation::visit_operation
system exception, ID 'IDL:omg.org/CORBA/COMM_FAILURE:1.0'
TAO exception, minor code = 6 (failed to recv request response; ENOENT), completed = MAYBE

(ifr_adding_visitor.cpp:110) ifr_adding_visitor::visit_scope - failed to accept visitor
(ifr_adding_visitor.cpp:2763) ifr_adding_visitor::create_interface_def - visit_scope failed
(ifr_adding_visitor.cpp:110) ifr_adding_visitor::visit_scope - failed to accept visitor
(ifr_adding_visitor.cpp:2281) ifr_adding_visitor::visit_root - visit_scope failed
(be_produce.cpp:230) BE_produce - failed to accept adding visitor
Fatal Error - Aborting
Comment 11 Bogdan Jeram 2010-01-15 07:41:53 CST
Actually it is problem with forward declaration of structs and unions when we want to use either of them when we define a sequence.

union ET; 
 
typedef sequence<ET> MySeq; // here is the problem

union ET switch(long)
{
case 0:
    double value;
case 1:
    string b;
};


interface tt
{
MySeq opT();   // here the IFR will crash
};


The problem is that  link to internal (IFR) information about ET is redefined when forward declaration is replaced with the real one, but the sequence still refer to the old one.
Comment 12 Jeff Parsons 2010-01-15 08:17:09 CST
This shouldn't be too hard to fix, but I'm surprised that it hasn't showed up before. This Bugzilla entry dates to before support for recursive types was added to the IFR. When this support was added, you'd think this bug would be the first one that would show up. What version of TAO are you using?
Comment 13 Bogdan Jeram 2010-01-15 08:26:38 CST
At the moment we are still with version  1.6.5
Comment 14 Jeff Parsons 2010-01-15 09:01:10 CST
Okay, this is mine to fix. I'll be tied up with other work for the next few weeks, but I want to get to this before we release TAO 2.0 sometime this summer. Thanks for reporting it.
Comment 15 Bogdan Jeram 2010-01-18 06:54:01 CST
Created attachment 1243 [details]
Patch for forwad declared unions and strcuts

I attached a patch that should fix the probnlem with forward declaration of 
struct and unions.

The patch, if finds out that a structure or union is forward declaration, does not destroy it from IFR, but just simply add members. So that "the reference" stays the same.

Please check if the patch is good.

Here is a simple IDL test that can be put in the TAO test some where.

    struct ET; 

    union UT;
 
    typedef sequence<ET> LinkedList;

  typedef sequence<UT> UnionLinkedList;

struct ET
{
    double value;
};



union UT switch(long)
{
case 0:
    double value;
case 1:
    string b;
};




interface Ex
{

    LinkedList testOp1();
    UnionLinkedList testOp2();
};
Comment 16 Bogdan Jeram 2010-02-02 04:43:07 CST
Created attachment 1249 [details]
Test IDL file for testing forward declaration support

The IDL file that can be used to test forward declaration properly works in any version of TAO IFR. Just try to load it using tao_ifr command.
Comment 17 Bogdan Jeram 2010-05-31 04:13:56 CDT
Today, I tested VERSION x.7.8 of ACE+TAO, and it looks that the problem is fixed = forward declaration of struct and union are handled w/o problem.

Thank you for the fix, so probably the bug can be closed.
Comment 18 Johnny Willemsen 2010-05-31 04:18:12 CDT
set to fixed