349 lines
29 KiB
HTML
349 lines
29 KiB
HTML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>The Be Book - System Overview - The Storage Kit</title><link rel="stylesheet" href="be_book.css" type="text/css" media="all" /><link rel="shortcut icon" type="image/vnd.microsoft.icon" href="./images/favicon.ico" /><!--[if IE]>
|
||
<link rel="stylesheet" type="text/css" href="be_book_ie.css" />
|
||
<![endif]--><meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /><meta name="keywords" content="Access, BeOS, BeBook, API" /><link rel="start" href="index.html" title="The Be Book" /><link rel="up" href="TheStorageKit_Overview.html" title="The Storage Kit" /><link rel="prev" href="BPath_Overview.html" title="BPath" /><link rel="next" href="BRefFilter_Overview.html" title="BRefFilter" /></head><body><div id="header"><div id="headerT"><div id="headerTL"><a accesskey="p" href="BPath_Overview.html" title="BPath"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a accesskey="u" href="TheStorageKit_Overview.html" title="The Storage Kit"><img src="./images/navigation/up.png" alt="Up" /></a> <a accesskey="n" href="BRefFilter_Overview.html" title="BRefFilter"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="headerTR"><div id="navigpeople"><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div><div class="navigboxed" id="navigindex"><a accesskey="i" href="ClassIndex.html" title="Index">I</a></div><div class="navigboxed" id="naviglang" title="English">en</div></div><div id="headerTC">The Be Book - System Overview - The Storage Kit</div></div><div id="headerB">Prev: <a href="BPath_Overview.html">BPath</a> Up: <a href="TheStorageKit_Overview.html">The Storage Kit</a> Next: <a href="BRefFilter_Overview.html">BRefFilter</a></div><hr /></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BQuery_Overview"></a>BQuery</h2></div></div></div><a id="id611344" class="indexterm"></a><p>
|
||
A query is a means of asking the file system for a set of entries that
|
||
satisfy certain criteria. As examples, you can ask for all the entries
|
||
with names that start with a certain letter, or that have nodes that are
|
||
bigger than a certain size, or that were modified within the last N days,
|
||
and so on.
|
||
</p><p>
|
||
The <code class="classname">BQuery</code> class lets you create objects that represent specific queries.
|
||
To use a <code class="classname">BQuery</code> you have to follow these steps:
|
||
</p><div class="orderedlist"><ol><li><p>
|
||
Initialize.<br />
|
||
The first thing you have to do is initialize the
|
||
object; there are two parts to the initialization: You have to set the
|
||
volume that you want to query over
|
||
(<a class="link" href="BQuery.html#BQuery_SetVolume" title="SetVolume()"><code class="methodname">SetVolume()</code></a>),
|
||
and set the query's "criteria formula"
|
||
(<a class="link" href="BQuery.html#BQuery_SetPredicate" title="SetPredicate(), GetPredicate(), PredicateLength()"><code class="methodname">SetPredicate()</code></a>)
|
||
</p></li><li><p>
|
||
Fetch.<br />
|
||
After the <code class="classname">BQuery</code> has been properly initialized, you invoke
|
||
<a class="link" href="BQuery.html#BQuery_Fetch" title="Fetch()"><code class="methodname">Fetch()</code></a>.
|
||
The function returns immediately while the query executes in the
|
||
background.
|
||
</p></li><li><p>
|
||
Read.<br />
|
||
As soon as <a class="link" href="BQuery.html#BQuery_Fetch" title="Fetch()"><code class="methodname">Fetch()</code></a>
|
||
returns, you can start reading the list of
|
||
winning entries by making iterative calls to the entry-list functions
|
||
<a class="link" href="BQuery.html#BQuery_GetNextRef"><code class="methodname">GetNextRef()</code></a>,
|
||
<a class="link" href="BQuery.html#BQuery_GetNextEntry" title="GetNextEntry(), GetNextRef(), GetNextDirents()"><code class="methodname">GetNextEntry()</code></a>,
|
||
and <a class="link" href="BQuery.html#BQuery_GetNextDirents"><code class="methodname">GetNextDirents()</code></a>. If you ask for
|
||
entries faster than the query can deliver them, your <code class="methodname">GetNext…()</code> call
|
||
will block until the next entry arrives. The function returns an error
|
||
when there are no more entries to retrieve.
|
||
</p></li></ol></div><p>
|
||
The set of entries that the <code class="methodname">GetNext…()</code> calls retrieve (for a given
|
||
fetch) are called the query's "static" entries. This distinction will
|
||
become useful when we speak of "live" queries, below.
|
||
</p><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id611756"></a>Reusing your BQuery</h3></div></div></div><p>
|
||
Want to go around again? You can, but first you have to clear the object:
|
||
</p><ul class="itemizedlist"><li><p>
|
||
Between each "fetching session," you have to invoke
|
||
<a class="link" href="BQuery.html#BQuery_Clear" title="Clear()"><code class="methodname">Clear()</code></a> on your
|
||
<code class="classname">BQuery</code> object.
|
||
</p></li></ul><p>
|
||
Clearing erases the object's predicate, volume, target (which we'll get
|
||
to later), and list of static entries—in other words, clearing gets
|
||
you back to a fresh <code class="classname">BQuery</code> object.
|
||
</p><p>
|
||
And speaking of going around again, be aware that the
|
||
<a class="link" href="BQuery.html#BQuery_Rewind"><code class="methodname">Rewind()</code></a> function,
|
||
which <code class="classname">BQuery</code> inherits from
|
||
<a class="link" href="BEntryList.html" title="BEntryList"><code class="classname">BEntryList</code></a>, is implemented to be a no-op: You
|
||
can't rewind a <code class="classname">BQuery</code>'s list of static entries. After you've performed a
|
||
fetch, you should read the entry list as quickly as possible and get on
|
||
with things; you can't turn back or start over.
|
||
</p><p>
|
||
<a class="link" href="BQuery.html#BQuery_CountEntries" title="CountEntries(), Rewind()"><code class="methodname">CountEntries()</code></a>
|
||
is also a no-op. This function is also defined by
|
||
<a class="link" href="BEntryList.html" title="BEntryList"><code class="classname">BEntryList</code></a>.
|
||
It doesn't apply to <code class="classname">BQuery</code>s.
|
||
</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id611851"></a>Live Queries</h3></div></div></div><p>
|
||
A live query is the gift that keeps on giving. After you tell a live
|
||
query to fetch, you walk through the entry list (as described above), and
|
||
then you wait for "query update" messages to be sent to your "target." A
|
||
query update message describes a single entry that has changed so that…
|
||
</p><ul class="itemizedlist"><li><p>
|
||
it now satisfies the predicate (where it didn't use to), or…
|
||
</p></li><li><p>
|
||
it no longer satisfies the predicate (where it did before).
|
||
</p></li></ul><p>
|
||
Not every <code class="classname">BQuery</code> is live; you have to tell it you want it to be live. To
|
||
do this, all you have to do is set the object's target, through the
|
||
<a class="link" href="BQuery.html#BQuery_SetTarget" title="SetTarget(), IsLive()"><code class="methodname">SetTarget()</code></a>
|
||
function. The target is a
|
||
<a class="link" href="BMessenger.html" title="BMessenger"><code class="classname">BMessenger</code></a> that identifies a
|
||
<a class="link" href="BHandler.html" title="BHandler"><code class="classname">BHandler</code></a>/<a class="link" href="BLooper.html" title="BLooper"><code class="classname">BLooper</code></a>
|
||
pair (as described in the
|
||
<a class="link" href="BQuery.html#BQuery_SetTarget" title="SetTarget(), IsLive()"><code class="methodname">SetTarget()</code></a>
|
||
function). Also…
|
||
</p><ul class="itemizedlist"><li><p>
|
||
Live query notifications stop when you
|
||
<a class="link" href="BQuery.html#BQuery_Clear" title="Clear()"><code class="methodname">Clear()</code></a>
|
||
or destroy the <code class="classname">BQuery</code> object.
|
||
</p></li></ul><p>
|
||
Another important point regarding live queries is that you can start
|
||
receiving updates before you're done looking at all the static entries
|
||
(in other words, before you've reached the end of the <code class="methodname">GetNext…()</code> loop).
|
||
It's possible that your target could receive an "entry dropped out"
|
||
update before you retrieve the entry through a <code class="methodname">GetNext…()</code> call. If
|
||
you're using live queries, you should take care in synchronizing the
|
||
<code class="methodname">GetNext…()</code> iteration with the target's message processing.
|
||
</p><p>
|
||
We'll look at the format of the update message in a moment; first, let's
|
||
fill in some gaps.
|
||
</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BQuery_Predicate_Attributes_Indices"></a>The Predicate, Attributes, and Indices</h3></div></div></div><p>
|
||
A <code class="classname">BQuery</code>'s predicate is a logical expression that evaluates to <code class="constant">true</code> or
|
||
<code class="constant">false</code>. The "atoms" of the expression are comparisons in the form…
|
||
</p><ul class="itemizedlist"><li><p>
|
||
<span class="emphasis"><em>attribute op value</em></span>
|
||
</p></li></ul><p>
|
||
…where <span class="emphasis"><em>attribute</em></span> is the name of an existing attribute,
|
||
<span class="emphasis"><em>op</em></span> is a constant
|
||
that represents a comparison operation (==, <, >, etc), and <span class="emphasis"><em>value</em></span> is the
|
||
value that you want to compare the attribute to.
|
||
</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id612032"></a>Attributes</h3></div></div></div><p>
|
||
As mentioned above, the attribute part of a query is a string name. When
|
||
you tell the query to fetch, the file system looks for all nodes that
|
||
have an attribute with that name and then compare the attribute's value
|
||
to the appropriate value in the predicate. However…
|
||
</p><ul class="itemizedlist"><li><p>
|
||
Every query must include at least one indexed attribute.
|
||
</p></li><li><p>
|
||
The index only knows about attributes that were written after the
|
||
index (for that attribute) was created.
|
||
</p></li></ul><p>
|
||
To index an attribute, you call the
|
||
<a class="link" href="TheStorageKit_Functions.html#fs_create_index" title="fs_create_index()"><code class="function">fs_create_index()</code></a> function.
|
||
Unfortunately, there's currently no way to retroactively include existing
|
||
attributes in a newly created index. (Such a utility would be simple
|
||
enough to write, but it would take a long time to execute since it would
|
||
have to look at every file in the file system.)
|
||
</p><p>
|
||
Only string and numeric attributes can be queried. Although an attribute
|
||
can hold any type of data (it's stored as raw bytes), the query mechanism
|
||
can only perform string and numeric comparisons.
|
||
</p><p>
|
||
On the bright side, every file gets three attributes for free:
|
||
</p><ul class="itemizedlist"><li><p>
|
||
"name" is the name of the entry.
|
||
</p></li><li><p>
|
||
"size" is the size of the data portion of the entry's node. The size
|
||
is a 64-bit integer, and doesn't include the node's attributes.
|
||
</p></li><li><p>
|
||
"last_modified" is the time the entry's node was last modified (data
|
||
and attributes), measured in seconds since January 1, 1970. The
|
||
modification time is recorded as a 32-bit integer.
|
||
</p></li></ul><p>
|
||
Technically, "name", "size", and "last_modified" aren't actually
|
||
attributes—you can't get them through
|
||
<a class="link" href="BNode.html#BNode_ReadAttr" title="ReadAttr(), WriteAttr(), RemoveAttr()"><code class="methodname">BNode::ReadAttr()</code></a>, for
|
||
example. But they're always eligible as the attribute component in a
|
||
query.
|
||
</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id612129"></a>Values</h3></div></div></div><p>
|
||
The value part of the "attribute op value" equation is any expression
|
||
that can be evaluated at the time the predicate is set. Once evaluated,
|
||
the value doesn't change. For example, you can't specify another
|
||
attribute as the value component in hopes of comparing, file by file, the
|
||
value of one attribute to the value of another. The value is just data.
|
||
And data is data.
|
||
</p><p>
|
||
The type of the value should match the type of the attribute: You compare
|
||
string attributes to strings; numeric attributes to numbers. You aren't
|
||
prevented from comparing a string to a number (for example), but it may
|
||
not give you the result you expect.
|
||
</p><div class="admonition warning"><div class="title">Warning</div><div class="graphic"><img class="icon" alt="Warning" width="32" src="./images/admonitions/Stop_32.png" /><div class="text"><p>The value of an indexed attribute can be, at most, 255 bytes.</p></div></div></div></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BQuery_Constructing_A_Predicate"></a>Constructing a Predicate</h3></div></div></div><p>
|
||
There are two ways to construct a predicate:
|
||
</p><ul class="itemizedlist"><li><p>
|
||
You can set the predicate formula as a string through
|
||
<a class="link" href="BQuery.html#BQuery_SetPredicate" title="SetPredicate(), GetPredicate(), PredicateLength()"><code class="methodname">SetPredicate()</code></a>,
|
||
or
|
||
</p></li><li><p>
|
||
You can construct the predicate by "pushing" the components in
|
||
Reverse Polish Notation (or "postfix") order through the
|
||
<a class="link" href="BQuery.html#BQuery_PushAttr" title="PushAttr() , PushOp(), PushUInt32(), PushInt32(), PushUInt64(), PushInt64(), PushFloat(), PushDouble(), PushString(), query_op"><code class="methodname">PushAttr()</code></a>,
|
||
<code class="methodname">PushValue…()</code>, and
|
||
<a class="link" href="BQuery.html#BQuery_PushOp"><code class="methodname">PushOp()</code></a>
|
||
functions. There are seven value-pushing
|
||
functions that push specific types: <span class="type">string</span>, <span class="type">int32</span>,
|
||
<span class="type">uint32</span>, <span class="type">int64</span>,
|
||
<span class="type">uint64</span>, <span class="type">float</span>, and <span class="type">double</span>.
|
||
</p></li></ul><p>
|
||
You can't combine the methods: Pushing the predicate always takes
|
||
precedence over
|
||
<a class="link" href="BQuery.html#BQuery_SetPredicate" title="SetPredicate(), GetPredicate(), PredicateLength()"><code class="methodname">SetPredicate()</code></a>,
|
||
regardless of the order in which the methods are deployed.
|
||
</p><p>
|
||
<a class="link" href="BQuery.html#BQuery_SetPredicate" title="SetPredicate(), GetPredicate(), PredicateLength()"><code class="methodname">SetPredicate()</code></a> features:
|
||
</p><ul class="itemizedlist"><li><p>
|
||
Comparison operators: = < > <= >= !=
|
||
</p></li><li><p>
|
||
Logical operators: || &&
|
||
</p></li><li><p>
|
||
Negation operator: !
|
||
</p></li><li><p>
|
||
Grouping: ()
|
||
</p></li><li><p>
|
||
String (value) wildcard: * (prefix and/or postfix only)
|
||
</p></li><li><p>
|
||
String (value) quoting: ' '
|
||
</p></li></ul><p>
|
||
The following are all legitimate strings that you can pass to
|
||
<a class="link" href="BQuery.html#BQuery_SetPredicate" title="SetPredicate(), GetPredicate(), PredicateLength()"><code class="methodname">SetPredicate()</code></a>:
|
||
</p><pre class="screen">
|
||
size < 500
|
||
|
||
(name = fido) || (size >= 500)
|
||
|
||
(! ((name = *id*) || ( 'final utterance' = 'pass the salt'))) &&
|
||
(last_modified > 1024563)
|
||
</pre><p>
|
||
Push features:
|
||
</p><ul class="itemizedlist"><li><p>
|
||
The <a class="link" href="BQuery.html#BQuery_PushOp"><code class="methodname">PushOp()</code></a>
|
||
function takes operator symbols, such as <code class="constant">B_EQ</code> (equals),
|
||
<code class="constant">B_GT</code> (greater than), <code class="constant">B_LT</code> (less than), and so on. The complete list is
|
||
given in the <a class="link" href="BQuery.html#BQuery_PushOp"><code class="methodname">PushOp()</code></a>
|
||
function description.
|
||
</p></li><li><p>
|
||
Value strings passed as arguments to
|
||
<a class="link" href="BQuery.html#BQuery_PushString"><code class="methodname">PushString()</code></a> are naturally
|
||
quoted, so you don't have to single-quote to embed spaces or other odd
|
||
characters.
|
||
</p></li><li><p>
|
||
The '*' wildcard is allowed, or you can use special "contains",
|
||
"begins with", and "ends with" operators.
|
||
</p></li></ul><p>
|
||
In Reverse Polish Notation, the operator is postfixed. You then push the
|
||
components from left to right. For example, this…
|
||
</p><pre class="screen">
|
||
size < 500
|
||
</pre><p>
|
||
…becomes…
|
||
</p><pre class="screen">
|
||
size 500 <
|
||
</pre><p>
|
||
The push sequence is…
|
||
</p><pre class="programlisting cpp"><code class="varname">query</code>.<code class="methodname">PushAttr</code>("size");
|
||
<code class="varname">query</code>.<code class="methodname">PushInt32</code>(500);
|
||
<code class="varname">query</code>.<code class="methodname">PushOp</code>(<code class="constant">B_LT</code>);</pre><p>
|
||
Another example; this…
|
||
</p><pre class="screen">(name = fido) || (size >= 500)</pre><p>
|
||
...becomes...
|
||
</p><pre class="screen">(name fido =) (size 500 >=) ||</pre><p>
|
||
In code:
|
||
</p><pre class="programlisting example cpp"><code class="varname">query</code>.<code class="methodname">PushAttr</code>("name");
|
||
<code class="varname">query</code>.<code class="methodname">PushString</code>("fido");
|
||
<code class="varname">query</code>.<code class="methodname">PushOp</code>(<code class="constant">B_EQ</code>);
|
||
<code class="varname">query</code>.<code class="methodname">PushAttr</code>("size");
|
||
<code class="varname">query</code>.<code class="methodname">PushInt32</code>(500);
|
||
<code class="varname">query</code>.<code class="methodname">PushOp</code>(<code class="constant">B_GE</code>);
|
||
<code class="varname">query</code>.<code class="methodname">PushOp</code>(<code class="constant">B_OR</code>);</pre><p>
|
||
There are no grouping operators in this notation; they're not
|
||
needed—grouping is implied by the order in which the components are
|
||
pushed.
|
||
</p><p>
|
||
When you're performing a numeric comparison, the <code class="methodname">Push…()</code> function that
|
||
you choose doesn't have to exactly match the natural type of the
|
||
attribute, but you can't mix integers and floating point. For example,
|
||
even though "size" is a 64 bit value, you can compare it to an <span class="type">int32</span>…
|
||
</p><pre class="programlisting example cpp"><code class="varname">query</code>.<code class="methodname">PushAttr</code>("size");
|
||
<code class="varname">query</code>.<code class="methodname">PushInt32</code>(2000);
|
||
<code class="varname">query</code>.<code class="methodname">PushOp</code>(<code class="constant">B_GE</code>);</pre><p>
|
||
But you can't (or shouldn't) compare it to a <span class="type">float</span>…
|
||
</p><pre class="programlisting example cpp"><code class="varname">query</code>.<code class="methodname">PushAttr</code>("size");
|
||
<code class="varname">query</code>.<code class="methodname">PushInt32</code>(2000);
|
||
<code class="varname">query</code>.<code class="methodname">PushOp</code>(<code class="constant">B_GE</code>);</pre></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id612617"></a>Query Update Messages</h3></div></div></div><p>
|
||
The <a class="link" href="BMessage.html" title="BMessage"><code class="classname">BMessages</code></a>
|
||
that are delivered by a live query have a <code class="varname">what</code> field of
|
||
<a class="link" href="TheStorageKit_MessageConstants.html#B_QUERY_UPDATE" title="B_QUERY_UPDATE"><code class="constant">B_QUERY_UPDATE</code></a>.
|
||
The rest of the message depends on what happened:
|
||
</p><ul class="itemizedlist"><li><p>
|
||
If the update is telling you that an entry has passed the predicate,
|
||
the message's <code class="varname">opcode</code> field
|
||
will be <code class="constant">B_ENTRY_CREATED</code>.
|
||
</p></li><li><p>
|
||
If the update is telling you that an entry has been eliminated from
|
||
the query, the <code class="varname">opcode</code>
|
||
field will be <code class="constant">B_ENTRY_REMOVED</code>.
|
||
</p></li></ul><p>
|
||
Note that the format of the messages that a live query generates are the
|
||
same as the similarly-opcode'd Node Monitor messages. The only difference
|
||
is the <code class="varname">what</code> field (the what for Node Monitor messages
|
||
is
|
||
<a class="link" href="The_Node_Monitor.html#B_NODE_MONITOR"><code class="constant">B_NODE_MONITOR</code></a>).
|
||
</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id612700"></a>Entry Created</h3></div></div></div><p>
|
||
The <code class="constant">B_ENTRY_CREATED</code> opcode means an entry has changed so that it now
|
||
passes the query's predicate. The message's fields are:
|
||
</p><div class="informaltable"><table border="1"><colgroup><col /><col /><col /></colgroup><thead><tr><th>Field</th><th>Type code</th><th>Description</th></tr></thead><tbody><tr><td><code class="varname">opcode</code></td><td><code class="constant">B_INT32_TYPE</code></td><td><code class="constant">B_ENTRY_CREATED</code></td></tr><tr><td><code class="varname">name</code></td><td><code class="constant">B_STRING_TYPE</code></td><td>The name of the new entry.</td></tr><tr><td><code class="varname">directory</code></td><td><code class="constant">B_INT64_TYPE</code></td><td>The <span class="type">ino_t</span> (node) number for the directory in
|
||
which the entry was created.</td></tr><tr><td><code class="varname">device</code></td><td><code class="constant">B_INT32_TYPE</code></td><td>The <span class="type">dev_t</span> number of the device on which the new
|
||
entry resides.</td></tr><tr><td><code class="varname">node</code></td><td><code class="constant">B_INT64_TYPE</code></td><td>The <span class="type">ino_t</span> number of the new entry itself. (More
|
||
accurately, it identifies the node that corresponds to the entry.)</td></tr></tbody></table></div><p>
|
||
If you want to cache a reference to the entry, notice that you can create
|
||
an <span class="type">entry_ref</span> and a <span class="type">node_ref</span> with the data in the message's fields:
|
||
</p><pre class="programlisting example cpp"><span class="comment">/* Create an entry_ref */</span>
|
||
<span class="type">entry_ref</span> <code class="varname">ref</code>;
|
||
const <span class="type">char*</span> <code class="varname">name</code>;
|
||
...
|
||
<code class="varname">msg</code>-><code class="methodname">FindInt32</code>("device", &<code class="varname">ref.device</code>);
|
||
<code class="varname">msg</code>-><code class="methodname">FindInt64</code>("directory", &<code class="varname">ref.directory</code>);
|
||
<code class="varname">msg</code>-><code class="methodname">FindString</code>("name", &<code class="varname">name</code>);
|
||
<code class="varname">ref</code>.set_name(name);
|
||
|
||
<span class="comment">/* Create a node_ref */</span>
|
||
<span class="type">node_ref</span> <code class="varname">nref</code>;
|
||
<span class="type">status_t</span> <code class="varname">err</code>;
|
||
|
||
...
|
||
<code class="varname">msg</code>-><code class="methodname">FindInt32</code>("device", &<code class="varname">nref.device</code>);
|
||
<code class="varname">msg</code>-><code class="methodname">FindInt64</code>("node", &<code class="varname">nref.node</code>);</pre><p>
|
||
The <span class="type">node_ref</span> is handy because you may want to start monitoring the node
|
||
(through a call to the Node Monitor). We'll get back to this point when
|
||
discussing <code class="constant">B_ENTRY_REMOVED</code> messages.
|
||
</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="id613015"></a>Entry Removed</h3></div></div></div><p>
|
||
The <code class="constant">B_ENTRY_REMOVED</code> opcode means an entry used to pass the predicate, but
|
||
something has changed (in the entry or the entry's node) so that now it
|
||
doesn't.
|
||
</p><div class="informaltable"><table border="1"><colgroup><col /><col /><col /></colgroup><thead><tr><th>Field</th><th>Type code</th><th>Description</th></tr></thead><tbody><tr><td><code class="varname">opcode</code></td><td><code class="constant">B_INT32_TYPE</code></td><td><code class="constant">B_ENTRY_REMOVED</code></td></tr><tr><td><code class="varname">directory</code></td><td><code class="constant">B_INT64_TYPE</code></td><td>The <span class="type">ino_t</span> (node) number of the directory from
|
||
which the entry was removed.</td></tr><tr><td><code class="varname">device</code></td><td><code class="constant">B_INT32_TYPE</code></td><td>The <span class="type">dev_t</span> number of the device that the removed
|
||
node used to live on.</td></tr><tr><td><code class="varname">node</code></td><td><code class="constant">B_INT64_TYPE</code></td><td>The <span class="type">ino_t</span> number of the node that was removed.</td></tr></tbody></table></div><p>
|
||
Notice that the <code class="constant">B_ENTRY_REMOVED</code> message doesn't tell you the name of the
|
||
entry. This is an unfortunate oversight that will be corrected. In the
|
||
meantime, if you need to match the node in this message to an entry from
|
||
a previous <code class="constant">B_ENTRY_CREATED</code> (or that you
|
||
got from a <code class="methodname">GetNext…()</code>
|
||
invocation), you have to keep track of the entry/node yourself. However,
|
||
the location of the entry that "contains" the node may have changed since
|
||
the time that the entry passed the predicate. Follow this outline:
|
||
</p><div class="orderedlist"><ol><li><p>
|
||
You set up a live query ask for entries that have nodes larger than
|
||
500 bytes.
|
||
</p></li><li><p>
|
||
The query mechanism tells you (either in the static set or through
|
||
a <code class="constant">B_ENTRY_CREATED</code> message) that
|
||
<code class="filename">/boot/home/fido/data</code> satisfies the
|
||
predicate.
|
||
</p></li><li><p>
|
||
You create an <span class="type">entry_ref</span> and a <span class="type">node_ref</span> to the entry, and cache them
|
||
away somewhere.
|
||
</p></li><li><p>
|
||
The user then renames or moves the entry. The query mechanism
|
||
doesn't tell you about this change—it only cares about the size of
|
||
the node, not its name
|
||
</p></li><li><p>
|
||
You get a <code class="constant">B_ENTRY_REMOVED</code> message. You create a <span class="type">node_ref</span> from the
|
||
message and match it to your cache—and get an out-of-date <span class="type">entry_ref</span>.
|
||
</p></li></ol></div><p>
|
||
To get around the lack of a "name" field, you should monitor the nodes
|
||
that you receive in your initial <code class="methodname">GetNext…()</code> calls
|
||
and <code class="constant">B_ENTRY_CREATED</code>
|
||
messages.
|
||
</p></div></div><div id="footer"><hr /><div id="footerT">Prev: <a href="BPath_Overview.html">BPath</a> Up: <a href="TheStorageKit_Overview.html">The Storage Kit</a> Next: <a href="BRefFilter_Overview.html">BRefFilter</a> </div><div id="footerB"><div id="footerBL"><a href="BPath_Overview.html" title="BPath"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a href="TheStorageKit_Overview.html" title="The Storage Kit"><img src="./images/navigation/up.png" alt="Up" /></a> <a href="BRefFilter_Overview.html" title="BRefFilter"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="footerBR"><div><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div></div><div id="footerBC"><a href="http://www.access-company.com/home.html" title="ACCESS Co."><img alt="Access Company" src="./images/access_logo.png" /></a></div></div></div><div id="licenseFooter"><div id="licenseFooterBL"><a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/" title="Creative Commons License"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by-nc-nd/3.0/88x31.png" /></a></div><div id="licenseFooterBR"><a href="./LegalNotice.html">Legal Notice</a></div><div id="licenseFooterBC"><span id="licenseText">This work is licensed under a
|
||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative
|
||
Commons Attribution-Non commercial-No Derivative Works 3.0 License</a>.</span></div></div></body></html>
|