haiku-website/static/legacy-docs/bebook/BQuery_Overview.html

349 lines
29 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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 (==, &lt;, &gt;, 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: = &lt; &gt; &lt;= &gt;= !=
</p></li><li><p>
Logical operators: || &amp;&amp;
</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 &lt; 500
(name = fido) || (size &gt;= 500)
(! ((name = *id*) || ( 'final utterance' = 'pass the salt'))) &amp;&amp;
(last_modified &gt; 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 &lt; 500
</pre><p>
…becomes…
</p><pre class="screen">
size 500 &lt;
</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 &gt;= 500)</pre><p>
...becomes...
</p><pre class="screen">(name fido =) (size 500 &gt;=) ||</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>-&gt;<code class="methodname">FindInt32</code>("device", &amp;<code class="varname">ref.device</code>);
<code class="varname">msg</code>-&gt;<code class="methodname">FindInt64</code>("directory", &amp;<code class="varname">ref.directory</code>);
<code class="varname">msg</code>-&gt;<code class="methodname">FindString</code>("name", &amp;<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>-&gt;<code class="methodname">FindInt32</code>("device", &amp;<code class="varname">nref.device</code>);
<code class="varname">msg</code>-&gt;<code class="methodname">FindInt64</code>("node", &amp;<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>