[Integration Kit Contents] [Integration Kit What's New] [Integration Kit Function Index] [More Documentation] [PTC]

Persistent Data Storage

Concepts

The Persistent Data Storage (PDS) System provides the ability to save data from one Creo Elements/Direct Modeling session to the next Creo Elements/Direct Modeling session. Data added to the PDS System is automatically saved to PDS files on System exit. If a data entry is inquired during the next Creo Elements/Direct Modeling session the PDS System ensures that the file containing the entry is loaded and the previously stored value is retrieved.

A PDS data entry is defined by a 2-level key and its value. The first level key, called module key, usually describes the environment for which the PDS data is defined. A module key must correspond to an internal application name. The available applications are stored in an internal table. The initial contents of this table is written to 'README.txt' in the user customization directory. The internal application name corresponds to the fourth column. Since a new application can be defined using the Integration Kit an interface is provided to add new entries to the internal application table. The second level key, called property key, identifies the entry within the underlying environment defined by the module key. A property key must be unique within its environment. Both, module and property key, are of type string and are by definition not case sensitive. Typical values for data entries are boolean, strings, numbers, and any kind of lists.

For each module key a separate file is created when Creo Elements/Direct Modeling terminates. PDS file names obey to the common customization file naming conventions. That is, a module key must correspond to an internal application name. The associated PDS file will be written to the corresponding subdirectory in the user customization directory. Its name is composed of the application prefix and the base name "data". Since we write PDS files in LISP format we use the ".lsp" suffix. Assume module key is set to "ANNOTATION" then the PDS file created on system exit will be written to

   '<user_cust_dir>/ANNOTATION/am_data.lsp'

When writing a PDS file the former version - if existing - is overwritten.

Function Index Top of Page

Interface

For programmers functions are available to set, get, and remove data entries from the PDS System.

SD-SET-PERSISTENT-DATA  [function]

(sd-set-persistent-data module_key property_key data
                        :subkey     subkey
                        :store-flag store-flag)
Description
Adds a new data entry to or replaces an existing data entry in the PDS System.
Parameters
module_key {STRING}
Specifies environment in which to store the entry. The key is used to determine file location and file prefix.
property_key {STRING}
Identifies the entry in the scope specified by the module key.
data {LISP-list or common LISP data type [nil]}
Entry that is to be added to the PDS System.
:subkey {KEYWORD}
This option allows to easily build up or modify a property list as data value. If nothing was stored yet under the property_key a plist of the form (subkey data) is created and stored as data. If property_key had already a value, a new property with subkey and data is created or data of the subkey entry is modified. If the value of property_key is not a plist, subkey is ignored and data becomes the PDS value.
:store-flag {BOOLEAN [t]}
If set to t this data entry goes to the PDS file on system exit.
Return Value
Example
  (sd-set-persistent-data
    "ALL"                   ;; module key
    "UNITS"                 ;; property key
    '(:mass   (:g   1)      ;; data entry
      :angle  (:deg 1)
      :length (:mm  1))
    :store-flag t)          ;; store flag

  (sd-set-persistent-data
    "ALL"                   ;; module key
    "UNITS"                 ;; property key
    '(:inch  1)             ;; data entry
    :subkey :length         ;; modifies just the subkey :length value
    :store-flag t)          ;; store flag
  

Function Index Top of Page

SD-GET-PERSISTENT-DATA  [function]

(sd-get-persistent-data module_key property_key
                        :default default-value
                        :subkey  subkey)
Description
Gets the value of a data entry from the PDS System. If the entry does not exist the default value is returned.
If the default value is the same as the current PDS value (same for subvalues defined by subkey) and the factory default was not overwritten by a corp or site setting, the PDS subkey entry or the full PDS key is removed from the PDS system automatically.
Parameters
module_key {STRING}
Specifies environment from which to inquire the entry.
property_key {STRING}
Identifies the entry in the scope specified by the module key.
:default {LISP-list or common LISP data type [nil]}
Value returned when no entry was found.
:subkey {KEYWORD}
Allows access of a single key within the PDS value property list. Please see sd-set-persistent-data for more information. If subkey is given, default represents just the default of this single property list subkey.
Return Value
sd-get-persistent-data is a multiple-valued function. It returns the values (data found) where data equals to and found equals to
Example
  (multiple-value-bind
    (value found)
    (sd-get-persistent-data
      "ALL"                         ;; module key
      "UNITS"                       ;; property key
      :default '(:mass   (:g   1)   ;; return value when entry not found
                 :angle  (:deg 1)
                 :length (:mm  1)))
     (if found
         ;; then
         ....
         ;; else
         ....)
     ) ;; multiple-value-bind
  
