[Back to Main Page]

Local Keyset
Namespace

Intent

Provide a local, mote-specific namespace for referring to distinct elements or data types.

Also Known As

unique ids

Example TinyOS Components

TimerC, MContextSynch, Matchbox

Motivation

A typical TinyOS application has to manage several data items or types at once. Processing them properly requires having a unique name for each one. As the use of these names is internal to a given mote, the names themselves are not important. Correspondingly, the names can be chosen to optimize their storage or use.

The Service Instance pattern is an example of this need. An application requires several instances of a service, and needs to be able to refer to each one uniquely. Additionally, because the identifiers for the service instances can be chosen freely, they can be selected to allow easy state management (storing per-instance state in an array).

The Local Keyset provides a way to generate and maintain a concise namespace; it is a local keyset in that other motes running different applications may not agree on the keys in the keyset: their use is limited to a particular application. For example, the Service Instance pattern uses a Local Keyset to keep track of the instances. However, if two applications include a component that uses an instance of the service, the identifier of the instance they use may be different.

nesC supports the Local Keyset pattern through the unique function. unique takes a single parameter, a constant string representing the keyset a key is needed from. The nesC compiler resolves the function to a constant at compile-time.

Applicability

Use the Local Keyset pattern when:

  • You need to keep track of a number of elements locally on a mote
  • The number of elements isn't known until a complete application is composed
  • The exact identifiers used for the elements is not important

Consequences

The Local Keyset allows a component to request unique keys from a keyset at compile time. This means that the compiler can generate a concise namespace, as well as enumerate the elements of the namespace. Pushing this logic to compile-time reduces RAM utilization (keyset state), CPU overhead (keys are constants in code), and enables compile-time checks on keyset values.

Motes cannot safely communicate with one another in terms of Local Keysets, as they may have different key-value mappings. Additionally, although each element of a keyset is unique, there nesC provides no type checking on keys: they are just integer values. This means that programs can confuse keysets and possibly cause run-time issues (e.g., using a key from set X on a component that expects keys from set Y).

The component model of TinyOS means that it can be difficult to figure out what components are requesting keys from a local key set. Similarly, being able to map local keys to user-comprehensible names (say, for external tools) can be problematic. In this case -- where other programs need to communicate with motes in terms of keys -- a Local Keyset may not be well suited; a Global Keyset may be preferrable.

Implementation

Components generate keys from a keyset with the unique() function, with a string parameter describing which keyset the key is from. A program can determine the number of elements in a Local Keyset with the uniqueCount function.

Sample Code

The Maté virtual machine maintains locks for resources that concurrent programs may access. The set of shared resources depends on what customized VM a user builds. These locks are handled internally by the VM engine, which locks and unlocks them as needed: user programs can refer to a resource's lock by its logical name (e.g., "shared variable X"). The VM translates this logical name to a lock name.

The VM maintains the set of locks as a local keyset. If a component needs a unique lock (it has a shared resource), then it allocates one with unique:

enum {
  MYCOMPONENT_LOCKNUM = unique("MateLock");
}

The component can then use this key in requests to the locking subsystem:

if (!call Locks.isHeldBy(MYCOMPONENT_LOCKNUM, context)) {
  call Error.error(context, MATE_ERROR_INVALID_ACCESS);
  return FAIL;
}

Known Uses

Many components use local keysets: they are a fundamental part of the Service Instance pattern.

TimerC uses a local keyset to keep track of different timers that components use.

MContextSynch uses a local keyset to keep track of Maté shared resource locks.

Matchbox uses a local keyset for file handles.

Related Patterns

The Global Keyset pattern also establishes a keyset, but for the purpose of inter-mote communication: the keys are globally valid. The Keyset Map pattern provides a simple way to map between local and global keysets, if a program needs to have a concise local representation of globally acccessible names (e.g., send queues for several AM types).

The Service Instance pattern uses a Local Keyset to refer to instances of the service.

[Back to Main Page]

Last modified: Fri Jul 30 17:09:59 PDT 2004