FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister   ProfileProfile   Log inLog in 


Unable to "Consult" assert(ed) 'time' data type - Exception r306 Unsupported interface 'time'

Post new topic   Reply to topic    discuss.visual-prolog.com Forum Index -> Visual Prolog
View previous topic :: View next topic  
Author Message
larryhoughton



Foothill Ranch
Joined: 04 Oct 2016
Posts: 9

PostPosted: 8 Jul 2017 16:48    Post subject: Unable to "Consult" assert(ed) 'time' data type - Exception r306 Unsupported interface 'time' Reply with quote

Hello,
I don't get it. The "time" data type "consult" works normally if I execute the "consult" before terminating the program instance that executes the assert and save to create my disk file.

However, if I restart the program and immediately execute "consult", to retrieve the disk file data, the exception below is thrown:
Exception in module: OneClass.exe
c:\program files (x86)\visual prolog 7.5\pfc\event\event4.pro(42) : error r306: Invalid object conversion from '<unknown>': unsupported interface 'time'


Everything in these scenarios (assert,save,consult) work as expected (including restarting the program and immediately executing a "consult") unless I am using the data type "time".

Note:
I am experimenting with using multiple classes in case that comes into play. Everything above happens in one class ("data") that gets instantiated before any of the failing code executes. Also all of the declarations are in the data class.

** Code snippets **
facts - availableFactDB
testTime : (time).

clauses
assert(testTime(time::new(2017,12,25,9,0,0)))
file::save ("availableFactsDB.dba",availableFactDB)
file::consult("availableFactsDB.dba",availableFactDB)

Any ideas?
Larry
Back to top
View user's profile Send private message
Martin Meyer



Frankfurt a.M., Germany
Joined: 14 Nov 2002
Posts: 223

PostPosted: 8 Jul 2017 21:47    Post subject: Reply with quote

Hello Larry,

time is an object type. What happens, when you save the fact database, is, that the addresses of the time objects are written to the file. And, when you restore the database by consult, you are reading back these addresses. However the objects are not there anymore at the addresses. VIP attempts to interprete the random crap, which is now in memory at these address, as time objects - that results in an exception.

To store and restore objects you have to serialize them. That is, you have code a routine, which saves the object's data, and another one, which reads the data back and (re-)creates the objects. The data of a time object can be obtained from property gmtTimeValue, and time objects can be (re-)created from it. So, it works for example like:

class facts - availableFactDB
    testTime : (time).

class predicates
    saveTestTime : (string FileName).
clauses
    saveTestTime(Filename) :-
        OutStream = outputStream_file::create(Filename, stream::binary),
        try
            foreach testTime(Time) do
                OutStream:write(Time:gmtTimeValue)
            end foreach
        finally
            OutStream:close()
        end try.

class predicates
    consultTestTime : (string FileName).
clauses
    consultTestTime(Filename) :-
        InStream = inputStream_file::openFile(Filename, stream::binary),
        try
            foreach InStream:repeatToEndOfStream() do
                GmtTimeValue = InStream:read(),
                Time = time::newFromGMT(GmtTimeValue),
                assert(testTime(Time))
            end foreach
        finally
            InStream:close()
        end try.

class predicates
    displayTestTime : ().
class facts
    formatter : timeFormatter := timeFormatter::new().
clauses
    displayTestTime() :-
        foreach testTime(Time) do
            Formated = formatter:formatDateTime(Time, "dddd MMM dd',' yyyy", " 'at' H:mm'"),
            stdIO::write(Formated, '\n')
        end foreach,
        stdIO::write("===\n").

clauses
    run() :-
        assert(testTime(time::new(2017, 01, 05, 03, 00, 0))),
        assert(testTime(time::new(2017, 12, 22, 09, 00, 0))),
        assert(testTime(time::new(2017, 11, 23, 17, 00, 0))),
        displayTestTime(),
        saveTestTime("availableFactsDB.dba"),
        retractAll(testTime(_)),
        consultTestTime("availableFactsDB.dba"),
        displayTestTime().


_________________
Regards Martin
Back to top
View user's profile Send private message
Harrison Pratt



Des Moines, Iowa USA
Joined: 05 Nov 2000
Posts: 312

PostPosted: 9 Jul 2017 13:03    Post subject: Reply with quote

