Be Newsletter
Issue 64, March 12, 1997
Table of Contents
BE ENGINEERING INSIGHTS: By The Node Monitor
By Cyril Meurillon
The Node Monitor is a new service that will accompany the
DR9 file system. It lets your application ask to be notified
when certain changes are made to a file or directory. For
example, you can "watch for" the creation and deletion of
files within a directory, for the modification of a specific
file's attributes or name, and so on.
As a built-in feature of the file system, the Node Monitor
is part of the kernel: It's always there. However, it's
anticipated that most applications won't need the Node
Monitor; watching the state of the file system is important
to servers and to navigational applications like the
Tracker, but your Tetris killer -- or even your Excel
insulter -- probably isn't going to care.
The Node Monitor is, in our estimation, an advanced feature;
the API for the Monitor is, suitably, rather low level --
it's not downright unfriendly, but it does have a somewhat
more mechanical view of the identity of files, as we're
about to see.
CAVEAT: The API that we'll be looking at throughout this
article isn't set in stone. Although the general concepts
should remain valid, some of the names may change before DR9
is released.
To tell the Node Monitor that you want to watch for changes,
you use the global watch_for() function:
watch_for(ulong flags, dev_t device, ino_t inode,
const BHandler *handler, const BLooper *looper);
The file or directory (or "node") that you're watching is
represented by the combination of the function's device and
inode arguments. (Conversion between device /inode and the
entry_ref structure/C++ objects, which were described in
last week's Newsletter, will be provided by the Storage
Kit.)
The activities that you're interested in watching are
represented by the constants that you pass through the flags
argument:
B_WATCH_NAME means you want to be told whenever the node
is renamed. This includes being moved to a new directory.
B_WATCH_STAT watches for changes to the stat structure.
This is the structure that records a node's size, creation
and modification dates, permissions, and so on.
B_WATCH_ATTR watches for changes to the node's attributes.
(See Be Newsletter #51 for more on attributes.)
B_WATCH_DIRECTORY watches for any changes to the list of
files that a directory contains. In other words, it watches
for files that are added to or removed from the directory.
Obviously, this flag only applies to directory nodes.
The special flag B_STOP_WATCHING can be passed to stop
watching the node.
When a change is detected, the Node Monitor generates a
BMessage and sends it to the "watcher" (a BHandler object)
that's specified in the watch_for() call. The watcher
receives the message in its MessageReceived() function. (The
Node Monitor divines the target from the handler and looper
arguments through a series of logical steps that are really
not very interesting.)
Each of the watched-for flags corresponds to a particular
type of message: B_WATCH_NAME generates a B_ENTRY_MOVED
message, B_WATCH_STAT generates B_STAT_CHANGED , and so on.
We'll look at an example of the Monitor's messaging later in
this article.
MONITOR VS. LIVE QUERIES
"Tres bien," you dit to yourself, "mais, comment c'est en
mieux a la 'Querie Vif!' en DRHuit?" ("How is this better
than DR8's live queries?")
True, you could "watch" changes to files and directories in
DR8 by installing a live query with the Storage Server --
this is how the Browser kept its folder windows in synch
with the file system, for example. But a live query can (or
could) only watch for changes to fields in the database
tables that represent the items in the file system. In other
words, this sort of monitoring worked because certain file
system parameters (file names, creation dates, and so on)
were stored in the database. But in DR9 we're going start
supporting foreign file systems, and these file systems (HFS
and DOS, for starters) don't know anything about Be-native
database facilities. Thus, a live query can't work on a
foreign file.
This is where the Node Monitor can be useful: It's a
"universal" service for spying on files and directories in
any file system. Some file systems may not provide complete
snoopage; it's likely that you won't be able to monitor
attribute changes in DOS simply because DOS doesn't know
about attributes. But one of the line items in the contract
for becoming a "File System Handler" is that stat and
directory-content information MUST be emulated. In other
words, the DOS file system handler knows how to fake a stat
structure. Thus, you'll be able to, at least, watch for
changes to the arrangement of files in any mountable file
system.
Note that the Node Monitor isn't a replacement for live
queries. But neither are live queries going away: In DR9,
you'll have the best of both worlds.
EXAMPLE (PRINT SERVER)
Let's consider an application that uses the Node Monitor:
the Print Server. When you print, the data that you're
printing is written to a "spool file." It's the Print
Server's responsibility to:
- Detect the presence of a new spool file.
- Wait for the file's "status" attribute to change to
"waiting" (this indicates that the file is ready to be
printed).
- Change the status to "printing" and print the file.
Spool files are always written to a known spool directory;
to detect new spool files, the Print Server asks the Node
Monitor to inform it of new entries in this directory:
PrintServer::PrintServer() : BApplication('PRNT')
{
dev_t spoolDevice;
ino_t spoolInode;
// Get the device and inode of the spool directory
get_inode_for_path("/boot/system/spool", &spoolDevice, &spoolInode);
// Start watching for new files in that directory.
// The final two arguments tell the Monitor to send
// notifications to this object's preferred handler.
watch_for(B_WATCH_DIRECTORY, spoolDevice, spoolInode, NULL, this);
// We're also going to need another looper later.
fStatusWatcher = new StatusWatcher();
...
}
When a spool file is created, a B_ENTRY_CREATED message is
sent to PrintServer's main loop. The "what " for Node Monitor
messages is always B_FS_NOTIFICATION . The Monitor message
type is in the "opcode " field:
long PrintServer::MessageReceived(BMessage *msg)
{
dev_t fileDevice;
ino_t fileInode;
switch (msg->what) {
. . .
case B_FS_NOTIFICATION:
switch(msg->FindLong("opcode")) {
case B_ENTRY_CREATED:
// Get the device and inode for the file;
// these are stored in the message.
fileDevice = msg->FindLong("device");
fileInode = msg->FindLong("node");
At this point, the Server knows the identity (as a
device/inode) of the new spool file. Now it waits for the
"status" attribute to change to "waiting" by asking for an
attribute-has-changed notification. Obviously, the Server
has to find a different watcher for these notifications --
that's why we defined the fStatusWatcher object:
watch_for(B_WATCH_ATTR, fileDevice, fileInode, NULL, fStatusWatcher);
. . .
}
}
}
(Note: There's a race condition in this code: What happens
if the spool file is already "waiting" when the first
notification is processed? The solution is left as an
exercise for the reader.)
Over in the StatusWatcher handler, we find...
long StatusWacher::MessageReceived(BMessage *msg)
{
dev_t fileDevice;
ino_t fileInode;
BFile spoolFile;
char buf[16];
switch (msg->what) {
case B_FS_NOTIFICATION:
switch(msg->FindLong("opcode")) {
case B_ATTR_CHANGED:
// make sure this is the status attribute
// that has changed.
if (strcmp(msg->FindString("attr"), "status") != 0)
break;
// Again, convert the msg into a
// device/inode and thence to a BFile...
fileDevice = msg->FindLong("device");
fileInode = msg->FindLong("node");
spoolFile = BFile(fileDevice, fileInode);
// ...and read the "status" attribute.
spoolFile.ReadAttr("status", buf, sizeof(buf));
/* if the status isn't "waiting", get out. */
if (strcmp(buf, "waiting") != 0)
break;
/* Set the status to "printing" */
/* and print the file. */
spoolFile.WriteAttr("status", "printing", strlen("printing")+1);
SendToPrinter(spoolFile);
. . .
Again, remember that the file system API is still subject to
change, so don't start porting your code on the basis of the
names shown here.
News from the Front
By William Adams
The early adopters and developers on a new OS platform
exhibit behavior that might be considered obsessive and
irrational. When I first received my BeBox(TM) last year, I
couldn't help but read every shred of information available
in the newsgroups, and I hungered for e-mail exchanges with
like-minded folks. I longed for new web sites and new
software on any ftp site.
This hunger and desire reaches a fevered pitch as a
'release' date approaches. DR5, DR6, DR7... Well, it's been
a long time since a release, and DR8.2 for many has been the
first release. Not wanting anyone to burst a blood vessel
waiting for their next fix, we've decided to release DR8.3.
This is really just a maintenance release and doesn't offer
any new functionality. You'll find all the details about
this release on our Web site this week. The general gist is,
this release is for the Power Mac only, not for the BeBox (BeOS
for BeBox does not have the limitations that DR8.3 removes).
In DR8.2, the font renderer had a limited license that
required us to have a termination date, past which the OS
wouldn't operate. We've changed font providers, and this
requirement has been removed.
Serial support wasn't included in the DR8.2 CD that shipped
with MacTech. This release includes it.
There may also be a few more bug fixes, but that was not the
purpose of this release. The long and short of it is, IF
YOU'RE RUNNING DR8.2 ON A POWER MAC, YOU SHOULD DEFINITELY
INSTALL THIS UPGRADE!!
You don't want to interrupt your endless stream of BeOS fun,
so get this thing and install it immediately!!
Since we're the digital content creation platform of choice
for discriminating artists, I thought I'd throw up some more
code of the digital content variety. There have been quite a
few MPEG encoders and decoders in the air for the BeOS. I
thought I'd add the code for the Berkeley decoder just for
fun.
ftp://ftp.be.com/pub/samples/video/obsolete/mpeg_lib.tgz
This library isn't the fastest, or smartest, or highest
quality thing in the world. But the code is understandable,
easy to make into a shared library, and it's free. It should
be useful to those who endeavor to do similar things in the
BeOS.
We will continue to provide innovative fresh fertile ground
upon which you can program your heart away. And in the long
run, you'll be satisfied with a job well done, until the
next release.
Who's Stupid?
By Jean-Louis Gassée
We are, of course, not the programmer, or the user of our
software. Making your customer feel stupid should be
prohibited by the Constitution, and in any case, generating
such feelings is always harmful to business. Put another
way, while we can sometimes be forgiven for embarrassing
mistakes, we won't make friends by generating feelings of
inadequacy, especially if they're followed by a realization
that the mistake was ours in the first place. Hence our
decision to post our bugs on our Web site. Starting with
developers, we want to get in the habit of mapping the
minefield as accurately as we can. This will save everyone
time and energy, a good reason to start with. Then, as more
eyes see the range of reported problems, some pattern
recognition might take place, meaning one or more
individuals will pick up on a bad habit, or a regular trap,
and share their knowledge with the community. In the same
vein, our example might encourage BeOS application
developers to do the same for their customers -- and for the
rest of us -- with similar benefits.
This is all nice and good, but what about disadvantages? For
instance, will the competition use this against us?
Possibly. We might save their harried Competitive Studies
people some time. But nasty bugs end up reported one way or
the other, so we might as well do the reporting ourselves,
thus minimizing distortion. Another possible criticism
leveled at us for posting our bugs is you don't show
customers the inside of the sausage factory. They don't want
to know. To this, my answer is that if I start a sausage
factory, I have to make a much better sausage than the
established industrial meat processors. And, assuming I
actually make a better product, I then make a point of
seeking out sausage connoisseurs and taking them through the
kitchen. They see the ingredients coming in, they watch the
mixing process... I sense some problems with this kind of
metaphor, the penalty, I guess for venturing out of my usual
range. Still, many great restaurants feature a visible
kitchen. For us, letting light in on our OS-making process
is a healthy constraint. We'll be embarrassed on a regular
basis, always good for the product and the soul. And we'll
also get more helpful suggestions along the way than if we
didn't open our doors.
Of course, as the bug reports show, we still have a lot to
do and a lot to prove. Ironically, a maturing OS will mean
even more bugs reported, not fewer, as our system gains more
flesh and is stressed by more applications and more users.
BeDevTalk Summary
BeDevTalk is an unmoderated discussion group that's a forum
for the exchange of technical information, suggestions,
questions, mythology, and suspicions. In this column, we
summarize some of the active threads, listed by their
subject lines as they appear, verbatim, in the group.
To subscribe to BeDevTalk, visit the mailing list page on
our Web site: http://www.be.com/aboutbe/mailinglists.html.
- ----WEEK 2---------------------------
Subject: Time is running out!
AKA: STREAMS
More suggestions and discussion of features that are
essential -- or, at least, desirable -- for a baseline
(future backwards-compatible) release. This week:
- Intelligent versioning
- Coalesce view update messages from the app_server (when
requested)
- STREAMS support
- Networked BMessages
- UNIX-style man pages
- A well-defined system directory tree
There was some debate over STREAMS. Some folks think that
BSD sockets are not only better, but that having two network
port models is confusing.
Obviously, not all of the requests are essential to a
baseline customer release.
- ----NEW---------------------------
Subject: endian-ness
AKA: Intel port == bad!
AKA: Dave's Raves
Was Brad Taylor's article in last week's Newsletter, in
which he described the pitfalls that one should avoid when
sending data between machines that are, potentially,
differently byte-ordered, a hint of ports to come?
This speculation led to a discussion of the history of the
little-endian/big-endian battle of the (byte) sexes. The
history lesson then followed its own logic into the future,
which led to general crystal ball gazing and a fantasy about
little brown men that, frankly, I had trouble following.
We also heard arguments over the desirability of an Intel
port. On the pro side is the thought that general
proliferation of the BeOS is a Good Thing. Con has it that
an alliance with Intel would be (for now) an unnecessary,
resource-guzzling distraction. No it wouldn't. Yes it would.
THE BE LINE: As many of you pointed out, Brad Taylor's
article was a sincere tutorial on good network programming
practice. No "hints" were intended.
- ----NEW---------------------------
Subject: Overclocking your BeBox?
This thread, which sprang from the endian-ness discussion,
discussed the benefits/detriments of "overclocking" (or,
more accurately, "undertiming") the CPU.
Overclocking increases the speed of the CPU beyond its rated
limit; typical overclocking techniques involve soldering a
faster oscillator onto the motherboard (think of it as
dangling a bigger carrot in front of the hamster). It works
-- but does it decrease the life expectancy of the chip?
Some folks say, "You bet it does."
- ----NEW---------------------------
Subject: Funky networking apps
Various listeners volunteered descriptions of their personal
programming projects (whether actually implemented or not).
Among other things, we heard about...
- A socket server that could be used as the basis for
networked scripting [Jon Ragnarrson]
- A port of socket++ [Howard Berkey]
- A network-playable Stratego game [Ficus Kirkpatrick]
Other network ideas:
What about moving the network layer into the kernel?
This idea met some amount of horrified resistance.
Some old favorites, such as picking up an entire executable
and sending it down the wire, were trotted out and banged
around.
- ----NEW---------------------------
Subject: On stability of APIs
Looking ahead to subsequent customer releases, will BeOS 2.0
break all 1.0 applications? Would modular libraries (rather
than the monolithic libbe.so) help?
This led to a discussion of relative pathnames in #include
directives and whether "greg" is "bill". Slow week.
THE BE LINE: In DR9, libbe WILL be broken into separate
libraries. The divisions will primarily follow the kits.
- ----NEW---------------------------
Subject: Who's buried in Grant's Tomb?
Some possibilities: Grant, Lee, Lee Grant, Grant Tinker, Lee
Tucker, John Smiley, "smileys," Liam Neeson, Neil Sedaka,
Otis Redding, Marvin Gardens, Marvin Hamlisch, Ham, Shem,
H.C. Earwicker, Gomer, Homer, Onan, Conan, Robert Donat, the
Donner Party, Guess Who's Coming to Dinner?, Sidney Poitier,
Sidney Greenstreet, On Green Dolphin Street, Where's Someone
I Can Meet, Flipper, Ishmael, Billy Budd, Peter Grimes, Jon
Vickers, Vic Damone, Joey Ramone, Patti Lupone, Lucille
Ball, Bud Cort, Cary Grant, Grant's Kills Ants.
|