IDOC_CREATION_CHECK parameters filling? - abap

I'm checking an implementation of the interface IF_EX_IDOC_CREATION_CHECK which has a method IDOC_DATA_CHECK with 3 parameters:
IDOC_CONTROL type EDIDC
IDOC_DATA type EDIDD_TT
CREATE_IDOC type C
And my problem is that I can't find documentation in internet related to this interface nor examples. I want to know specifically what value does the parameter IDOC_DATA have when is called? Does it process IDocs from one material at a time or it carries all the IDocs of all the materials?
The code that is breaking my head is
loop at idoc_data assigning <it_data>.
case <it_data>-segnam.
when 'E1BPE1MATHEAD'. " Segment
clear: it_mat,zliser.
it_mathead = <it_data>-sdata.
...
if sy-subrc eq 0. " -------> This
exit. " -------> is my
endif. " -------> headache
...
When it comes to the exit. statement it goes out the loop without processing the next IDocs but I don't know exactly if it stops checking all the next IDocs of all the materials or the method IF_EX_IDOC_CREATION_CHECK~IDOC_DATA_CHECK is called again with the next set of IDocs of another material.
Unfortunately I can't run this interface with sample data because it directly changes data of other systems, so I just can read the code.
So if anyone has experience or reference in this issue I'd appreciate your help.
Thanks in advance.

The exit statement will cause the program to exit out of the loop, if the loop is the only processing block in the method, it will also exit the method.
However, the BADI/method should be called again for each IDOC.
Don't you have a development or QA environment where you could test this just to be sure?

Related

In LabView, how to run a block only after exit from a while loop?

In LabView, I want to take some readings into a Measurement File in a while loop and run a Read From Measurement File block only after exit from a while loop as below:
How can I achieve this event driven running?
P.S. Other blocks are removed for convenience.
Enforce execution order with an error wire as shown.
Wire error out from your Write to Measurement File function to error in of the Read from Measurement File.
LabVIEW dataflow works like this: data does not appear at the output terminals of a function, VI or structure (such as the While loop) until the loop completes, and a function, VI or structure does not execute until data is available at all input terminals that are wired. So the Read will not execute until the error data is output from the completed While loop.
Using the error wire to enforce the order of execution like this is common practice in LabVIEW, and has another advantage: most VIs are written to not perform their function if an error is present at error in, but instead 'fall through' and return the same error at their output. So you can wire up a chain of operations linked by the error wire and catch and handle any errors at the end of the chain.
If you want more precise control over how LabVIEW handles errors look at the help, but this page describes how to specifically ignore an error if you don't want it to stop your program, and this site has a good overview of techniques for error handling.

Erlang. Registering processes assignment

