Ada: Entry meaning - ada

I am an absolute beginner with Ada, and there's one thing I cannot find a concrete definition for - that's the statement entry.
I understand an entry with a barrier - if the barrier is true, the statement can execute and if false, the task is queued until it's evaluated to be true.
For example:
entry Get(Item : out Data_Item) when Number_In_Buffer /= 0 is
begin
...
end Get;
But what does it mean for the statement entry to appear without a following when statement?

ARM9.4 describes protected objects, which is where entry bodies (as in your code) occur.
It’s not clear from your question, but I think you’re describing a protected specification, with an entry declaration.
Declaration:
protected type Resource is
entry Seize;
procedure Release;
private
Busy : Boolean := False;
end Resource;
Corresponding body:
protected body Resource is
entry Seize when not Busy is
begin
Busy := True;
end Seize;
procedure Release is
begin
Busy := False;
end Release;
end Resource;
It is not the caller’s business how the entry is guarded, just that it is. One thing that’s caught me out a couple of times is that an entry body must have a guard; there are some circumstances (requeueing - search the Ada 95 Rationale II.9 for protected Event) where when True is OK.

An ENTRY is also a connection point for TASK communication. In the TASK definition, it is ENTRY. In the TASK BODY, it is an ACCEPT statement. So every ENTRY in a TASK definition has a corresponding ACCEPT in the TASK body.

Related

Deserialisation error and logging the partition, topic and offset

I am handling deserialisation error using the ErrorHandlingDeserialiser sent on my DefaultKafkaConsumerFactory.
I have code a custom
try (ErrorHandlingDeserializer<MyEvent> errorHandlingDeserializer = new ErrorHandlingDeserializer<>(theRealDeserialiser)) {
errorHandlingDeserializer.setFailedDeserializationFunction(myCustomFunction::apply);
return new DefaultKafkaConsumerFactory<>(getConsumerProperties(), consumerKeyDeserializer, errorHandlingDeserializer);
}
My custom function does some processing and publishes to a poison pill topic and returns null.
When a deserialisation error occurs, I would like to log the topic, partition and offset. The only way I can think of doing this is to stop returning null in the function and return a new sub type of MyEvent. My KafkaListener could then interrogate the new sub type.
I have a #KafkaListener component, which listens for the ConsumerRecord as follows:
#KafkaListner(....)
public void onMessage(ConsumerRecord<String, MyEvent> record) {
...
...
// if record.value instance of MyNewSubType
// I have access to the topic, partition and offset here, so I could log it here
// I'd have to check that the instance of MyEvent is actually my sub type representing a failed record.
}
Is this the way to do it? I know null has special meaning Kafka.
The downside of this sub type approach is, I'd have to create a subtype every type using the ErrorHandlingDeserialiser.
Don't use a function; instead, the thrown DeserializationException is passed directly the container's ErrorHandler.
The SeekToCurrentErrorHandler considers these exceptions to be fatal and won't retry them, it passes the record to the recoverer.
There is a provided DeadLetterPublishingRecoverer which sends the record.
See https://docs.spring.io/spring-kafka/docs/current/reference/html/#annotation-error-handling
and
https://docs.spring.io/spring-kafka/docs/current/reference/html/#dead-letters

asp.net VB best way to return result code