Hi Martin,

Thanks for the very crisp tutorial on serializing -- something I'll need to know soon!
Back to top
View user's profile Send private message
larryhoughton



Foothill Ranch
Joined: 04 Oct 2016
Posts: 9

PostPosted: 9 Jul 2017 19:35    Post subject: I want my cake and eat it too Reply with quote

Hi Martin,
Thanks for your quick response. My need is to keep track of possibly thousands of date/time db records along with their related attributes in a compound domain. I'm looking for some guidance here because the date/time storage and comparison methods will be critical to my program's performance.

I can see (now) that it would be simple enough to serialize the time objects for storage and retrieval, but it seems like a lot of processing whereas I suppose I could just as easily(?) store the date/time data as individual integers (e.g. mm/dd/yyyy/hh/mm).

Storing time as integers - Pros:
    My data file time entries would be human readable.
    "Consult" would work on the stored integers
    avoid the overhead of serialization
Storing time as integers - Cons:
    Without the time object, I don't get the time *methods (for date/time comparisons etc.).
    I inherit the overhead of making my own *"time methods".
*Cake and Eat it Too?
    Save the date/time data as integers (e.g. mm/dd/yyyy/hh/mm)
    Create a new <time object> from the retrieved integer data and.....
    Again have the time object methods that I lost when saving the date/time as integers
Hopefully there is a known answer for my dilemma. My primary priority will be efficiency in retrieving and comparing dates/times.

Note:
I'm using "Save/Consult" now, but I will be moving to DB Chains once I get some of these fundamental issues sorted out.

Thanks in advance,
Larry
Back to top
View user's profile Send private message
Martin Meyer



Frankfurt a.M., Germany
Joined: 14 Nov 2002
Posts: 223

PostPosted: 10 Jul 2017 0:54    Post subject: Reply with quote

The values of domain gmtTimeValue are simply 64 bit numbers. Its declaration in class core is:

domains
    gmtTimeValue = unsigned64.

To invent your own date/times coded in integers is no good idea. It would cost you needless efforts. Better go with the flow and just rely on the rich choice of well tested functionalities in the time package.

Generally VIP and the pfc (Prolog Foundation Classes) are making extensive use of objects, it is not only time. When you want to store objects, serialization is inevitable. Do not see a dilemma there, it is just a standard programming technique. Maybe in a future version VIP will support automatic object serialization. But until that, write your own serialization code per object type that you want to store/restore.

When you have a large number of data sentences, but you are processing only some of them selectively, hold date/times in the gross of your data as gmtTimeValue numbers. When you pick up one data sentence from the gross for processing, 'unpack' it, i.e. construct the time object from the gmtTimeValue. That is more efficient than constructing the time objects of all data sentences right away.

When you are searching in larger amounts of data, do not store the data in a fact database, because that is slow. I suppose VIP just tries one fact after the other to find matches. Thus searching is in O(n) where n is the number of facts in the database.

Identify "keys" in your data. I.e. small sub-fields in your data containing the values, which you want to match in your searches. Typically keys are numbers containing person IDs, item IDs, date/time values, etc. or maybe strings containing names.

For searching data by a key collections based on trees (construct them for example from class mapM_redBlack{@Key, @Data}) offer a good runtime growth rate with respect to the number of items in the collection. Searching in a tree-based collection is in O(log(n)) (provided two keys can be compared in constant time). If your keys are positive numbers, use a collection based on an array (i.e. class arrayM{@ItemType}). Retrieval time then is even better, it is in O(1).

If you have very large amounts of data, consider using a database system like for example MariaDB via the ODBC package. But do not use the chainDB package. The package is kind of deprecated. Thomas said it is only still there for reasons of backwards compatibility. I guess he will kick it out in future VIP versions.

_________________
Regards Martin
Back to top
View user's profile Send private message
larryhoughton



Foothill Ranch
Joined: 04 Oct 2016
Posts: 9

PostPosted: 30 Jul 2017 6:23    Post subject: Reply with quote

Hi Martin,
I've taken all of your excellent advice. It took a while, but I have everything working nicely now with MS SQL and file stream storage/retrieval of Prolog Fact subsets (as needed) for Prolog processing. Thanks again.
Larry
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    discuss.visual-prolog.com Forum Index -> Visual Prolog All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum