Home AMX User Forum AMX General Discussion

Persistence in Structure?

I posted this in the ViewStat Scheduler but no one responded there so I'll ask it here.

Question! Persistence in structures. How do you go about getting this to work? I declared everything possible as persistent and have code to check for valid data upon start up so I don't re-load the defaults but upon ever program upload I keep ending up with the defaults being loaded and to my understanding they shouldn't be providing my data checking method is working?

You can declare the structure persistent but you can't add a persistent storage modifier to a structure members. So should my structure values remain at last set values after a program upload or not. That's is of course providing I'm not re-writing them with my DEFINE_START default values structure loading.

I guess I could just comment out the applicable define_start code and try it but that code looks good and runs a function to test for lenght string of key variables and if there something there it should abort the default loading.

The code example is in the Viewstat scheduler module posted in code examples if any one wants to review the code to see if its faulty.

Comments

  • Joe HebertJoe Hebert Posts: 2,159
    No PERSISTENCE in modules

    PERSISTENT variables (and therefore structures) don’t work in modules. Bummer I know…

    PERSISTENT variables and structures work fine in the main source file or include files.

    The only work around that I know of is to declare the variables as PERSITENT in your main source file (or include file) and then pass them INTO the module as a parameter. Kinda defeats the purpose of a module though.

    See tech note 480.
  • Joe HebertJoe Hebert Posts: 2,159
    And as a follow up, you can't pass in STRUCTUREs into a module. But you can pass in multi-dimensioned arrays.
  • vining wrote:
    I posted this in the ViewStat Scheduler but no one responded there so I'll ask it here.

    Question! Persistence in structures. How do you go about getting this to work? I declared everything possible as persistent and have code to check for valid data upon start up so I don't re-load the defaults but upon ever program upload I keep ending up with the defaults being loaded and to my understanding they shouldn't be providing my data checking method is working?

    You can declare the structure persistent but you can't add a persistent storage modifier to a structure members. So should my structure values remain at last set values after a program upload or not. That's is of course providing I'm not re-writing them with my DEFINE_START default values structure loading.

    I guess I could just comment out the applicable define_start code and try it but that code looks good and runs a function to test for lenght string of key variables and if there something there it should abort the default loading.

    The code example is in the Viewstat scheduler module posted in code examples if any one wants to review the code to see if its faulty.

    It's not possible to define single structure elements as PERSISTENT, but only the whole structure.

    A PERSISTENT variable will hold it's current value at reboot, and at new program download as long as a variable of same type exists in the new code. But it will be overwritten if values are set to it in DEFINE_START (of course).

    If you have predefined a PERSISTENT variable in DEFINE_VARIABLE with values, these values again are only loaded the really first time.
    DEFINE_VARIABLE
    PERSISTENT INTEGER nMyVal = 3333
    
    DEFINE_PROGRAM
    PUSH[dvPanel,1]
    {
    nMyVal = 4444
    }
    
    If you have pushed button 1 and so set nMyVal to 4444, this value will be hold also at download/reboot, it's not overwritten with the 3333 default again.

    PERSISTENTs can not be created within modules, but it's possible to pass a PERSISTENT variable into a module as a parameter.
  • Joe Hebert wrote:
    And as a follow up, you can't pass in STRUCTUREs into a module. But you can pass in multi-dimensioned arrays.

    Dreaming of passing Structures into modules.... :rolleyes:
  • Joe HebertJoe Hebert Posts: 2,159
    Dreaming of passing Structures into modules.... :rolleyes:
    Yup, that and passing in parameters (like the number 1, or a literal string) without having to declare it as a variable first. :rolleyes:
  • DHawthorneDHawthorne Posts: 4,584
    I pass the elements of the structure to my module as persistent variables, then rebuild the structure inside the module on start up. For a very simplified example, if you have a structure that has these elements:

    STRUCT strPerson
    { CHAR sName[50]
    INTEGER nNumber }

    and an array in the module of these structures:

    strPerson perDataBase[500]

    You can declare in your main code:

    PERSISTENT CHAR sNameStore[50][500]
    PERSISTEN INTEGER nNumStore[500]

    You pass sNameStore and nNumStore to your module as parameters, and in the DEFINE_START of the module, make a for loop that populates perDataBase with the elements of sNameStore and nNumStore.

    Of course, this uses twice the memory since you now have two copies of your database, and it's awkward as heck with complex structures, but it does work. I've found, in general, that it is usually easier to use similarly indexed arrays rather than structures when they need to be persistent.
  • yuriyuri Posts: 861
    you could read in from an .xml file at startup using XML_TO_VARIABLE. That way you dont use up memory
  • Joe HebertJoe Hebert Posts: 2,159
    Yes, XML_TO_VARIABLE and VARIABLE_TO_XML are powerful functions and the help file does a good job explaining how to use them. One thing to keep in mind is if you need to instantiate more than one of your modules per project, then you will probably need to pass in another parameter (perhaps a directory name) to differentiate the XML files for each module instance that need to be written to the DOC.
  • viningvining Posts: 4,368
    I know I can't pass a structure to a module and the module in question gets created with in the module and works fine, just not persistent. I did declare the entire structure perssitent but that didn't work.

    Joe's reference to tech note 480:

    piece of the tech note:
    Why don't persistent variables work in modules?
    With modules there is the potential for a number of variables with the same name but located in different instances of a particular module. Since these duplicate variables all have the same name, source location (filename), and type - a fourth attribute would have to be determined. This has not yet been done.

    This is where I got screwed which sort of makes sense much to my chagrin.

    I could live w/o persistence but t-stats schedule programs really, kinda, sort of should be.

    I'll have to ponder the possiblities posted to see which one will prevail. The structures in question are somewhat complex and layered, some things reside in the first level of the structure while other reside in the structures with in the structure so I not sure if any of the methods will be much fun. It really would be nice if the persistent classification would just work especially when this module will never need more than one instance.

    It's ironic, I finally decide to give a module a try, mostly just to say I did it, and now it's srewing me. Boy do I feel cheap!
  • GSLogicGSLogic Posts: 562
    Since we can't use a persistence variable in a module, I store it in an XML file which I load into the module structure at startup, any changes to the structure I save back to the XML file.
  • viningvining Posts: 4,368
    How well does it handle conversion to xml on a complex structure?
  • i am all for the file storage as well.

    the only persistent i try to use now is for an encrpyted password. that way it's not stored in a file, so even i can't get to the user-set password (well, i could if i really wanted to i know).

    also, setup automated backups of the files. then, heaven forbid, if a controller needs to be swapped out, you have all the customised data ready in a file.

    but, i tested the following code, and persistent does work in the structure.
    _________________________________________
    define_type

    STRUCTURE MyStruct
    {
    integer number
    integer second
    }

    define_variable

    persistent MyStruct testStruct[1]
    _________________________________________


    so i guess you are left with passing structures to modules and the related issues.
  • viningvining Posts: 4,368
    But what amount a structure like this:
    structure sVST_Setting
    
         {
         char cVST_Time[11] ;
         integer nVST_HTemp ;
         integer nVST_CTemp ;
         }
         
    structure sVST_Days
    
         {
         sVST_Setting sVSTSet[4] ;
         }
         
    structure sVST_Stat
    
         {
         sVST_Days sVSTDay[7] ;
         char cVST_Z_NAME[18] ;  //18 is max numbers that fits in vt field at font size.
         char cVST_HoldReleaseTime[8] ;
         integer nVST_Hold ;
         integer nVST_Hold_24 ;
         integer nVST_SchedMode ;
         }
    

    The top structure is used in the second structure. The second structure which contains the first is used in the third which is the structure I use to hold my data and reference in my code.

    Attached is a debug screenshot of the structure in question that I'm using in the module.
  • viningvining Posts: 4,368
    Rich wrote:
    i tested the following code, and persistent does work in the structure.

    My previous post wasn't the proper response to your post, I was still thinking xml and my first reading of your post said that structures to xml work fine when in fact you said persistence in structures work fine.

    Yeah, it ended up not being a persistent structure problem but a no persistence at all inside a module unless done in manners descibe by other forum members.
  • yes, i tested that code and persistent still worked.

    (i had to change sVSTSet[4] to sVSTSet[1] and sVSTDay[7] to sVSTDay[1] to that i could view them and change them in the debug window, too large to update otherwise).

    i changed the values for
    cVST_Time[11] ;
    nVST_HTemp ;
    nVST_CTemp ;

    within debug and reset the controller. i also re-powered the controller. in both cases persistent did work.

    be aware that if you modify your program and upload that any persistent values get reset, as the controller sees this as a 'new' program and removes any persistents. this is another good reason to be using file storage instead.
  • viningvining Posts: 4,368
    Rich,

    Another piece of Joe's reference of tech note 480.
    How do persistent variables keep their value?
    When you reboot after downloading a new program, the master loads the new program into memory before erasing the old one. The master searches through the two programs for matching persistent variables; i.e., a variable with the same variable name, source location (filename), and variable type. It then updates the new program with the persistent values from the old, and when it's finished, it deletes the old program from memory.

    Why can't I use CLEAN DISK to reset the value of persistent variables?
    CLEAN DISK does not clear the RAM memory. That's where the values are stored (with the rest of the running program).

    What are some ways to reset the value of persistent variables?
    To clear all the values - change the name of the program, download, and reboot.
    To clear all the values - download a different program, reboot.
    To clear one value - change it's name; e.g., rename "nFlag" to "Flag".
    To clear one value - change it's type; e.g., instead of declaring "Flag" as INTEGER, declare it as LONG or CHAR.

    If this is true and I believe it is, persistant values should remain after a new program upload. This is also my recollection from pro II class which is why I set up functions in DEFINE_START to check for values in the structures before loading them with deafaults. If there was data it would abort the default loading process. All should have worked fine and most likely would have if it wasn't in the module.
  • thanks for that tech note. i'll keep that in mind.

    and yeah, all this is probably due to using it in a module :)
  • DHawthorneDHawthorne Posts: 4,584
    vining wrote:
    Rich,

    Another piece of Joe's reference of tech note 480.



    If this is true and I believe it is, persistant values should remain after a new program upload. This is also my recollection from pro II class which is why I set up functions in DEFINE_START to check for values in the structures before loading them with deafaults. If there was data it would abort the default loading process. All should have worked fine and most likely would have if it wasn't in the module.

    Persistent variables definitely persist with program changes. I just had to pull out a bad NI-2000 and temporarily swap it with my bench NI-3000 unit while it gets repaired. Even after doing a "clean doc" on it and loading all the customer files, the location info for his weather page remained that of my office, because the same module was running on both and used a persistent variable to store the location. I had to change it in debug to make it correct.
  • yeah, this is right that persistents are retained, i should have not forgetten that process, just got a bit sloppy sorry :)

    and that weather thing with swapping the controllers... a great example of why it might be better to use xml files. simply copy the right file to the right controller, nothing to debug.

    admittedly sometimes there is only a small bit of data to debug. but if you forget to do it, or there are more related data items, structures etc, debug can get real messy.

    try to debug-edit the complex structure supplied before and debug will report that it cannot update the data chunk because it's to large. that's why i reduced the number of elements for the test.

    but if it's in a data file, simply edit the file on your local pc and then upload it. you may have to reboot, or provide a service that refreshs the data from the file after uploading.

    unfortunately Netlinx doesn't record file modifiication date/times (ok, that i know of). if we could check for date/time change of a file say every minute (better still, if it was an event), and reload it if the date changed it would make for easier auto updating of data.
Sign In or Register to comment.