DXL Execution Timeout

Hello,

I modified existing code that has error checking and no i get a "DXL Execution Timeout" is there a way to increase the timeout within the script? I believe it's do to my search function anyone see how to improve it?

Thank you,
Jim
 

Module Source = current
Object obj
bool found = false
 
Module archiveModule = edit("/CNPE - Project/Fuqing/Engineering Specifications/Copy of FQ856000003B30444DS",true,true) 
 
bool search(Object hObject, Module archiveModule, Module Source)
{
//
// This code snippet will follow the outlinks from a given object. (hObject)
//
  //Declarations
  Object    curr_obj          = null
  Object    targetObject      = null
  bool      found             = false
  int       absnoArchive      = 0
  int       absnoCurrent      = 0
  
  absnoCurrent = hObject."Absolute number"
  // First, find the target object.
  curr_obj = object(absnoCurrent, archiveModule)
  if (null curr_obj || isDeleted(curr_obj))
  {
      for targetObject in entire Source do
          {
                absnoArchive = targetObject."Absolute Number"
                if (absnoArchive == absnoCurrent)
                {
                        found = true
                        break
                }
          }
  }
  else
  {
        found = true
  }
  return found
}
void InLinks(Object hObject, Module archiveModule, Module Source)
{
 // Follow the in-links from the selected object (hObject)
 
  Object     hInObj          = null
  ModName_   inModRef        = null
  LinkRef    lr              = null
  Link       in_Link         = null
  string     linkSourcePath  = null
 
  Object     curr_obj        = null
  int        absnoCurrent     = 0
  
  absnoCurrent = hObject."Absolute number"
  curr_obj = object(absnoCurrent, archiveModule)
        
  // find the source (other end) of the in-link
  for lr in hObject <- "*" do
  {
        // get the full path to the link source
        // for in-links this is always in the other module
        linkSourcePath = fullName(source lr)
 
        // check that the returned path is valid
        if (exists(module linkSourcePath) == true)
        {
                // check to see if the module is already open
                if (open(module linkSourcePath) == false)
                {
                        // open it if it is closed
                        edit(linkSourcePath,true,true) 
                }
        }
  }
 
  // now we know for sure those modules are open, we can do the real work
  for in_Link in hObject <- "*" do
  {
        // check the module at the other end of the link
        inModRef =  source in_Link
        if (null inModRef)      {continue}
 
        // check the object at the other end of the link
        hInObj   =  source in_Link
        if (null hInObj)        {continue}
        if (isDeleted(hInObj))  {continue} 
 
        //and finally do something useful with the source object
        //print identifier hInObj "\n"
        hInObj->curr_obj
  }
}
 
void OutLinks(Object hObject, Module archiveModule, Module Source)
{
//
// This code snippet will follow the outlinks from a given object. (hObject)
//
  //Declarations
  Object    hTargetObj        = null 
  Module    targetModule      = null
  Link      outLink           = null
 
  Object     curr_obj         = null
  int        absnoCurrent     = 0
  
  // now we know for sure those modules are open, we can do the real work
  for outLink in hObject -> "*" do
  {
        absnoCurrent = hObject."Absolute number"
        curr_obj = object(absnoCurrent, archiveModule)
                
        // full path to the module at the other end of the out_link
        string sTargetPath = fullName(target outLink)
        if (null sTargetPath) {continue}
 
        // only relevant if module exists with r access
        if (exists(module sTargetPath) == true)
        {
                // ensure module is open
                targetModule = read(sTargetPath, false)
        }
 
        //check that the target Module still exists
        if (null targetModule )     {continue}
 
        //check that the target object still exists
        hTargetObj = target outLink
        if (null hTargetObj)        {continue}
        if (isDeleted(hTargetObj))  {continue} 
 
        //now do something useful with the object
        //print identifier hTargetObj"\n"
        curr_obj->hTargetObj
  }
}
 
for obj in entire Source do
{
        if (search(obj, archiveModule, Source))
        {
                InLinks(obj, archiveModule, Source)
                OutLinks(obj, archiveModule, Source)
        }
        else
        {
                print "mismatch\n"
        }
}

SystemAdmin - Wed Oct 19 14:46:19 EDT 2011

