Some more fixes wrt child-indexables. Namely, fix proper handling of child indexables...
[beagle.git] / beagled / FileSystemQueryable / InotifyBackend.cs
blob947e57163ba249069862cb379eb109e7aa653ba2
1 //
2 // InotifyEventBackend.cs
3 //
4 // Copyright (C) 2005 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
27 using System;
28 using System.Collections;
29 using System.IO;
31 using Beagle.Util;
32 using Beagle.Daemon;
34 namespace Beagle.Daemon.FileSystemQueryable {
36 public class InotifyBackend : IFileEventBackend {
38 FileSystemQueryable queryable;
40 public object CreateWatch (string path)
42 object watch = null;
43 try {
44 watch = Inotify.Subscribe (path, OnInotifyEvent,
45 Inotify.EventType.Create
46 | Inotify.EventType.Delete
47 | Inotify.EventType.CloseWrite
48 | Inotify.EventType.MovedFrom
49 | Inotify.EventType.MovedTo);
52 catch (IOException) {
53 // We can race and files can disappear. No big deal.
55 return watch;
58 public bool ForgetWatch (object watch_handle)
60 try {
61 ((Inotify.Watch) watch_handle).Unsubscribe ();
62 } catch (Exception ex) {
63 Logger.Log.Error (ex, "Caught exception while doing ForgetWatch");
64 return false;
66 return true;
69 public void Start (FileSystemQueryable queryable)
71 this.queryable = queryable;
74 private void OnInotifyEvent (Inotify.Watch watch,
75 string path,
76 string subitem,
77 string srcpath,
78 Inotify.EventType type)
80 bool is_directory;
81 is_directory = (type & Inotify.EventType.IsDirectory) != 0;
83 queryable.ReportEventInDirectory (path);
85 // The case of matched move events
86 if ((type & Inotify.EventType.MovedTo) != 0 && srcpath != null) {
87 queryable.HandleMoveEvent (Path.GetDirectoryName (srcpath),
88 Path.GetFileName (srcpath),
89 path, subitem, is_directory);
90 return;
93 // Then this must be an unmatched moveto
94 // An unmatched MovedTo is like a create
95 if ((type & Inotify.EventType.MovedTo) != 0) {
97 // Synthesize the appropriate Create event. Note that we could check for the
98 // IsDirectory event here, but this also shrinks the race window.
99 if (is_directory)
100 type |= Inotify.EventType.Create;
101 else
102 type |= Inotify.EventType.CloseWrite;
103 Logger.Log.Debug ("Synthesizing event on unpaired MoveTo", type);
106 // An unmatched MovedFrom is like a delete
107 if ((type & Inotify.EventType.MovedFrom) != 0) {
108 type |= Inotify.EventType.Delete;
109 Logger.Log.Debug ("Synthesizing event on unpaired MoveFrom", type);
112 if ((type & Inotify.EventType.Delete) != 0) {
113 queryable.HandleRemoveEvent (path, subitem, is_directory);
114 return;
117 if ((type & Inotify.EventType.Create) != 0) {
118 if (is_directory)
119 queryable.HandleAddEvent (path, subitem, is_directory);
120 return;
123 if ((type & Inotify.EventType.CloseWrite) != 0) {
124 queryable.HandleAddEvent (path, subitem, is_directory);
125 return;
128 if ((type & Inotify.EventType.QueueOverflow) != 0) {
129 Logger.Log.Warn ("Inotify queue overflowed: file system is in an unknown state");
130 queryable.HandleOverflowEvent ();
131 return;