Miscellaneous
Session Store
The session store can be used to persist information (or state) across Origen threads of execution within a given workspace.
Setting the current target with origen t
is a example
of session information being used to setup some state that will persist into
future Origen commands that are executed within that workspace, while having no bearing on what happens
in other workspaces.
To access the session store:
Origen.app.session
The session is split into named stores which will be automatically created as soon as data is added to them, this gives application developers a namespace level to keep their data organized.
The namespace returns a key-value store containing all of the values in that namespace:
Origen.app.session.main # => A key-value store
Origen.app.session.blah # => A different key-value store
Plugin developers should use a store named after their plugin, for example the ATDTest
plugin would use:
Origen.app.session.atd_test # => A key-value store for use by the ATDTest plugin
To store values to the session simply set them like this:
Origen.app.session.main[:exec_count] = 10
Unlike assigning values to a regular Hash variable, this value will survive between Origen
threads - go on fire up an origen i
session and try it out:
Origen.app.session.main[:exec_count] # => 10
Generally you can store hashes, arrays and even objects to the session although your mileage-may-vary with particularly rich objects. Note that in the case of storing objects the class definition must still be around when Origen tries to resurrect it from the session. i.e. you cannot store an object, delete the class definition for that object, and then materialize it from the session later. Similarly binary data cannot be stored to the session.
There are a few helper methods for managing the session store.
Origen.app.session.main[:exec_count] = 10
Origen.app.session.main[:owner] = 'Stephen'
Origen.app.session.main.has_key?(:exec_count) # => true
Origen.app.session.main.keys.sort # => [:exec_count, :owner]
Origen.app.session.main.delete_key(:exec_count) # => 10
Origen.app.session.main.keys.sort # => [:owner]
In one of our applications, called ‘NVM’, there is a need to program firmware images that are provided by the design team.
Rather than duplicate the firmware images in the design and test repositories they are typically imported from the design repository into the test workspace at runtime (on as as-required basis). It is critical to keep track of what version of the firmware exists locally so that if the production firmware version changes then the new version will be fetched, but if it is the same as what is already there then the user is not made to wait for a redundant import operation.
In early Origen applications, significant logic had to be added to the application to implement such a system, but the availability of the session store now makes this trivial:
# Return the associated firmware file, this will automatically fetch the new version
# if the production firmware tag has changed since this was last called
def firmware_file
path_to_local_file = "#{Origen.app.imports_dir}/firmware/production.hex"
f = Pathname.new(path_to_local_file)
if !f.exist? || Origen.app.session.nvm[:local_firmware_version] != production_tag
# Clear this up front as we won't know what we will have if the checkout fails
Origen.app.session.nvm[:local_firmware_version] = nil
firmware_rc.checkout("production.hex", force: true, version: production_tag)
Origen.app.session.nvm[:local_firmware_version] = production_tag
end
f
end
# Returns a revision controller to manage local import of firmware files
def firmware_rc
@firmware_rc ||= Origen::RevisionControl.new remote: "sync://sync-15000:15000/nvm/firmware",
local: "#{Origen.app.imports_dir}/firmware"
end
Origen also has a global session that is accessible across all Origen applications, plugins, etc., or from outside any of those at all! Note, however, that ‘global’ is in terms of a single user. This is not a shared session across the entire Origen installation (in the case of site-wide Origen installions as referenced in the Origen Installation Guides.
Accessing Origen’s global session is similiar to that of the application specific sessions and works in much the same way:
Origen.session #=> Origen's Global Session
Origen.session.globals #=> Create a new database called 'globals' available across all of Origen.
# One use case encountered was to store another machine's IP that other applications would SSH into.
# This IP is the same for all Origen applications for a given user (i.e., each user has their own
# machine to log into).
Origen.session.ssh[:machine_ip] = "255.255.255.0"
Origen.session.ssh[:machine_ip] #=> "255.255.255.0"
# --Move to another Origen workspace--
Origen.session.ssh[:machine_ip] #=> "255.255.255.0"
The session itself is stored in the same fashion as the application sessions, just at a more accessible location. That
location is at Origen.home
, which equates to ~/.origen/
. There lives the global .session
.
By default, the session databases are accessible to the user and to members of the same group (in Unix speak, that is), and are
readable by everyone. The session contains a variable that can be set to instead make the session only accessible by the user.
This is accomplished by just setting the permissions to 0600
.
To enable a private session, you can, at anytime, run:
Origen.session.secret.private = true
The next time that a session is updated, the permissions will be modified accordingly. Likewise, you can disable the private database by running:
Origen.session.secret.private = false
If you want to create a new session that is private from the beginning, just set the private variable prior to performing the first session write:
# This session doesn't exist yet:
Origen.session.always_secret.private = true
Origen.session.always_secret[:my_key] = "my value"
You can check whether a session is private or not by querying one of the methods below:
Origen.session.secret.private
Origen.session.secret.private?
It is important to note that this is a per individual session parameter. That is, you must set this for all sessions that you want to make private.
Another note: under the hood, this uses Ruby’s FileUtils.chmod
method, which itself is platform dependent. This
was built with a Unix use case in mind, so your milage may vary with other operating systems. But, this is standard Ruby,
so it should run regardless of OS and its effect.