Re: DXL Execution Timeout
SystemAdmin - Wed Oct 19 17:48:55 EDT 2011

The DXL interpreter has a primitive built-in watchdog\timeout type function to try and trap infinite loops. It's based on how many DXL execution cycles have been performed which loosely translates to how many lines of code have been interpreted - from memory I think it defaults to 1 million cycles.

You can disable this (not recommended) or change the default cycles by using the "runLim" pragma at the beginning of the code.

To disable use: pragma runLim, 0

To set a specific number of cycles, change the value from zero to how many cycles you want, so if it's 2 million cycles, use: pragma runLim, 2000000


Paul Miller
Melbourne, Australia

Re: DXL Execution Timeout
llandale - Thu Oct 20 13:18:58 EDT 2011

Yes, my old notes say that default runLim is 1000000; but I don't think it corresponds to lines of code but I really don't know what its counting.

The "object" function only finds objects that are currently displayed, and I believe its particularly ineffecient. Since your target and source modules are static in this code, you might as well build yourself a Skip list of their objects, with int absno as the KEY:
Skip skpArchive = create() // KEY 'int' AbsNo; DATA: 'Object' handle
for o in archiveModule do
{ if (!isDeleted(o()) put(skpArchive, (int o."Absolute Number"), o)
}
To find a module:
if (!find(skpArchive, AbsNoDesired, o)) then no such AbsNoDesired in Archive Module.

The Skip searching is certainly a LOT quicker than searching the module; when I tested the overhead of creating, populating, and deleting the Skip was recouped by the 3rd object search, and you gain tremendous speed after that.
 


If I read this correctly, you are restoring an ArchiveModule which at some time was an Ancestor of the SourceModule (such as previously archived and restored) and you want to replicate all the in and out links of each Source object in the corresponding Archive object. You should have some comment in there that says that, or what it is that you are trying to do.

The only ineffeciency I see here is the slow object searching which I addressed above. Creating links is extremely slow and there's nothing you can do about that. Creating a link that already exists doesn't take any time; probably less time then checking if the link already exists. The fact that you are exceeding your default time out is irrelevant; just about all admin type script will do that.

Your 'search()' function
Looks odd. You are calling it with objects from the source module. If you don't find that object in the archiveModule it seems to me then you should return false. Instead, you proceed to search for that object's absolute number in the Source module, which surely will result in finding the object since "obj" is in the Source module.

Your "inLinks()" function.
You need to open the other module "edit" when its not currently open (as you do), but also if it is open but its not currently "edit". You would want to get the open Module handle of that module (if any), and then check if its open edit. Here's some incomplete code for that

Item      itm
Module  mod
                // "item" returns whether it exists.
                // "module" below returns only if its open.
itm      = item(NameModFull)
if (!null itm)
     mod        = module(itm)   // Module handle if its open
if (null mod or !isEdit(mod))
                        edit(linkSourcePath,true,true)


Don't see an advantage to opening that other module visibly, perhaps your first 'true' should be 'false'. Also probably load the standard view:
edit(linkSourcePath, false, false, true)

Your outLinks() function.
Move these two lines above the loop; comparable to what you do in inLinks().
absnoCurrent = hObject."Absolute number"
curr_obj = object(absnoCurrent, archiveModule)

Your bottom loop:
Seems to me you want to skip Source objects that are deleted.

The create links statements should surely be trapped for errors:
noError()
o->o1
ErrMess = lastError().

Seems to me you would want to get the Link Module Name of the link, perhaps with some "module(lnk)" command, and use that in the link create statement:
o ->NameLinkModFull->o1

Seems to me you may want to create the link-set in the script. As it is, the script will stop and prompt the user when a new linkset is needed. The LinkModule will need to be open Edit, and need to be saved afterwards:
LinkSet ls = create(mLinkMod, NameFullSourceMod, NameFullTargetMod).

Lets not forget to save all your modules. Perhaps like this:
for mod in database do
{ if (unsaved(mod)) save(mod)
if (!isVisible(mod)) close(mod)
}

 

  • Louie

 

Re: DXL Execution Timeout
Mathias Mamsch - Thu Oct 20 17:13:33 EDT 2011

llandale - Thu Oct 20 13:18:58 EDT 2011

Yes, my old notes say that default runLim is 1000000; but I don't think it corresponds to lines of code but I really don't know what its counting.

The "object" function only finds objects that are currently displayed, and I believe its particularly ineffecient. Since your target and source modules are static in this code, you might as well build yourself a Skip list of their objects, with int absno as the KEY:
Skip skpArchive = create() // KEY 'int' AbsNo; DATA: 'Object' handle
for o in archiveModule do
{ if (!isDeleted(o()) put(skpArchive, (int o."Absolute Number"), o)
}
To find a module:
if (!find(skpArchive, AbsNoDesired, o)) then no such AbsNoDesired in Archive Module.

The Skip searching is certainly a LOT quicker than searching the module; when I tested the overhead of creating, populating, and deleting the Skip was recouped by the 3rd object search, and you gain tremendous speed after that.
 


If I read this correctly, you are restoring an ArchiveModule which at some time was an Ancestor of the SourceModule (such as previously archived and restored) and you want to replicate all the in and out links of each Source object in the corresponding Archive object. You should have some comment in there that says that, or what it is that you are trying to do.

The only ineffeciency I see here is the slow object searching which I addressed above. Creating links is extremely slow and there's nothing you can do about that. Creating a link that already exists doesn't take any time; probably less time then checking if the link already exists. The fact that you are exceeding your default time out is irrelevant; just about all admin type script will do that.

Your 'search()' function
Looks odd. You are calling it with objects from the source module. If you don't find that object in the archiveModule it seems to me then you should return false. Instead, you proceed to search for that object's absolute number in the Source module, which surely will result in finding the object since "obj" is in the Source module.

Your "inLinks()" function.
You need to open the other module "edit" when its not currently open (as you do), but also if it is open but its not currently "edit". You would want to get the open Module handle of that module (if any), and then check if its open edit. Here's some incomplete code for that

Item      itm
Module  mod
                // "item" returns whether it exists.
                // "module" below returns only if its open.
itm      = item(NameModFull)
if (!null itm)
     mod        = module(itm)   // Module handle if its open
if (null mod or !isEdit(mod))
                        edit(linkSourcePath,true,true)


Don't see an advantage to opening that other module visibly, perhaps your first 'true' should be 'false'. Also probably load the standard view:
edit(linkSourcePath, false, false, true)

Your outLinks() function.
Move these two lines above the loop; comparable to what you do in inLinks().
absnoCurrent = hObject."Absolute number"
curr_obj = object(absnoCurrent, archiveModule)

Your bottom loop:
Seems to me you want to skip Source objects that are deleted.

The create links statements should surely be trapped for errors:
noError()
o->o1
ErrMess = lastError().

Seems to me you would want to get the Link Module Name of the link, perhaps with some "module(lnk)" command, and use that in the link create statement:
o ->NameLinkModFull->o1

Seems to me you may want to create the link-set in the script. As it is, the script will stop and prompt the user when a new linkset is needed. The LinkModule will need to be open Edit, and need to be saved afterwards:
LinkSet ls = create(mLinkMod, NameFullSourceMod, NameFullTargetMod).

Lets not forget to save all your modules. Perhaps like this:
for mod in database do
{ if (unsaved(mod)) save(mod)
if (!isVisible(mod)) close(mod)
}

 

  • Louie

 

For anyone who wants to know: The runLim count refers to iterations of the basic interpreter loop. During interpretation the DXL source is translated into micro operations for the DXL Virtual Machine. Then these microoperations are executed by the DXL VM.

This little program for example:

pragma runLim, 47
 
// we start with 18 cycles
int a = 4  // 6 cycles (SUM: 24)
a = 5      // 6 cycles (SUM: 30)
int b = 8  // 6 cycles (SUM: 36)
b + a      // 6 Cycles (SUM: 42)
-a         // 4 Cycles (SUM: 46) 
{}         // 1 Cycle  (SUM: 47)

 


runs on my DOORS 8.2 just without triggering an 'Execution Timeout'. Using progPrint_ we can see how it is split up into micro-operations:

 

 

 

// *** { ***
1.i0(   BlockI 0 4 0)
 
// *** obj = obj__() ***
1.i4(   IntAss, 1.i9, 1.i16, 1.i22) 
1.i9( PushVarA, obj, 0,  0)^
1.i16(CurrentObj)^
1.i22(      Pop)
 
// *** attrDXLName = aDXLName__() ***
1.i25(   IntAss, 1.i30, 1.i37, 1.i43)
1.i30( PushVarA, attrDXLName, 0,  1)^
1.i37(AttrDXLNameGet)^
1.i43(      Pop) 
 
// No idea how we come out with 18 here ..., should be 9 or so. Probably progPrint_ is omitting some initialization stuff. 
 
// *** int a = 4 *** 
1.i46(   IntAss, 1.i51, 1.i58, 1.i65)   <- 1
1.i51( PushVarA, a, 0,  2)^             <- 2
1.i58(     Push 4)^                     <- 2
1.i65(      Pop)                        <- 1
 
// *** a = 5 *** 
1.i68(   IntAss, 1.i73, 1.i80, 1.i87)   <- 1
1.i73( PushVarA, a, 0,  2)^             <- 2 
1.i80(     Push 5)^                     <- 2
1.i87(      Pop)                        <- 1
 
// *** b = 8 ***
1.i90(   IntAss, 1.i95, 1.i102, 1.i109) <- 1
1.i95( PushVarA, b, 0,  3)^             <- 2 
1.i102(     Push 8)^                    <- 2
1.i109(      Pop)                       <- 1
 
// *** b + a ***
1.i112(  IntPlus, 1.i117, 1.i124, 1.i131) <- 1
1.i117( PushVarC, b, 0,  3)^              <- 2
1.i124( PushVarC, a, 0,  2)^              <- 2
1.i131(      Pop)                         <- 1
 
// *** -a ***                             
1.i134(  IntUMin, 1.i138, 1.i145)         <- 1
1.i138( PushVarC, a, 0,  2)^              <- 2
1.i145(      Pop)                         <- 1
 
// empty block is missing? 
 
// *** } *** 
1.i163(   BlockE 0 4 0)^



Assuming interpreter cycles for the micro operations, e.g. Pop = 1 (Decrease Stack Pointer), Push Address = 2 ( Write Address on Stack, Increase Stack Pointer), Push Value = 2 (Write Value on Stack, Decrease Stack Pointer), Call Perm = 1, you can see how these add up to the cycles that we can see from playing with the runLim.

Never mind, just guesswork by me :-) Maybe this is interesting for someone. I find it nice, how well one can reconstruct the source code from the progPrint_ results, by the way. This is a nice way to inspect encoded DXL files by the way ;-) Regards, Mathias



 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Re: DXL Execution Timeout
