The basic service that Mercury provides is the lookup of stored data
items using range-queries over multiple attributes. In Mercury,
data items are represented as a list of typed attribute-value pairs,
very similar to a record in a relational database. Each field is a
tuple of the form:
. The following
types are recognized:
and
. For example, objects within Quake II
describe their locations using attributes
,
and
corresponding to the three
coordinate axes. Other attributes of an object include
and
, for
team membership and each player's score, respectively.
A query is a conjunction of
predicates which are tuples of the form:
. A disjunction is implemented by multiple distinct
queries. Mercury supports the following operators:
.
As an example, using the above query language, a node could retrieve all data items within a cuboid bounding its region of visibility.
Mercury supports range lookups over multiple attributes by
partitioning the nodes in the system into groups called attribute
hubs, one for each naming attribute in the overall application
schema. Nodes within an attribute hub are organized into a circular
overlay with each node responsible for a contiguous range
of attribute values, like that shown in Figure 4. This
range is assigned to a node when it joins the network and may change
during its lifetime due to other joins as well as load-balancing
operations. A query
is delivered to exactly one of the hubs
corresponding to the attributes that are queried. To guarantee that
query will discover all relevant data items, a data item
is sent
to hubs for all attributes referenced in
. Mercury uses a
combination of long-links (a.k.a. finger pointers) and cached pointers
from previous lookups to reduce the hop count for delivering a
message.