For asp.net framework 4.5 vb
I know that I can use a session variable.. but wondering if there is a more efficient way to return a variable (we call it a condition code) that we set almost in every function /sub being called.
Example
Function xyz(bla as String, blab as String) as dataset
.. do the deed
**Cond.code = -1**
Return ds
We use this Cond.code everywhere. Obviously it can not be a Public Shared variable... but want the most efficient way to always set a "condtion code" within any sub or function... It is valid, only from the time it is set, to the time it is checked by the calling function... so the lifetime is very short.
It's unclear what, exactly the condition code is used for. It's possible that a proper use of custom exception types would replace the need for it. However, if you really need it, it would be better to have it be returned by the method, rather than essentially setting a global, which is pretty rotten. What happens if two methods ever got called simultaneously? It's just brittle and unnecessarily confining.
For instance, you could make a container to hold the return value plus the condition code, like this:
Public Class ReturnValue(Of T)
Public Sub New(value As T, conditionCode As Integer)
Me.Value = value
Me.ConditionCode = conditionCode
End Sub
Public ReadOnly Property Value As T
Public ReadOnly ConditionCode As Integer
End Class
By requiring the code in the constructor, like that, it forces every method to always specify a condition code in its return value. That way it could never be forgotten:
Function xyz(bla As String, blab As String) As ReturnValue(Of DataSet)
' do the deed
Return New ReturnValue(ds, -1)
End Function
However, even then, I would still strongly recommend making the condition code use an enumeration or, at the very least, a set of constants. -1 isn't very self documenting.

Exception reason/message. Am I reinventing the wheel here?

I want some kind of mechanism to have more information about a caught exception. (Specifically exceptions I throw myself to abort transactions) I've looked around and pretty much the only thing I could find was "Use the info log". This to me does not seem like a good idea. For one it is cumbersome to access and find the last message. And it is limited in size so at some point the new messages won't even show up.
So my idea is the following: Create a class NuException and pass an instance of that through all methods store an instance in the class where the work methods are located. When I need to throw an exception I call a method on it similar to Global::error() but this one takes an identifier and a message.
Once I reach my catch block I can access those from my object the class that contains the work methods similarly to how CLRExceptions work.
class NuException
{
"public" str identifier;
"public" str message;
public Exception error(str _id, str _msg)
{
//set fields
return Exception::Error;
}
}
class Worker
{
"public" NuException exception;
void foo()
{
throw this.exception.error("Foo", "Record Foo already exists");
}
void bar()
{
this.foo();
}
}
void Job()
{
Worker w = new Worker();
try
{
w.bar(ex);
}
catch (Exception::Error)
{
info(w.exception().message());
}
}
It works but isn't there a better way? Surely someone must have come up with a solution to work around this shortcoming in AX?
Short answer: yes.
While your "brilliant" scheme "works", it gets boring pretty fast, as you now must transport your NuException object deep down 20 level from the listener (job) to the thrower (foo). Your bar method and other middle men has no interest or knowledge about your exception scheme but must pass it on anyway.
This is no longer the case after the update.
There are several ways to go.
Use an observer pattern like the Event broker or in AX 2012 and newer use delegates.
Stick to the infolog system and you use an InfoAction class to peggy bag your information to be used later. It can be used to display a stack trace or other interesting information.
Use a dedicated table for logging.
The third way may seem impractical, as any errors will undo the insert in the log. This is the default behavior but can be circumvented.
MyLogTable log;
Connection con = new UserConnection();
con.ttsBegin();
log.setConnection(con);
... // Set your fields
log.insert();
con.ttsCommit();
Your way to go depends on circumstances you do not mention.

Can’t write aggregate for protected type