SystemAdmin - Thu Oct 20 21:28:47 EDT 2011

Mathias Mamsch - Thu Oct 20 17:13:33 EDT 2011

For anyone who wants to know: The runLim count refers to iterations of the basic interpreter loop. During interpretation the DXL source is translated into micro operations for the DXL Virtual Machine. Then these microoperations are executed by the DXL VM.

This little program for example:

pragma runLim, 47
 
// we start with 18 cycles
int a = 4  // 6 cycles (SUM: 24)
a = 5      // 6 cycles (SUM: 30)
int b = 8  // 6 cycles (SUM: 36)
b + a      // 6 Cycles (SUM: 42)
-a         // 4 Cycles (SUM: 46) 
{}         // 1 Cycle  (SUM: 47)

 


runs on my DOORS 8.2 just without triggering an 'Execution Timeout'. Using progPrint_ we can see how it is split up into micro-operations:

 

 

 

// *** { ***
1.i0(   BlockI 0 4 0)
 
// *** obj = obj__() ***
1.i4(   IntAss, 1.i9, 1.i16, 1.i22) 
1.i9( PushVarA, obj, 0,  0)^
1.i16(CurrentObj)^
1.i22(      Pop)
 
// *** attrDXLName = aDXLName__() ***
1.i25(   IntAss, 1.i30, 1.i37, 1.i43)
1.i30( PushVarA, attrDXLName, 0,  1)^
1.i37(AttrDXLNameGet)^
1.i43(      Pop) 
 
