Beispiel #1
0
        static Inotify()
        {
            if (Environment.GetEnvironmentVariable("BEAGLE_DISABLE_INOTIFY") != null)
            {
                Logger.Log.Debug("BEAGLE_DISABLE_INOTIFY is set");
                return;
            }

            if (Environment.GetEnvironmentVariable("BEAGLE_INOTIFY_VERBOSE") != null)
            {
                Inotify.Verbose = true;
            }

            try {
                inotify_fd = inotify_glue_init();
            } catch (EntryPointNotFoundException) {
                Logger.Log.Info("Inotify not available on system.");
                return;
            }

            if (inotify_fd < 0)
            {
                Mono.Unix.Native.Errno errno = Mono.Unix.Native.NativeConvert.ToErrno(-inotify_fd);

                string error_message;

                if (errno == Mono.Unix.Native.Errno.ENOSYS)
                {
                    error_message = "Inotify not supported!  You need a 2.6.13 kernel or later with CONFIG_INOTIFY enabled.";
                }
                else
                {
                    error_message = Mono.Unix.UnixMarshal.GetErrorDescription(errno);
                }

                Logger.Log.Warn("Could not initialize inotify: {0}", error_message);
            }
            else
            {
                try {
                    FileStream   fs = new FileStream("/proc/sys/fs/inotify/max_user_watches", FileMode.Open, FileAccess.Read);
                    StreamReader r  = new StreamReader(fs);

                    string line = r.ReadLine();
                    r.Close();

                    int watches = -1;
                    try {
                        watches = Int32.Parse(line);
                    } catch (FormatException) { }

                    if (watches > -1 && watches < 32768)
                    {
                        Log.Warn("Inotify watches may be too low ({0}) for some users!  Increase it to at least 65535 by setting fs.inotify.max_user_watches in /etc/sysctl.conf", watches);
                    }
                } catch { }
            }
        }
Beispiel #2
0
        // Ensure our watch exists, meets all the subscribers requirements,
        // and isn't matching any other events that we don't care about.
        private static void CreateOrModifyWatch(WatchInfo watched)
        {
            EventType new_mask = base_mask;

            foreach (WatchInternal watch in watched.Subscribers)
            {
                new_mask |= watch.Mask;
            }

            if (watched.Wd >= 0 && watched.Mask == new_mask)
            {
                return;
            }

            //Log.Debug ("{0} inotify watch on {1}", watched.Wd >= 0 ? "Recreating" : "Creating", watched.Path);

            // We rely on the behaviour that watching the same inode twice won't result
            // in the wd value changing.
            // (no need to worry about watched_by_wd being polluted with stale watches)

            int wd = -1;

            wd = inotify_glue_watch(inotify_fd, watched.Path, new_mask);
            if (wd < 0)
            {
                Mono.Unix.Native.Errno errno = Mono.Unix.Native.NativeConvert.ToErrno(-wd);

                if (!watch_limit_error_displayed && errno == Mono.Unix.Native.Errno.ENOSPC)
                {
                    Log.Error("Maximum inotify watch limit hit adding watch to {0}.  Try adjusting /proc/sys/fs/inotify/max_user_watches", watched.Path);
                    watch_limit_error_displayed = true;
                }

                string msg = String.Format("Attempt to watch {0} failed: {1}", watched.Path, Mono.Unix.UnixMarshal.GetErrorDescription(errno));
                throw new IOException(msg);
            }

            if (watched.Wd >= 0 && watched.Wd != wd)
            {
                string msg = String.Format("Watch handle changed unexpectedly!", watched.Path);
                throw new IOException(msg);
            }

            watched.Wd   = wd;
            watched.Mask = new_mask;
        }
Beispiel #3
0
        private static void Unsubscribe(WatchInfo watched, WatchInternal watch)
        {
            watched.Subscribers.Remove(watch);

            // Other subscribers might still be around
            if (watched.Subscribers.Count > 0)
            {
                // Minimize it
                CreateOrModifyWatch(watched);
                return;
            }

            int retval = inotify_glue_ignore(inotify_fd, watched.Wd);

            if (retval < 0)
            {
                Mono.Unix.Native.Errno errno = Mono.Unix.Native.NativeConvert.ToErrno(-retval);
                string msg = String.Format("Attempt to ignore {0} failed: {1}", watched.Path, Mono.Unix.UnixMarshal.GetErrorDescription(errno));
                throw new IOException(msg);
            }

            Forget(watched);
            return;
        }
