Vulcan runtime, DBFCDX order seek failure on customers machine

  • wriedmann
  • wriedmann's Avatar Topic Author
  • Away
More
2 weeks 16 hours ago #1 by wriedmann
Hello,

I have a problem with a VO compatible application that uses the Vulcan runtime (I need DBFCDX).
On my machine a seek works as expected, and on my customers machine the seek fails.
The files are the same (I have copied them over from the customers machine), and I have made sure that I have copied all Vulcan runtime DLLs to the customers machine.
And yes, I'm using SetCollation( #Clipper ), and SetInternational( #Clipper ).

Any ideas?

Wolfgang

Please Log in or Create an account to join the conversation.

More
2 weeks 16 hours ago #2 by Karl-Heinz
Hi Wolfgang,

are there differences in the "Seek ()" and "Found" results ?

if oDB:seek ( ...)
? "found"

else
? "not found"

endif

//

oDB:seek ( ... )

if oDB:Found
? "found"

else
? "not found"

endif


regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

  • wriedmann
  • wriedmann's Avatar Topic Author
  • Away
More
2 weeks 15 hours ago #3 by wriedmann
Hi Karl-Heinz,

on the customers machine the following code
oServer 	:= DBServer{ cPath, true, false, "DBFCDX" }
System.Console.WriteLine( "SetOrder(" + cOrder + ") returns " + AsString( oServer:SetOrder( cOrder ) ) )
System.Console.WriteLine( "Seek(" + cSeek + ") returns " + AsString( oServer:Seek( cSeek, true ) ) )
System.Console.WriteLine( "EOF returns " + AsString( oServer:EOF ) )
System.Console.WriteLine( "Kdnr is " + AsString( oServer:FieldGet( #Kdnr ) ) )

returns
Hello x#!
SetOrder(KDNR) returns .F.
Seek(MOSER) returns .F.
EOF returns .F.
Kdnr is 0001

On my machine instead it returns
Hello x#!
SetOrder(KDNR) returns .T.
Seek(MOSER) returns .T.
EOF returns .F.
Kdnr is MOSER

Wolfgang

Please Log in or Create an account to join the conversation.

  • wriedmann
  • wriedmann's Avatar Topic Author
  • Away
More
2 weeks 15 hours ago #4 by wriedmann
Hello,

yes, and the application is using the VO dialect, so the InitVulcan() call should not be needed.

On my machine, Vulcan is installed, so I have all DLLs in the GAC. But I have triple checked if all DLLs that the application loads on my machine are installed also on the customers machine.

Is there any setting put when Vulcan is installed?

Wolfgang

Please Log in or Create an account to join the conversation.

  • wriedmann
  • wriedmann's Avatar Topic Author
  • Away
More
2 weeks 14 hours ago #5 by wriedmann
Hi Karl-Heinz,

the customers machine is a WIndows Server 2012 foundation.

I have now copied the following two files into the program folder:
msvcp100.dll
msvcr100.dll

and now it works as expected.

It seems that these DLLs are available on Windows 10, but not on Server 2012 or Windows 8.x.

Wolfgang

Please Log in or Create an account to join the conversation.

More
2 weeks 13 hours ago #6 by Karl-Heinz
Hi Wolfgang,

> Hello x#!
> SetOrder(KDNR) returns .F.
> Seek(MOSER) returns .F.
> EOF returns .F.
> Kdnr is 0001

so already SetOrder() fails.

> I have now copied the following two files into the program folder:
> msvcp100.dll
> msvcr100.dll

Seems that some Visual C ++ Redistributable Package is missing, so I would not simply copy the DLLs to another PC. i do have both Dlls in my win 8.1 system32 and syswow64 dir, all have the datestamp 11.06.2011

Strange, that at runtime no errorbox like "xxxx.dll is missing" is shown.

regards
Karl-Heinz

Please Log in or Create an account to join the conversation.

More
2 weeks 12 hours ago #7 by robert
Karl-Heinz, Wolfgang,

The DbServer class "swallows" all the errors. After a failed SetIndex(), SetOrder() etc, you need to check the dbServer:Status. This most likely has a hyperlabel with a message describing the problem. You need to do that immediately. Every operation can/may reset the status.
This is a "built-in" problem of the VO classes. I think this is designed badly but we can't change that anymore: A failed operation should not return FALSE but generate an error/exception. People quite often forget to check the return value of an operation and almost never check the status of the Server object.

Robert

XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.

Please Log in or Create an account to join the conversation.

  • wriedmann
  • wriedmann's Avatar Topic Author
  • Away
More
2 weeks 11 hours ago #8 by wriedmann
Hi Robert,

thank you for this explanation!

Wolfgang

Please Log in or Create an account to join the conversation.

More
1 week 1 day ago - 1 week 1 day ago #9 by g.bunzel@domonet.de
Replied by g.bunzel@domonet.de on topic Vulcan runtime, DBFCDX order seek failure on customers machine
Robert,

>This is a "built-in" problem of the VO classes. I think this is designed badly but we can't change that anymore

I check all return values of every SetOrder(), SetRelation(), ....
Is that return value a problem of the Vulcan runtime or will this also be a problem in the X# runtime?
I would not be pleased to have to change all these checks to status.

Thanks in advance

Best regards

Gerhard
Last edit: 1 week 1 day ago by g.bunzel@domonet.de.

Please Log in or Create an account to join the conversation.

More
1 week 1 day ago #10 by Chris
Hi Gerhard,

No, no, in both vulcan and x# it works like in VO, you still get a TRUE/FALSE return value (success yes/no) from those functions/methods and dbServer:Status can be used the same way.

Robert was suggesting that it would had been better if the SDK classes were designed from the beginnning in such a way to throw exceptions when something failed (because for example if a Skip() fails, then it very rarely makes sense to execute the next commands of the code after it), but of course we will not be making such major changes to the SDK now, as that would indeed break a lot of existing code as you pointed out.

Chris

XSharp Development Team
chris(at)xsharp.eu

Please Log in or Create an account to join the conversation.

More
1 week 18 hours ago - 1 week 18 hours ago #11 by robert
Gerhard,

No need to change that. We will not change that behavior in the VO SDK classes.
I commented about that, because experience shows that many people simply ignore these return values. Converting the code to throw exceptions in stead would make that impossible, and is something that should be done in new code.
In fact inside our RDD system we are already doing that.
The old (Clipper - VO - Vulcan) code was returning success or failure from the RDD layer to the runtime in a similar way. That mean that a property such as EOF had to be read by the runtime by passing a logical value by reference to a method in the RDD. The return value of the method indicated success or failure and on success the value by reference would return the EOF state.
We have changed this now. EOF is a property of the RDD. When a problem happens then the RDD will throw an exception.
That makes the interface of the RDD somewhat easier.
Of course we now have to catch the exceptions in a layer inside the runtime, because in the end the functions such as DbGoTop() still need to return TRUE or FALSE.
If you look into the docs for the CoreDb.Eof() method you will see this
github.com/X-Sharp/XSharpPublic/blob/fea....Core/RDD/CoreDb.prg
The method on line 555 looks like this:

    STATIC METHOD Eof() AS LOGIC
        RETURN CoreDb.Do ({ =>
        LOCAL oRDD := CoreDb.CWA(__FUNCTION__) AS IRDD
        RETURN oRDD:EoF
})

- The code inside the CoreDb() call is a multi line lambda expression (a kind of codeblock on steroids, sometimes called an unnamed function)
- The CoreDb.CWA method returns the current workarea as an IRDD interface. It also clears the LastRDDError property in the runtimestate and throws an exception when there is no table open in the current workarea.
- We are returning the EOF property of that interface
- The CoreDb.Do construct around it is a convenient way to wrap this code with a generic protocol to have a try catch and store the exception in a common location. It uses some new mechanism in .Net. This method looks like this:
   INTERNAL STATIC METHOD Do<T>(action AS @@func<t>) AS T
        TRY
            RETURN action()
        CATCH e AS RddError
            RuntimeState.LastRDDError := e
        END TRY
RETURN DEFAULT(T)

This is a generic method that will return a type T. The Type is determined by the return type of the code that gets passed in the action parameter. In this case the action is oRDD:EOF so the return type is Logic.
If an exception occurs then the exception is stored in the Runtimestate and an empty LOGIC (false) is returned.
If you look in this source you will see that most of the RDD methods are encapsulated in a call to CoreDb.Do() to standardize the error handling.

In short:
There is no need to change anything in your code.


Robert

PS Sorry for the long answer. It was a nice excuse to explain some of what we have done in the RDD system. Maybe Wolfgang can add some of this to his docs ? ;)

XSharp Development Team
The Netherlands
This email address is being protected from spambots. You need JavaScript enabled to view it.
Last edit: 1 week 18 hours ago by robert.

Please Log in or Create an account to join the conversation.

  • wriedmann
  • wriedmann's Avatar Topic Author
  • Away
More
1 week 17 hours ago #12 by wriedmann
Hi Robert,

first: thank you very much for explaining this - it is a very useful insight how to the runtime is working internally, and a wonderful sample for us.
and second: of course I will add that to the docs wiki and let you know when it is added.

Wolfgang

Please Log in or Create an account to join the conversation.

More
6 days 15 hours ago #13 by g.bunzel@domonet.de
Replied by g.bunzel@domonet.de on topic Vulcan runtime, DBFCDX order seek failure on customers machine
Hi Chris and Robert,

thanks for your answers.
That are good infos. It sounds to me, that there is a problem with the return value of that functions/methods.

Thanks again and best regards

Gerhard

Please Log in or Create an account to join the conversation.