// No idea how we come out with 18 here ..., should be 9 or so. Probably progPrint_ is omitting some initialization stuff. 
 
// *** int a = 4 *** 
1.i46(   IntAss, 1.i51, 1.i58, 1.i65)   <- 1
1.i51( PushVarA, a, 0,  2)^             <- 2
1.i58(     Push 4)^                     <- 2
1.i65(      Pop)                        <- 1
 
// *** a = 5 *** 
1.i68(   IntAss, 1.i73, 1.i80, 1.i87)   <- 1
1.i73( PushVarA, a, 0,  2)^             <- 2 
1.i80(     Push 5)^                     <- 2
1.i87(      Pop)                        <- 1
 
// *** b = 8 ***
1.i90(   IntAss, 1.i95, 1.i102, 1.i109) <- 1
1.i95( PushVarA, b, 0,  3)^             <- 2 
1.i102(     Push 8)^                    <- 2
1.i109(      Pop)                       <- 1
 
// *** b + a ***
1.i112(  IntPlus, 1.i117, 1.i124, 1.i131) <- 1
1.i117( PushVarC, b, 0,  3)^              <- 2
1.i124( PushVarC, a, 0,  2)^              <- 2
1.i131(      Pop)                         <- 1
 
// *** -a ***                             
1.i134(  IntUMin, 1.i138, 1.i145)         <- 1
1.i138( PushVarC, a, 0,  2)^              <- 2
1.i145(      Pop)                         <- 1
 
