The services layer of the
QNX CAR Platform for Infotainment is built on the QNX
Persistent
Publish/Subscribe (PPS) service, a simple filesystem-based facility that
provides persistence across reboots. Small and extensible, PPS allows interfacing from
almost any higher-level language that can support open, read, write, and close
operations on files.
Key concepts
- Objects
- Objects are implemented as files under the /pps
directory. Your applications use objects to communicate with each other.
There can be many objects in the system, but never more than one instance of
the same object.
Applications
often use a control object for sending commands and a
corresponding status object for publishing responses.
Applications can read a single special object
(.all) to get notifications of changes to
all the objects in a directory. Apps can use the special
.notify object to get changes for a certain set
of objects.
- Attributes
- Objects contain attributes or properties that apps can modify. Each
attribute appears on a single line in the object file.
- Publishers
- As publishers, apps can modify objects and their attributes so that other
interested apps can receive updates. Publishing is asynchronous—apps
don't have to wait for the publisher.
To publish to an object, the publisher calls open() for that
object and then write() to
modify it. Multiple publishers can publish to the same object. When a
publisher changes an object, the PPS service informs all subscribers of
the change.
- Subscribers
- As subscribers, apps receive updates for objects and attributes that
publishers have modified. To get updates for an object, a subscriber calls
open() for that
object and then read() to query it.
Note that reads are nonblocking by default. Multiple subscribers can
subscribe to the same object.
Note: The same app can be a publisher, a subscriber, or both.
- Full subscription mode
- In full mode (the default), the subscriber gets a "snapshot" of the
entire object as it exists when the request is made. Note that if a
publisher changes the object many times, the subscriber may miss some of the
changes. Full mode is useful, for instance, for high-bandwidth objects that
have numerous and frequent changes.
- Delta subscription mode
- In delta mode, the subscriber gets only the changes made to an object. On
first read, the subscriber will get all the object's attributes
(because the subscriber knows nothing yet about the object's state);
subsequent reads will return only the changes since the previous read. Delta
mode is useful, for instance, when you want to receive all the warnings or
error messages that might be published to an object.
- Persistence
- PPS maintains objects in memory while it's running and can save them to
persistent storage (either at shutdown or on demand) on any reliable
filesystem, such as flash or hard disk. Objects can be restored immediately
on startup or on first access.
- Server objects
- A publisher can designate itself as a server for a particular
object. When an app writes to a server object, only the publisher will get
the message. PPS appends a unique identifier to the object name so that the
publisher knows which client app is sending the message. For details, see
"Server objects" in the
Persistent Publish/Subscribe Developer's Guide.
Command-line options for the PPS service
pps [-A file][-b][-C][-d backlog][-l argument][-m mount][-p dir]
[-P prio][-t period][-T tolerance][-U uid:gid][-v]
- -A
file
- Set path to ACL configuration file. For details, see "Access Control List configuration
file" in the Persistent Publish/Subscribe
Developer's Guide.
- -b
- Don't run in the background (useful for debugging).
- -C
- Convert between -U and non-U persistence formats.
- -d
backlog
- Set size of delta backlog (default is 256 kilobytes).
- -l
argument
- Set load behavior:
- 0 — load directory names and objects on demand
(default).
- 1 — load directories at startup, but objects on demand.
- 2 — load directories and objects at startup.
- -m
mount
- Specify the mountpoint for PPS (default is /pps).
- -p
dir
- Specify the directory for persistent storage (default is
/var/pps).
- -P
prio
- Set the priority of the persistence thread.
- -t
period
- Set the time period (in milliseconds) for writing to persistent storage
(default is off).
- -T
tolerance
- Set the tolerance (in milliseconds) for writing to persistent storage
(default is off).
- -U
uid:gid
- Downgrade from root to the specified UID and GID.
- -v
- Run in verbose mode (use multiple v's to increase
verbosity).
Note: You can also use SIGUSR1 to increase
verbosity.
Pathname options
PPS lets you use
various pathname options when opening objects. An option must follow a question mark
(?). Use a comma to separate multiple options. For example,
opening the playlist object like this:
/pps/media/playlist?wait,delta
will open the object with the wait and delta
options.
- backlog
- Total delta size to keep before flushing this OCB (Open Control Block).
- cred
- Output the credentials for this object.
- critical
- Designate the publisher as critical to the object.
- crypt
- Set the crypto domain for this object.
- delta
- Open the object in delta mode.
- deltadir
- Return the names of all objects in the .all object in a
directory.
- f=<attrspec>{+<attrspec>}...
- Filter notifications based on changes to the names and/or values of
specified attributes, where attrspec can be either an
attribute's name or an expression specifying an attribute's value. Here's
the syntax for a value expression:
<attr_name><operator><value>
- Operators for integers (which must be in the range of a long long)
are: <, <=,
>, >=,
=, ==, and
!=
- Operators for strings are: =, ==,
and != (you can use + if escaped
with \)
- flow
- Treat the object as a server object, with purge and overflow
notifications.
- hiwater
- Flow high-water mark as percent of client backlog. If this tag isn't
specified, the default (100) is used.
- nopersist
- Make the object nonpersistent.
- notify=id:value
- Associate the object with the notification group specified by
id:value, where:
- id is the string returned by the first read from
the .notify object
- value is any arbitrary string
- opens
- Update an _opens::rd,wr attribute when the open count
changes.
- reflect
- Reflect attribute changes made on this object back to itself.
- server
- Designate the publisher as a server for the object.
- verbose
- Set the verbosity level for this object.
- wait
- Clear the O_NONBLOCK flag so that read()
calls will wait until the object changes or a delta appears.
Object format
Objects appear as files
and directories in the PPS filesystem. For example, to view the contents of an
object called AA:BA:19:B2:AA:70 (in this case the filename is a
device's MAC address) under the
/pps/services/bluetooth/remote_devices/ directory, you can
simply use cat at the command line:
cat /pps/services/bluetooth/remote_devices/AA:BA:19:B2:AA:70
The object's contents might look like this:
@AA:BA:19:B2:AA:70
[n]cod::0x007a020c
[n]name::My mobile
[n]paired:b:false
[n]rssi::0x00
The first line
always begins with an at sign (@), immediately followed by the
object's name. Each line after that can begin with a qualifier, followed by an
attribute name, followed by its encoding, followed by its value. For example, this
line:
[n]paired:b:false
means that the nonpersistence
qualifier (
[n]) has been set and that the attribute
paired has the Boolean value of
false.
Note:
For details on encodings and on qualifiers, see these sections in the
Persistent Publish/Subscribe Developer's Guide:
Format for messages to server objects
msg::command_string\nid::ID_number\ndat:json:{JSON_data}
where:
- command_string
- Name of the command being sent to the object.
- ID_number
- Any ID that identifies this instance of the message. The server always
reflects the ID back in the response.
- JSON_data
- The dat is usually JSON encoded, because it may contain
more than a simple string.
Format for responses
Responses always reflect the command_string and
ID_number that were sent in the message, along with any
errors:
res::command_string\nid::ID_number\ndat:json:{JSON_data}\nerr::errno_number\nerrstr::error_description
Changing the directory for persistent storage
The root PPS object tree
(/pps by default) may look something like this:
# pwd
/pps
# ls -1F
accounts/
applications/
qnx/
qnxcar/
services/
system/
#
PPS populates its root object tree from the persistence tree
(/var/pps by default), where the objects and attributes
that you want to persist are stored.
To
specify a different directory for persistent storage:
- Create your own persistence directory (e.g., mkdir
/myobjects).
- Start the PPS service from a different mountpoint (e.g.,
/fs/pps) and specify your new persistence
directory:
pps -m /fs/pps -p /myobjects
Note:
You may want to run PPS with the
-t option, which lets you specify the time period (in
milliseconds) that the service will use to write to persistent storage. Without
the -t, you won't see any changes in your persistence directory
until PPS exits.