I am currently reading the Programming Erlang Second Edition Writing Software for a concurrent world written by Joe Armstrong and I have the following assignment :
Write a function start(AnAtom, Fun) to register AnAtom as spawn(Fun). Make sure your program works correctly in the case when two parallel processes simultaneously evaluate start/2. In this case you must guarantee that one succeeds and the other fails.
I understand the first bit. I need to register the process of Fun to the AnAtom. However what does the second part want me to do?
If two processes call start/2 at the same time then one of them must fail? Why? Given that the AnAtom is different to any others (which will be done inside the body of start/2 why would I want to fail one of the processes?
From what I can understand so far we have:
a = spawn(process1).
b = spawn(process2).
a ! {self(), registerProcess} //which should call the start/2
b ! {self(), registerProcess} //which should call the start/2
What is the problem here? Two processes will evaluate start/2. Why fail one of them? I'm probably missing the logic here or what I understood so far is completely wrong. Can anybody explain this in easier terms so I can get my head around it?
I believe the exercise is asking you to think about what happens when two parallel process evaluate start/2 using the SAME atom as the first parameter. When start(a, MyFunction) completes, there should be a spawned function (running MyFunction) associated with the name (atom) a.... what happens if
start(cool, MyFun1) and
start(cool, MyFun2)
are both executed simultaneously? How do you guarantee that one succeeds and the other fails.... does this help?
EDIT: I think you are not understanding the register process part of the assignment. When you get done with start(name, MyFun), doing a whereis(name) from the repl should return the process identifier of the process that got created.
This is not about sending the process a message to give it a name, it is about registering the process your created under the name passed in as the first parameter to start/2

Optimizing the number of times a subroutine is called from a loop

A small question on optimizing a program. The problem is stated as follows
Problem Statement:
The main code has a for/DO loop in which a subroutine is present. The subroutine need or need not be executed depending upon a flag I receive from user.
Obvious Solution:
Simplest way of doing it is using an IF loop to call the subroutine. But then this is time consuming if I have to check for the flag everytime the loop is executed. I am doing molecular dynamics and the number of times the loop will be executed will be of the order of 10^5 .
Qn: Is there a better way to do this, like I say to the program whether the subroutine has to be invoked depending on the flag once and for all? I am coding in Fortran 90. So it would be helpful if something can be said along that lines.
PROGRAM MAIN
IMPLICIT NONE
"ALL ARRAY INITIALIZATIONS
CALL DENSITY() ! I do a field based approach. So this is for grid formulation
DO i = 1, neq ! neq = number of eqbm cycles
CALL MC_CYC() ! Monte carlo steps
CALL DENSITY() ! Recalculate density
END DO
DO i = 1,nprod ! production cycle
DO j = 1, niter ! for averages of ensembles
CALL MC_CYC()
CALL DENSITY()
END DO
!do average here
IF(<flag is present>) ! This is where I needed to check flag. Because otherwise the flag will be checked everytime.
CALL RDF()
END IF
END DO
END PROGRAM MAIN
I am not sure that an IF statement is really going to slow down the program, even if called (more than) 100,000 times. You might only end up saving a second or two by restructuring the code (test this though!)
Anyway, if the flag is received at the start of the program, then you'd be able to write your code as
IF(<flag is present>) THEN
DO
...
CALL <subroutine name>
...
ENDDO
ELSE
DO
...
ENDDO
ENDIF
where the second DO loop omits the subroutine CALL.
EDIT
As another alternative (that might be cheaper to implement) is to pre-process the data and have the flag keyed in at compile-time. This might make the user a bit annoyed to have to recompile the program when changing the flag, but it'd make your job easier.
Anyway, you'd have something like
DO
...
#ifdef <flag>
CALL <subroutine name>
#endif
ENDDO

Parameter 3 is not constant in call of system task $fwrite

I am using Xilinx ISE 10.1 to run some verilog code. In the code I want to write the register values of 3 registers in a file, cipher.txt. The following is the code snippet:
if (clk_count==528) begin
f1 = $fopen("cipher.txt", "w");
$fwrite(f1, "clk: %d", clk_count[11:0]);
$fwrite(f1, "plain: %h", plain[31:0]);
$fwrite(f1, "cipher: %h", cipher[31:0]);
$fclose(f1);
end
At the end of execution, the contents of cipher.txt is found as:
clk: %dplain: %hcipher: %h
There is no other error encountered, but a warning comes up corresponding to the 3 fwrite's:
Parameter 3 is not constant in call of system task $fwrite.
Parameter 3 is not constant in call of system task $fwrite.
Parameter 3 is not constant in call of system task $fwrite.
The values of the registers clk_count and cipher change on every clock cycle (value of register plain remains constant throughout), and the values are written to cipher.txt when clk_count equals 528 (indicated by the if statement)
Can anybody provide some insight and/or help me get past this hurdle?
Thanks.
It appears that ISE expects the arguments to $fwrite to be constant. The warnings are referring to clk_count[11:0], plain[31:0], and cipher[31:0], which are not constant. By definition they are changing each cycle so they are not known at compile time. This also explains why they are not printing and you are seeing %d and %h in the output.
There is nothing to my knowledge in the Verilog spec that requires the arguments to $fwrite be constant. The same code works as expected with Cadence Incisive. My guess is that it's a limitation of ISE, so you may want to check with Xilinx.
Possible work-arounds:
1) Use $swrite to create a string with the proper formatting. Then write the string to the file.
2) Try using an intermediate variable in the calls to $fwrite. Maybe the part-selects are throwing it off. e.g.
integer foo;
foo = clk_count[11:0];
$fwrite(... , foo , ...);
Either of those might work, or not.
Out of curiosity, if you remove the part-selects, and try to print clk_count without the [11:0] , do you get the same warnings?

How to really trap all errors with $etrap in Intersystems Caché?

I've been banging my head a lot because of this. In the way that $etrap (error handling special variable) was conceived you must be careful to really trap all errors. I've been partially successful in doing this. But I'm still missing something, because when run in user mode (application mode) there are internal Cache library errors that are still halting the application.
What I did was:
ProcessX(var)
set sc=$$ProcessXProtected(var)
w !,"after routine call"
quit sc
ProcessXProtected(var)
new $etrap
;This stops Cache from processing the error before this context. Code
; will resume at the line [w !,"after routine call"] above
set $etrap="set $ECODE = """" quit:$quit 0 quit"
set sc=1
set sc=$$ProcessHelper(var)
quit sc
ProcessHelper(var)
new $etrap
; this code tells Cache to keep unwindind error handling context up
; to the previous error handling.
set $etrap="quit:$quit 0 quit"
do AnyStuff^Anyplace(var)
quit 1
AnyStuffFoo(var)
; Call anything, which might in turn call many sub routines
; The important point is that we don't know how many contexts
; will be created from now on. So we must trap all errors, in any
; case.
;Call internal Cache library
quit
After all this, I can see that when I call the program from a prompt it works! But when I call from Cache Terminal Script (application mode, I was told) it fails and aborts the program (the error trapping mechanism doesn't work as expected).
Is is possible that an old-style error trap ($ZTRAP) is being set only in Usermode?
The documentation on this is pretty good, so I won't repeat it all here, but a key point is that $ZTRAP isn't New-ed in the same way as $ETRAP. In a way, it is "implicitly new-ed", in that its value only applies to the current stack level and subsequent calls. It reverts to any previous value once you Quit up past the level it was set in.
Also, I'm not sure if there's a defined order of precedence between $ETRAP and $ZTRAP handlers, but if $ZTRAP is of higher precedence, that would override your $ETRAPs.
You could try setting $ZTRAP yourself right before you call the library function. Set it to something different than $ETRAP so you can be sure which one was triggered.
Even that might not help though. If $ZTRAP is being set within the library function, the new value will be in effect, so this won't make a difference. This would only help you if the value of $ZTRAP came from somewhere further up the stack.
You didn't mention what library function caused this. My company has source code for some library functions, so if you can tell me the function name I'll see what I can find. Please give me the value of $ZVersion too so I can be sure we're talking about the same version of Cache.