0

I'm working on a file monitoring daemon written in PHP, using the inotify PECL extension. I've nearly got it finished, as in it tells me when an inotify event happens.

The return value of inotify_read($fd) is an array that looks like this:

Array
(
    [0] => Array
        (
            [wd] => 2
            [mask] => 1073741840
            [cookie] => 0
            [name] => collaphoto
        )

    [1] => Array
        (
            [wd] => 2
            [mask] => 1073741856
            [cookie] => 0
            [name] => filewatcher
        )

    [2] => Array
        (
            [wd] => 2
            [mask] => 1073741840
            [cookie] => 0
            [name] => filewatcher
        )

)

If I understand it correctly, each sub array is an individual event, with information about that event. wd is the descriptor of the inotify instance, mask is the integer value of the flags that triggered the event, eg IN_ATTRIB or IN_ACCESS, cookie is a unique ID to connect this event to another event in the queue, and name is the directory or file that was changed. The name is only given if a directory is being watched by inotify.

My question is how do I figure out what Bit Mask triggered the event based on the mask value given? I'm still fairly inexperienced with dealing with Bit Masks, so go easy on me.

Full List of inotify Flags

Goldentoa11
  • 1,700
  • 2
  • 17
  • 29
  • Hmmm...I'm trying to think of an elegant way to do this. Have you considered making an array with all the constant names in it then just looping through and comparing til you find the right one, foreach loop with $key => $value format? – Zarathuztra Dec 14 '13 at 17:59
  • There's an idea.. I might just try that. On another note, I can tell the program which events to listen for, so I thought about running it repetitively, switching out the flag to listen for each time, and recording the value. But there are a lot of flags to listen for... :P – Goldentoa11 Dec 14 '13 at 18:02
  • For sure! I'm just trying to figure out the absolute best way to do this since we're talking about monitoring the file system. – Zarathuztra Dec 14 '13 at 18:13
  • I'm gonna try your suggestion and let you know how it works. One quick question though, if `inotify` returns multiple flags per event (which I *do* doubt), do you know how I could efficiently figure out which flags triggered it? – Goldentoa11 Dec 14 '13 at 18:16
  • Hmmmm I think I'd need to see an example of that to really give you a decent answer – Zarathuztra Dec 14 '13 at 18:17
  • (Using Bit Mask, Flag, and integer value interchangeably) If `inotify_read` returns a mask that would *resolve* to the value of `IN_CLOSE | IN_MOVE` (which I doubt it would return), is there an efficient way to figure out which _X_ Masks are in play? – Goldentoa11 Dec 14 '13 at 18:24
  • Hmmm that's a good question. I've never gotten this close to the OS before in PHP. – Zarathuztra Dec 14 '13 at 18:29
  • Thought you might be interested in seeing the source, so I put it on bitbucket. [FileWatcher Source](https://bitbucket.org/kkeiper1103/filewatcher) – Goldentoa11 Dec 14 '13 at 18:32
  • 1
    Hey, your suggestion worked great. I created an associative array where the key is the actual flag and the value is the textual name. If you post that as the answer, I'll accept it, since you gave me the idea. All I had to do then was `echo $this->_allFlags[ $evt['mask'] ]` – Goldentoa11 Dec 14 '13 at 21:09
  • Nice job on the code dude, I like! – Zarathuztra Dec 15 '13 at 02:39

1 Answers1

0

It's really not the most elegant solution I could think of, because we're talking about an event that could occur quite often and be difficult to come up with a decent strategy for dealing with constant model changes, observing filesystem changes that is. Here is my sort of brute force method for dealing with such a thing.

So we have a master list of constants (which underneath all have a value of course), and we have numerical values coming back from the filesystem that need to match up with one of the constants.

What do? Well, stringify the numeric values to create an associative array where the numeric values are the keys and the named constants are the values. This array is just a place holder of sorts and not meant to be modified, so make try to keep it as constant as possible. You can't declare an array as constant, but there are some hacks out there to do so. I'd also recommend making it static so that only one copy exists, and see if you can figure out a way to maximize seek times in the structure. That may be based on how much your filesystem changes and how many lookups you need to perform on the array, but you should be safe so long as PHP does a good job with its hash tables and keeps associative arrays at O(1) time.

NOTE: Just in case you run into memory issues with your keys being the way they are: The scoop on PHP array sizes

Community
  • 1
  • 1
Zarathuztra
  • 3,215
  • 1
  • 20
  • 34