Beispiel #4
0
            public override bool Obtain()
            {
                Log("Trying to obtain lock " + lockFile.FullName);
                if (Lucene.Net.Store.FSDirectory.disableLocks || Enclosing_Instance.InstanceDisableLock)
                {
                    return(true);
                }

                bool tmpBool;

                if (System.IO.File.Exists(Enclosing_Instance.lockDir.FullName))
                {
                    tmpBool = true;
                }
                else
                {
                    tmpBool = System.IO.Directory.Exists(Enclosing_Instance.lockDir.FullName);
                }
                if (!tmpBool)
                {
                    try
                    {
                        System.IO.Directory.CreateDirectory(Enclosing_Instance.lockDir.FullName);
                    }
                    catch (Exception)
                    {
                        throw new System.IO.IOException("Cannot create lock directory: " + Enclosing_Instance.lockDir);
                    }
                }

                try
                {
                    int fd = Mono.Unix.Native.Syscall.open(
                        lockFile.FullName,
                        Mono.Unix.Native.OpenFlags.O_RDWR |
                        Mono.Unix.Native.OpenFlags.O_CREAT |
                        Mono.Unix.Native.OpenFlags.O_EXCL,
                        Mono.Unix.Native.FilePermissions.S_IRUSR);
                    if (fd == -1)
                    {
                        Mono.Unix.Native.Errno error = Mono.Unix.Native.Stdlib.GetLastError();
                        if (error == Mono.Unix.Native.Errno.ENOSPC)
                        {
                            throw new Beagle.Util.NoSpaceException();
                        }
                        else
                        {
                            throw new System.IO.IOException("Could not create lock file: "
                                                            + Mono.Unix.Native.Stdlib.strerror(error));
                        }
                    }

                    // This code replaces the commented-out code below because
                    // it ends up being much faster.  The reason for this is
                    // that closing a UnixStream causes Syscall.fsync() to be
                    // called, and that apparently is extremely slow!
                    //
                    // Time(ms) Count   P/call(ms) Method name
                    // 1563.926      68   22.999   Mono.Unix.Native.Syscall::fsync(int)
                    //
                    // Since the lock file is written out very often, this time
                    // adds up and noticably slows down indexing.
                    IntPtr ptr = IntPtr.Zero;
                    long   ret;

                    try {
                        string s = System.Diagnostics.Process.GetCurrentProcess().Id.ToString() + "\n";
                        ptr = Mono.Unix.UnixMarshal.StringToHeap(s);

                        do
                        {
                            ret = Mono.Unix.Native.Syscall.write(fd, ptr, (ulong)s.Length);
                        } while (Mono.Unix.UnixMarshal.ShouldRetrySyscall((int)ret));
                        if ((int)ret == -1)
                        {
                            Mono.Unix.Native.Errno error = Mono.Unix.Native.Stdlib.GetLastError();
                            if (error == Mono.Unix.Native.Errno.ENOSPC)
                            {
                                throw new Beagle.Util.NoSpaceException();
                            }
                            else
                            {
                                Mono.Unix.UnixMarshal.ThrowExceptionForError(error);
                            }
                        }
                    } finally {
                        Mono.Unix.UnixMarshal.FreeHeap(ptr);

                        do
                        {
                            ret = Mono.Unix.Native.Syscall.close(fd);
                        } while (Mono.Unix.UnixMarshal.ShouldRetrySyscall((int)ret));
                        Mono.Unix.UnixMarshal.ThrowExceptionForLastErrorIf((int)ret);
                    }

                    //System.IO.StreamWriter w = new System.IO.StreamWriter (new Mono.Unix.UnixStream (fd, true));
                    //w.WriteLine (System.Diagnostics.Process.GetCurrentProcess ().Id);
                    //w.Close ();
                    return(true);
                }
                catch (Beagle.Util.NoSpaceException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    Log("Exception in CreateNew for file:" + lockFile.FullName + ":" + e);
                    return(false);
                }
            }