or just using the return value no matter if the inquiry was successful or not:
  (setf value (sd-get-persistent-data
                "ALL"                          ;; module key
                "UNITS"                        ;; property key
                :default '(:mass   (:g   1)    ;; return value when entry not found
                           :angle  (:deg 1)
                           :length (:mm  1))))

  (setf value (sd-get-persistent-data
                "ALL"                          ;; module key
                "UNITS"                        ;; property key
                :default '(:mm  1)             ;; return value when entry not found
                :subkey  :length))             ;; access single entry of PDS value property list
  

Function Index Top of Page

SD-REMOVE-PERSISTENT-DATA  [function]

(sd-remove-persistent-data module_key property_key
                           :subkey subkey)
Description
Removes a data entry from the PDS System.
Parameters
module_key {STRING}
Specifies environment in which the entry is stored.
property_key {STRING}
Identifies the entry in the scope specified by the module key.
:subkey {KEYWORD}
Allows to delete a single property from the PDS value property list. Please see sd-set-persistent-data for more information.
Return Value
Example
  (sd-remove-persistent-data
    "ALL"        ;; module key
    "UNITS")     ;; property key
  

Function Index Top of Page

SD-SUBSCRIBE-INIT-PERSISTENT-DATA  [function]

(sd-subscribe-init-persistent-data function)
Description
Subscribes the provided function to the initialization event of the PDS System. For more information refer to Initialize Variables.
Parameters
function {SYMBOL}
The function to subscribe to the PDS initialization.
Note: As a rule, subscribed functions should ALWAYS include a &rest parameter.
Return Value
Example
  (defun init-fun (&rest args)
    (declare (ignore args))
    (multiple-value-bind
      (pos found)
      (sd-get-persistent-data
        "MY-MODULE" "POSITION"
        :default '(:x 0 :y 0))
      ;; do initialization
      ...)
    ) ;; defun
    
  (sd-subscribe-init-persistent-data #'init-fun)
  

Function Index Top of Page

SD-UNSUBSCRIBE-INIT-PERSISTENT-DATA  [function]

(sd-unsubscribe-init-persistent-data function)
Description
Removes the provided function from the subscription list of the PDS initialization.
Note: If the PDS System is re-initialized data set in the initialization function can't be updated. For more information refer to Initialize Variables.
Parameters
function {SYMBOL}
The function to remove from the PDS initialization.
Note: As a rule, subscribed functions should ALWAYS include a &rest parameter.
Return Value
Example
  (sd-unsubscribe-init-persistent-data #'init-fun)
  

Function Index Top of Page

Using the PDS System as a Programmer

An application needn't to meet special requirements to use the PDS System. Simply set, get, or remove data. What you need to take care on when using PDS is described here.

Initial Step

If your application is not listed in the internal application table you need to add your application data to the table before using the PDS interface. The next example shows how to add the necessary information.

  (sd-add-application-data "Annotation"   ;; internal application name
                           "ANNOTATION"   ;; application subdirectory
                           "am"           ;; application prefix
                           "Annotation")  ;; product name

There are two ways to check whether your application is element of the internal application table. Either you open the file "README.TXT" which you can find in your user customization directory or for a more programmatic way use the Integration Kit function sd-inq-application-data-p which returns t when your application has been already added.

  (sd-inq-application-data "Annotation")   ;; internal application name
        => t

Load PDS System

A programmer hasn't to care about loading the PDS System. The PDS interface functions ensure that the addressed PDS file is loaded on first access. That is, for example, the first call to a PDS function with the module key "ANNOTATION" causes the PDS System to load "<user_cust_dir>/ANNOTATION/am_data.lsp".

Initialize Variables

Usually during module activation global variables are initialized. This might be setting a flag or assigning a property list to the variable. Making such data persistent forces the programmer to slightly change the initialization.

At the best, the variable can be removed from the code. Its value is kept in the PDS System. If the program needs to inquire or set the value it just calls PDS functions. Initialization is done by the PDS System. Typical applications are variables that evaluate to a simple data type (e.g. a number).

Original Code Replaced by PDS based Code
(defvar *my-variable* ....)
        
;; not needed - data kept in PDS
        
(setq .... *my-variable*)
        
(sd-get-persistent-data
  "MY-MODULE" "PROPERTY" :default ...)
        
(setq *my-variable* ...)
        
(sd-set-persistent-data
  "MY-MODULE" "PROPERTY" ...)
        

Using an Initialization Function

Maybe there are reasons to preserve the existence of the global variable. In this case a programmer should provide an initialization function which can be added to the subscription list of the PDS initialization (see here for an example).
There is a scenario when the contents of the PDS System changes. If a user loads a session file the PDS System is re-initialized. All initialization functions subscribed to the PDS System are called. This ensures that the global variable is updated as well. Removing the initialization function from the subscription list prevents the PDS System from updating a global variable. A programmer needs to decide which approach to prefer.

Set a Data Entry

There are two cases we need to regard when setting a data entry. In the first case we add to or - if the entry already exists - we replace data in the PDS System.

  (sd-set-persistent-data "MY-MODULE" "MY-KEY" 4711)

There is no need to care about the old entry. Thus let's move directly to the second case. Assume we need to modify an existing entry which identifies a property list. We only want to change parts of these properties. In this case we need to inquire the data entry first. Second, apply the changes and, third, bring the entry back to the repository which replaces the old entry.

  (multiple-value-bind
    (entry found)
    
    ;; inquire existing entry - this call fills 'entry' and 'found'
    (sd-get-persistent-data "MY-MODULE" "MY-KEY")
    (if found
       ;; then - replace value
       (setf (getf entry :x) x_value)
       ;; else - new entry
       (setf entry `(:x ,x_value
                     :y 100))
       ) ;; if
    (sd-set-persistent-data "MY-MODULE" "MY-KEY" entry))

A good programming style is to provide a set (and of course a get) function to access a global variable. Prepared with such an infrastructure, making data persistent is just one step forward.

(defvar *my-property-list* ...)

(defun set-value (keywd value)
   (setf (getf keywd *my-property-list*) value)
   (sd-set-persistent-data "MY-MODULE" "MY-KEY" *my-property-list*))

Get a Data Entry

As mentioned in the previous paragraph, providing a get function is a good style. It makes it easy to exchange the source of data without touching other code statements.

;;(defvar *my-variable* '(:x 10 :y 10))

(defun get-my-variable (&optional (keywd nil keywd-p))
  (let ((data (sd-get-persistent-data "MY-MODULE" "MY-KEY"
                 :default '(:x 10 :y 10))))
    (if keywd-p
      ;; then
      (getf data keywd)
      ;; else
      data)))

Removing a Data Entry

Removing a data entry is not that difficult. It's just a call like the following one.

(sd-remove-persistent-data "MY-MODULE" "MY-KEY")

But removing a data entry when setting is expected makes this topic more interesting. Assume a persistent data is changed. This implicates that the new value is set in the PDS System. But is it set in any case? No. Usually for each data a default value is defined. If changing the data back to its default value the corresponding setting function may simply remove the entry from the PDS System.

(defun get-value ()
  (sd-get-persistent-data "MY-MODULE" "MY-KEY" :default 4711))

(defun set-value (value)
  (if (= value 4711)
    ;; then
    (sd-remove-persistent-data "MY-MODULE" "MY-KEY")
    ;; else
    (sd-set-persistent-data "MY-MODULE" "MY-KEY" value)))

If the data is a property list, of course, this function gets more complex. But it is always a good style to remove an entry from the PDS System when the entry contains the default value.

Save PDS System

Saving the PDS System to the file system - to the user customization directory - is accomplished automatically on system exit. A programmer has not to care about saving PDS.

[Integration Kit Contents] [Integration Kit What's New] [Integration Kit Function Index] [More Documentation] [PTC]
© 2019 Parametric Technology GmbH
(a subsidiary of PTC Inc.), All Rights Reserved