I have the following function
function Allocate(V : Value_Type; N : access Node) return access Node is
begin
return new Node'(Value => V, Next => N);
end Allocate;
on compilation, GNAT complains about expecting an access to Node, yet finding a composite type. This seems broken.
Node is:
protected type Node is
--Various routines
private
Value : Value_Type;
Next : access Node;
end Node;
I've reverted back to non tasking types, and don't have the exact error message. It's one I've seen numerous times when, for example, just using:
return (Value => V, Next => N);
or similar. I have never seen it when using "new Type'()".
Correct, there are no aggregates for protected types. As Simon said in his answer, protected fields are private and are only visible within the body of the protected type (or possibly later in the private part of the protected type). The outside world can't see the fields at all. So you have to add a protected procedure to set the fields:
protected type Node is
--Various routines
procedure Set_Value(V : Value_Type);
procedure Set_Next(N : access Node);
private
Value : Value_Type;
Next : access Node;
end Node;
and call the procedures in your Allocate:
function Allocate (V : Boolean; N : access Node) return access Node is
New_Node : access Node;
begin
New_Node := new Node;
New_Node.Set_Value (V);
New_Node.Set_Next (N);
return New_Node;
end Allocate;
(Or use an extended return as in Simon's answer--I think it will work.)
NOTE: I have not tested this.
The other possibility, if Value and Next will never change throughout the life of the protected object, is to use discriminants:
protected type Node (Value : Value_Type; Next : access Node) is ...
and now you can say
return new Node(Value => V, Next => N);
Note that there is no tick mark in this syntax! I haven't tested this, though, so I'm not sure it will work. I think it's acceptable to have a reference to the same type in the discriminant list, but I'm not sure.
The only place where Value and Next are visible (aside from the private part of Node’s spec, of course) is in their own Node’s body.
I can’t see a way of writing Allocate within Node. I gave up at
function Allocate (V : Boolean) return access Node is
begin
return N : access Node do
N := new Node;
N.Next := Node'Access;
N.Value := V;
end return;
end Allocate;
having got messages along the way including
protected function cannot modify protected object
protected type cannot be used as type mark within its own spec or body (so you can't say Node'Access)
invisible selector "Value" for type “Node"
so I think you’d need to use a wrapper of some sort.

Is it possible to return from the *calling* method using IL?

There's an annoying quirk in the way Response.Redirect works: you almost always want to terminate excecution right away and jump to the new page:
If ThisIsTheWrongPage Then
Response.Redirect(sUrl, False)
End If
'this code should not execute
DoSomethingWithThisPage
But Response.Redirect doesn't end execution, it just keeps on going and executes the subsequent lines of code. This is causing a lot of havoc in a legacy app I'm maintaining. So you have to do this:
If ThisIsTheWrongPage Then
Response.Redirect(sUrl, False)
Return
End If
What I would like to do is implement a method like this:
Sub RedirectToUrl(sUrl As String)
'redirect to the specified url
HttpContext.Current.Response.Redirect(sUrl, False)
'return from the CALLING method
End Sub
And then I could write this:
If ThisIsTheWrongPage Then
RedirectToUrl(sUrl)
End If
And not have to worry about the missing Return statement. I know it's not hard to write that return statement, but there are about 1,000 of these in the code, and new ones being added, and I want a method that the developer can call and not have to be careful about that Return statement. It's a bug just waiting to happen.
I know there's no way to do this in traditional .NET code, but I was wondering if it could be implemented in IL, to pop the stack twice and jump to the calling method's return location.
This is not possible. You'd be breaking invariants of the calling method. It would be unpredictable what happens when you call a method that you didn't write.
Redirect has a parameter that can be set to make it throw a ThreadAbortException on the current thread. This is made exactly for your use case. It effectively aborts execution of the page.
The only way a method can change the return point of the method that invoked it is to throw an exception. Considering the way many web apps are written with exception handlers to keep pages from returning 500 errors to the user, it could be difficult to provide your desired behavior by throwing an exception.
One problem with instructing a caller to return is there would be no way to specify the return value of that method. Exceptions work around this by propagating the exception itself up the stack until a handler is found.
Have a look at this, it uses the jmp opcode,
maybe this fits your needs.
.assembly JumpTest{}
.module JumpTest.exe
.namespace Test{
.class public auto ansi JumpClass extends [mscorlib]System.Object {
.method public static void Main() cil managed{
.entrypoint
.maxstack 8
ldstr "start"
call void [mscorlib]System.Console::WriteLine(string)
ldstr ""
call void Test.JumpClass::Page(string)
ldstr "end"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public static void Page(string sUrl) cil managed{
ldc.i4.1 //always redirect in this test
brfalse.s target
jmp void Test.JumpClass::RedirectToUrl(string)
target:
ldstr "Page() stuff here"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public static void RedirectToUrl(string sUrl) cil managed{
ldstr "RedirectToUrl() stuff here"
call void [mscorlib]System.Console::WriteLine(string)
ret
}
}}

Resources