DESCRIPTION
This module provides asynchronous notification for changes happening on
files and/or directories. For that purpose only file and directory
(string) names are used for the registration. This makes AEM a
very convenient mechanism to handle recursive notification in
user space.
DEFINITIONS
#include <aem.h>
This file is located in the directory {AEMSRC}/include/user in the AEM
source package. It must be installed and included with your source code.
libaem
This is the AEM library. It is located in
the directory {AEMSRC}/lib
in the AEM source package. It must be installed and linked with your
source code.
Registration (inerest) events:
F_BIN
F_BOUT
F_BHUP
F_BOPEN
F_BOWNER
F_BMODE
F_BLOCK
F_BCREATE
F_BREMOVE
F_BRENAME
State (notification) flags:
B_IN
B_OUT
B_HUP
B_OPEN
B_OWNER
B_MODE
B_LOCK
B_CREATE
B_REMOVE
B_RENAME
total number of notification band:
NR_BAND
Array of
integers (event ID) called idset:
int idset[NR_BAND];
INTERFACES
The
following set of API is provided by libaem.
int aemFD_init (void);
Initialize the aem-fd functionality. This module alseo require memory
allocation through vmtable.
int aemFD_clear_idset (int
*);
Clear an idset.
int aemFD_notify_register
(char *, unsigned long, void *, int *);
Register events for the file/directory name given as the first
parameter. The second parameter is a OR
of event flags (F_Bflags given
above) wich represent events of interest. The third parameter is
the handler to called asynchronously . An idset pointer is given in the
last parameter which is filled up by the call. It containts the event
Id for each interest flags.
Handler prototype:
void notiication_handler (int
event_id, char *filename, int len, int pid, int band);
The first parameter is the event Id obtained during registration. The
name of the file/directory on which an event occured is givent in
parameter as well as the length of the string. The other parameters are
the pid of the process that
triggered the action (event) and the event itself (B_flags givent above).
int aemFD_notify_start
(int *);
Enable notification for the idset in parameter.
int aemFD_notify_stop (int
*);
Disbale
notification for the idset in parameter.
int aemFD_notify_unregister (int *);
Unregister events for the idset in parameter.
int aemFD_hash (int *);
Hash the idset in parameter. This permits to retrieve later the idset
corresponding to a specific event Id. This is typically called after
registration.
int aemFD_unhash (int *);
Unhash the idset given in parameter. This is typically called before
un-registration of events.
int *aemFD_get_idset (int
);
Retrieve
the idset corresponding to a specific event Id.
EXAMPLE
The following example illustrates a server that gets asynchronous
notification for changes on files and directories starting at /tmp.
This example is also available in the examples that come with the
source package.
#include
<stdio.h>
#include <fcntl.h>
#include <aem.h>
/*
* This example
illustrates how to get notifications for changes on files
* and how to
handle sub-directory and recursive registrations with AEM.
*/
const char
*band_helper[NR_BAND] = {
"B_IN",
"B_OUT",
"B_HUP",
"B_OPEN",
"B_OWNER",
"B_MODE",
"B_LOCK",
"B_CREATE",
"B_REMOVE",
"B_RENAME"
};
static void check_idset
(int *idset)
{
int i;
for
(i=0 ; i<NR_BAND ; i++) {
if (idset[i] <= 0)
printf ("Could not register for
'%s' - value = %d\n", band_helper[i], idset[i]);
}
}
/*
* This is the
handler for file and directory change notifications
* The
file/directory name is directly received by the process.
*/
void fd_events (int jid,
char *filename, int len, int pid, int band)
{
int
err;
int
idset[NR_BAND];
int
*set;
if
(len <= 0)
return;
*(filename + len) = '\0';
printf ("[%d] notification '%s' for '%s'\n", jid, band_helper[band],
filename);
switch (band) {
case
B_REMOVE:
printf ("[%d] removing entry '%s'\n", jid, filename);
set = aemFD_get_idset (jid);
if (!set) {
printf ("Event un-registration
cannot find idset from jid=%d. Aborting.\n", jid);
exit (1);
}
err = aemFD_notify_unregister (set);
if (err > 0) {
printf ("%d event un-registration
errors in handler. Aborting.\n", err);
exit (1);
}
err = aemFD_unhash (set);
if (err < 0) {
perror ("");
exit (1);
}
break;
case
B_CREATE:
/*
* Recursively register newly created entries
*/
aemFD_clear_idset (idset);
printf ("[%d] event registration for '%s'\n", jid,
filename);
err = aemFD_notify_register (filename, F_BIN |
F_BOUT | F_BHUP | F_BOPEN | F_BOWNER
| F_BMODE | F_BLOCK |
F_BCREATE | F_BREMOVE | F_BRENAME,
fd_events, idset);
if (err == NR_BAND) {
printf ("No events could be
registered for '%s'. Bailing out.\n", filename);
return;
}
if (err > 0)
check_idset (idset);
err = aemFD_hash (idset);
if (err < 0) {
perror ("hash:");
return;
}
err = aemFD_notify_start (idset);
if (err < 0) {
perror ("start:");
exit (1);
}
break;
default:
break;
}
}
main (int argc, char
**argv)
{
int
err;
int
idset[NR_BAND];
/* We
need the AEM memory management here */
if
(aemCORE_init (TBL_UZONE) < 0)
exit (1);
if
(aemFD_init () < 0)
exit (1);
aemFD_clear_idset (idset);
/* we
want to receive all possible notifications for changes happening in
/tmp */
err =
aemFD_notify_register ("/tmp", F_BIN | F_BOUT | F_BHUP | F_BOPEN |
F_BOWNER
| F_BMODE | F_BLOCK | F_BREMOVE | F_BCREATE |
F_BRENAME,
fd_events, idset);
if
(err == NR_BAND) {
printf ("No events could be registered for /tmp.
Bailing out.\n");
exit (1);
}
if
(err > 0)
check_idset (idset);
err =
aemFD_hash (idset);
if
(err < 0) {
perror ("");
exit (1);
}
/*
let's go */
err =
aemFD_notify_start (idset);
if
(err < 0) {
perror ("");
exit (1);
}
printf ("Monitoring changes under /tmp ...\n");
while
(1)
pause ();
}
|