// empty block is missing? 
 
// *** } *** 
1.i163(   BlockE 0 4 0)^



Assuming interpreter cycles for the micro operations, e.g. Pop = 1 (Decrease Stack Pointer), Push Address = 2 ( Write Address on Stack, Increase Stack Pointer), Push Value = 2 (Write Value on Stack, Decrease Stack Pointer), Call Perm = 1, you can see how these add up to the cycles that we can see from playing with the runLim.

Never mind, just guesswork by me :-) Maybe this is interesting for someone. I find it nice, how well one can reconstruct the source code from the progPrint_ results, by the way. This is a nice way to inspect encoded DXL files by the way ;-) Regards, Mathias



 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

Hello,

I have several questions and was wondering if anyone could answer them?
1) Could anyone please tell me why I get different error message when I switch between the different methods of linking. My main concern is when I use createLink_() it doen't give be the same module name as ErrMess.
 

//noError()
//(hInObj)->LinkModule->(aObject)
//ErrMess = lastError()
//print ErrMess "\n"
Error=createLink_(hInObj,LinkModule,aObject)

 

2) I am trying to create linkset on the fly so that I don't manually need to add them and to prevent the errors I am getting from my first question.

Module lm = edit(LinkModule, false)
    Linkset ls = create(lm, linkSourcePath, fullName(archiveModule))


3) I would also like to add a desciption when the linkset is created. So that when you open the module and go to the "linkset" tab you see what you just created.

4) Can anyone tell me why I get an error when I try the following code: (its due to the casting DXL 9.3.0.4)?

if (find(ActiveObjectsArchive,(int Src."Absolute Number"),Arc)


5) My whole purpose for writting this script is to teach myself DXL and to fix a mistake a fellow co-worker made and the easy way was to restore the module from a backup prior to the mistake. If anyone has a script that they would be willing to share I would appeciate it.
Thank you,
Jim

Once again thank you for everyones input I appreciate.

Does anyone recommend the DXl training class(2 days) from IBM?

For those that use RPE is there a limit to producing output from DOORS tables, because I have a template that works fine but when I run it against a module(DIL) that has 1000+ row table(s) I get a run-time error. I am trying to stop this practice within the company. -not to use DOORS tables in this fashion. Any ideas?

Full Source code:

#include <utils/linkops.dxl>
pragma runLim, 0
 
Module Source = current
Object Src
Module archiveModule = edit("/Sandbox/Copyof864506-1325-XNC00",true,true,true) 
string LinkModule = "/CNPE - Project/Fuqing/ Admin/Satisfies"
 
if (null Source)
{
    infoBox "This DXL must be run from a current Module."
    halt
}
 
void InLinks(Object hObject, Module aMod)
{
 // Follow the in-links from the selected object (hObject)
  Object     hInObj          = null
  ModName_   inModRef        = null
  LinkRef    lr              = null
  Link       in_Link         = null
  string     linkSourcePath  = null
  Item       itm             = null
  Module         mod                     = null
  Object     aObject         = null
  int        Error           = 0
  int        absno           = 0
  //string     ErrMess         = ""
 
  absno = hObject."Absolute number"
  aObject = object(absno, aMod)
  
  // find the source (other end) of the in-link
  for lr in hObject <- "*" do
  { 
        // get the full path to the link source
        // for in-links this is always in the other module
        linkSourcePath = fullName(source lr)
 
        // check that the returned path is valid
        itm  = item(linkSourcePath)
        if (!null itm)
        { mod = module(itm) }       // Module handle if its open
        if (null mod or !isEdit(mod))
        { edit(linkSourcePath,false,true,true) }
  }
 
  // now we know for sure those modules are open, we can do the real work
  for in_Link in hObject <- "*" do
  {  
        // check the module at the other end of the link
        inModRef =  source in_Link
        if (null inModRef)      {continue}
 
        // check the object at the other end of the link
        hInObj   =  source in_Link
        if (null hInObj)        {continue}
        if (isDeleted(hInObj))  {continue} 
 
    Module lm = edit(LinkModule, false)
    Linkset ls = create(lm, linkSourcePath, fullName(archiveModule))
        //and finally do something useful with the source object
        //print identifier hInObj "\n"
        //noError()
        //(hInObj)->LinkModule->(aObject)
        //ErrMess = lastError()
        //print ErrMess "\n"
        Error=createLink_(hInObj,LinkModule,aObject)
        if (Error!=linkErrorNoError) { reportLinkError_(hInObj,aObject,LinkModule,"",Error) }
  }
}
 
void OutLinks(Object hObject, Module aMod)
{
//
// This code snippet will follow the outlinks from a given object. (hObject)
//
  //Declarations
  Object    hTargetObj        = null 
  Module    targetModule      = null
  Link      outLink           = null
  int       Error             = 0
  int       absno             = 0
  //string     ErrMess         = ""
 
  absno = hObject."Absolute number"
  aObject = object(absno, aMod)
        
  // now we know for sure those modules are open, we can do the real work
  for outLink in hObject -> "*" do
  {  
        // full path to the module at the other end of the out_link
        string sTargetPath = fullName(target outLink)
        if (null sTargetPath) {continue}
 
        // only relevant if module exists with r access
        if (exists(module sTargetPath) == true)
        {
                // ensure module is open
                targetModule = read(sTargetPath, false)
        }
 
        //check that the target Module still exists
        if (null targetModule )     {continue}
 
        //check that the target object still exists
        hTargetObj = target outLink
        if (null hTargetObj)        {continue}
        if (isDeleted(hTargetObj))  {continue} 
 
        //now do something useful with the object
        //print identifier hTargetObj"\n"
        //noError()
        //(aObject)->LinkModule->(hTargetObj)
        //ErrMess = lastError()
        //print ErrMess "\n"
        Module lm = edit (LinkModule, false)
    Linkset ls = create(lm, fullName(archiveModule), sTargetPath)
        Error=createLink_(aObject,LinkModule,hTargetObj)
        if (Error!=linkErrorNoError) { reportLinkError_(aObject,hTargetObj,LinkModule,"",Error) }
  }
}
 
 
Skip ActiveObjectsArchive = create() // KEY 'int' AbsNo; DATA: 'Object' handle
Skip DeletedObjectsArchive = create() // KEY 'int' AbsNo; DATA: 'Object' handle
 
Object Arc
int absno = 0
for Arc in archiveModule do
{ 
    absno = Arc."Absolute Number"
        if (!isDeleted(Arc)) 
        { 
                put(ActiveObjectsArchive, absno, Arc)
        }
        else
        {
                put(DeletedObjectsArchive, absno, Arc)
        }
}
 
for Src in entire Source do
{
    absno = Src."Absolute Number"
        if (find(ActiveObjectsArchive,absno,Arc))
        {
                InLinks(Src, archiveModule)
                OutLinks(Src, archiveModule)
        }
}