Пример #1
0
        private static void HandleSignal(int signal)
        {
            Logger.Log.Debug("Handling signal {0} ({1})", signal, (Mono.Unix.Native.Signum)signal);

            // Pass the signals to the helper too.
            GLib.Idle.Add(new GLib.IdleHandler(delegate()
            {
                RemoteIndexer.SignalRemoteIndexer((Mono.Unix.Native.Signum)signal);
                return(false);
            }));

            // If we get SIGUSR1, turn the debugging level up.
            if ((Mono.Unix.Native.Signum)signal == Mono.Unix.Native.Signum.SIGUSR1)
            {
                LogLevel old_level = Log.Level;
                Log.Level = LogLevel.Debug;
                Log.Debug("Moving from log level {0} to Debug", old_level);
                return;
            }
            else if ((Mono.Unix.Native.Signum)signal == Mono.Unix.Native.Signum.SIGUSR2)
            {
                // Debugging hook for beagled
                QueryDriver.DebugHook();
                LuceneCommon.DebugHook();
                return;
            }

            Logger.Log.Debug("Initiating shutdown in response to signal.");
            Shutdown.BeginShutdown();
        }
Пример #2
0
        internal void WorkerFinished(object o)
        {
            lock (this) {
                Debug.Assert(workers > 0, "Too many calls to WorkerFinished");
                --workers;


                DateTime now = DateTime.Now;

                //DateTime then = (DateTime) per_worker_started_time [o];
                //Logger.Log.Debug ("{0} finished in {1:0.00}s", o, (now - then).TotalSeconds);

                per_worker_started_time.Remove(o);

                if (workers == 0)
                {
                    finished_time = now;
                    //Logger.Log.Debug ("Last worker finished {0:0.00}s after start",
                    //(finished_time - started_time).TotalSeconds);
                    if (FinishedEvent != null)
                    {
                        FinishedEvent(this);
                    }
                    Monitor.Pulse(this);
                }
            }
            Shutdown.WorkerFinished(o);
        }
Пример #3
0
 private void RunInThread()
 {
     try {
         this.Run();
     } catch (ThreadAbortException) {
         Thread.ResetAbort();
         Log.Debug("Breaking out of UnixListener -- shutdown requested");
         Shutdown.WorkerFinished(this);
     }
 }
Пример #4
0
        private static int BeagleXIOErrorHandler(IntPtr display)
        {
            Logger.Log.Debug("Lost our connection to the X server!  Trying to shut down gracefully");

            if (!Shutdown.ShutdownRequested)
            {
                Shutdown.BeginShutdown();
            }

            Logger.Log.Debug("Xlib is forcing us to exit!");

            ExceptionHandlingThread.SpewLiveThreads();

            // Returning will cause xlib to exit immediately.
            return(0);
        }
Пример #5
0
        private void Run()
        {
            this.unix_listener.Start();

            if (!Shutdown.WorkerStart(this, String.Format("server '{0}'", socket_path)))
            {
                return;
            }

            while (this.running)
            {
                UnixClient client;
                try {
                    // This will block for an incoming connection.
                    // FIXME: But not really, it'll only wait a second.
                    // see the FIXME in UnixListener for more info.
                    client = this.unix_listener.AcceptUnixClient();
                } catch (SocketException) {
                    // If the listener is stopped while we
                    // wait for a connection, a
                    // SocketException is thrown.
                    break;
                }

                // FIXME: This is a hack to work around a mono
                // bug.  See the FIXMEs in UnixListener.cs for
                // more info, but client should never be null,
                // because AcceptUnixClient() should be
                // throwing a SocketException when the
                // listener is shut down.  So when that is
                // fixed, remove the if conditional.

                // If client is null, the socket timed out.
                if (client != null)
                {
                    ConnectionHandler handler = new UnixConnectionHandler(client);
                    lock (live_handlers)
                        live_handlers [handler] = handler;
                    ExceptionHandlingThread.Start(new ThreadStart(handler.HandleConnection));
                }
            }

            Shutdown.WorkerFinished(this);

            Logger.Log.Debug("Server '{0}' shut down", this.socket_path);
        }
Пример #6
0
        private static void LogMemoryUsage()
        {
            while (!Shutdown.ShutdownRequested)
            {
                SystemInformation.LogMemoryUsage();

                int vm_rss = SystemInformation.VmRss;

                if (arg_heap_shot && arg_heap_shot_snapshots)
                {
                    MaybeSendSigprof(vm_rss, GC.GetTotalMemory(false));
                }

                if (vm_rss > 300 * 1024)
                {
                    Logger.Log.Debug("VmRss too large --- shutting down");
                    Shutdown.BeginShutdown();
                }

                Thread.Sleep(5000);
            }
        }
Пример #7
0
        private bool WorkerStartNoLock(object o)
        {
            if (!Shutdown.WorkerStart(o))
            {
                return(false);
            }

            DateTime now = DateTime.Now;

            per_worker_started_time [o] = now;
            ++workers;
            if (workers == 1)
            {
                started_time = now;
                if (StartedEvent != null)
                {
                    StartedEvent(this);
                }
            }


            return(true);
        }
 private void DoShutdown()
 {
     Shutdown.BeginShutdown();
 }
Пример #9
0
        static void DoMain(string [] args)
        {
            SystemInformation.SetProcessName("beagle-build-index");

            if (args.Length < 2)
            {
                PrintUsage();
            }

            ArrayList allowed_patterns = new ArrayList();
            ArrayList denied_patterns  = new ArrayList();

            int i = 0;

            while (i < args.Length)
            {
                string arg = args [i];
                ++i;
                string next_arg = i < args.Length ? args [i] : null;

                switch (arg)
                {
                case "-h":
                case "--help":
                    PrintUsage();
                    break;

                case "--tag":
                    if (next_arg != null)
                    {
                        arg_tag = next_arg;
                    }
                    ++i;
                    break;

                case "-r":
                case "--recursive":
                    arg_recursive = true;
                    break;

                case "--enable-deletion":
                    arg_delete = true;
                    break;

                case "--disable-directories":
                    arg_disable_directories = true;
                    break;

                case "--enable-text-cache":
                    arg_cache_text = true;
                    break;

                case "--target":
                    if (next_arg != null)
                    {
                        arg_output = Path.IsPathRooted(next_arg) ? next_arg : Path.GetFullPath(next_arg);
                    }
                    ++i;
                    break;

                case "--disable-filtering":
                    arg_disable_filtering = true;
                    break;

                case "--disable-on-battery":
                    arg_disable_on_battery = true;
                    break;

                case "--allow-pattern":
                    if (next_arg == null)
                    {
                        break;
                    }

                    if (next_arg.IndexOf(',') != -1)
                    {
                        foreach (string pattern in next_arg.Split(','))
                        {
                            allowed_patterns.Add(pattern);
                        }
                    }
                    else
                    {
                        allowed_patterns.Add(next_arg);
                    }

                    ++i;
                    break;

                case "--deny-pattern":
                    if (next_arg == null)
                    {
                        break;
                    }

                    if (next_arg.IndexOf(',') != -1)
                    {
                        foreach (string pattern in next_arg.Split(','))
                        {
                            denied_patterns.Add(pattern);
                        }
                    }
                    else
                    {
                        denied_patterns.Add(next_arg);
                    }

                    ++i;
                    break;

                case "--disable-restart":
                    arg_disable_restart = true;
                    break;

                case "--source":
                    if (next_arg == null)
                    {
                        break;
                    }

                    arg_source = next_arg;
                    ++i;
                    break;

                case "--removable":
                    arg_removable = true;
                    break;

                default:
                    if (arg.StartsWith("-") || arg.StartsWith("--"))
                    {
                        PrintUsage();
                    }

                    string path = Path.IsPathRooted(arg) ? arg : Path.GetFullPath(arg);
                    if (path != "/" && path.EndsWith("/"))
                    {
                        path = path.TrimEnd('/');
                    }

                    if (Directory.Exists(path))
                    {
                        pending_directories.Enqueue(new DirectoryInfo(path));
                    }
                    else if (File.Exists(path))
                    {
                        pending_files.Enqueue(new FileInfo(path));
                    }
                    break;
                }
            }

            /////////////////////////////////////////////////////////

            if (arg_output == null)
            {
                Logger.Log.Error("--target must be specified");
                Environment.Exit(1);
            }

            // Set the storage dir, this should be used to store log messages
            // and filterver.dat
            PathFinder.StorageDir = arg_output;

            foreach (FileSystemInfo info in pending_directories)
            {
                if (Path.GetFullPath(arg_output) == info.FullName)
                {
                    Logger.Log.Error("Target directory cannot be one of the source paths.");
                    Environment.Exit(1);
                }
            }

            foreach (FileSystemInfo info in pending_files)
            {
                if (Path.GetFullPath(arg_output) == info.FullName)
                {
                    Logger.Log.Error("Target directory cannot be one of the source paths.");
                    Environment.Exit(1);
                }
            }

            if (!Directory.Exists(Path.GetDirectoryName(arg_output)))
            {
                Logger.Log.Error("Index directory not available for construction: {0}", arg_output);
                Environment.Exit(1);
            }

            // Be *EXTRA PARANOID* about the contents of the target
            // directory, because creating an indexing driver will
            // nuke it.
            if (Directory.Exists(arg_output))
            {
                foreach (FileInfo info in DirectoryWalker.GetFileInfos(arg_output))
                {
                    if (Array.IndexOf(allowed_files, info.Name) == -1)
                    {
                        Logger.Log.Error("{0} doesn't look safe to delete: non-Beagle file {1} was found", arg_output, info.FullName);
                        Environment.Exit(1);
                    }
                }

                foreach (DirectoryInfo info in DirectoryWalker.GetDirectoryInfos(arg_output))
                {
                    if (Array.IndexOf(allowed_dirs, info.Name) == -1)
                    {
                        Logger.Log.Error("{0} doesn't look safe to delete: non-Beagle directory {1} was found", arg_output, info.FullName);
                        Environment.Exit(1);
                    }
                }
            }

            string config_file_path = Path.Combine(arg_output, "StaticIndex.xml");
            string prev_source      = null;

            if (File.Exists(config_file_path))
            {
                Config static_index_config = Conf.LoadFrom(config_file_path);
                if (static_index_config == null)
                {
                    Log.Error("Invalid configuation file {0}", config_file_path);
                    Environment.Exit(1);
                }

                prev_source = static_index_config.GetOption("Source", null);
                if (arg_source != null && prev_source != arg_source)
                {
                    Log.Error("Source already set to {0} for existing static index. Cannot set source to {1}.", prev_source, arg_source);
                    Environment.Exit(1);
                }

                bool prev_removable = static_index_config.GetOption("Removable", false);
                if (arg_removable != prev_removable)
                {
                    Log.Error("Index previously created for {0}-removable path",
                              (prev_removable ? "" : "non"));
                    Environment.Exit(1);
                }
                else
                {
                    volume_label = static_index_config.GetOption("VolumeLabel", null);
                }

                // If arg_source is not given, and prev_source is present, use prev_source
                // as the arg_source. This is useful for re-running build-index without
                // giving --arg_source for already existing static index
                arg_source = prev_source;
            }

            // Removable media related options
            if (arg_removable)
            {
                if (pending_files.Count > 0)
                {
                    Log.Error("Indexing individual files is not allowed for removable media.");
                    Environment.Exit(1);
                }
                else if (pending_directories.Count > 1)
                {
                    Log.Error("Indexing multiple root directories is not allowed for removable media.");
                    Environment.Exit(1);
                }

                mnt_dir = ((DirectoryInfo)pending_directories.Peek()).FullName;
                if (mnt_dir.Length != 1)
                {
                    mnt_dir = mnt_dir.TrimEnd('/');
                }

                // compute volume label
                // (1) directory name if block.is_volume is false
                // (2) hal volume.label if set
                // (3) hal volume.uuid if set
                Hal.Manager manager    = new Hal.Manager(new Hal.Context());
                Hal.Device  mnt_device = null;

                foreach (Hal.Device device in manager.FindDeviceStringMatch("volume.mount_point", mnt_dir))
                {
                    mnt_device = device;
                }

                string new_volume_label = null;
                if (mnt_device != null)
                {
                    new_volume_label = mnt_device.GetPropertyString("volume.label");


                    if (String.IsNullOrEmpty(new_volume_label))
                    {
                        new_volume_label = mnt_device.GetPropertyString("volume.uuid");
                    }
                }

                if (new_volume_label == null)
                {
                    new_volume_label = ((DirectoryInfo)pending_directories.Peek()).Name;
                }

                // Sanity check
                // Volume label is part of the URI, so cannot be changed once set
                if (volume_label == null)
                {
                    volume_label = new_volume_label;
                }
                else if (volume_label != new_volume_label)
                {
                    Log.Error("Volume label (earlier '{0}') changed (to '{1}')! You need to create a new index.", volume_label, new_volume_label);
                    Environment.Exit(1);
                }
            }

            if (arg_source == null)
            {
                DirectoryInfo dir = new DirectoryInfo(StringFu.SanitizePath(arg_output));
                arg_source = dir.Name;
            }

            if (!BatteryMonitor.UsingAC && arg_disable_on_battery)
            {
                Log.Always("Indexer is disabled when on battery power (--disable-on-battery)");
                Environment.Exit(0);
            }

            string global_files_config = Path.Combine(PathFinder.ConfigDataDir, "config-files");

            global_files_config = Path.Combine(global_files_config, Conf.Names.FilesQueryableConfig + ".xml");
            if (!File.Exists(global_files_config))
            {
                Log.Error("Global configuration file not found {0}", global_files_config);
                Environment.Exit(0);
            }

            // Setup regexes for allowed/denied patterns
            if (allowed_patterns.Count > 0)
            {
                allowed_regex = StringFu.GetPatternRegex(allowed_patterns);
            }
            else
            {
                // Read the exclude values from config
                // For system-wide indexes, only the global config value will be used
                Config          config = Conf.Get(Conf.Names.FilesQueryableConfig);
                List <string[]> values = config.GetListOptionValues(Conf.Names.ExcludePattern);
                if (values != null)
                {
                    foreach (string[] exclude in values)
                    {
                        denied_patterns.Add(exclude [0]);
                    }
                }

                if (denied_patterns.Count > 0)
                {
                    denied_regex = StringFu.GetPatternRegex(denied_patterns);
                }
            }

            Log.Always("Starting beagle-build-index (pid {0}) at {1}", Process.GetCurrentProcess().Id, DateTime.Now);

            // Set system priorities so we don't slow down the system
            SystemPriorities.ReduceIoPriority();
            SystemPriorities.SetSchedulerPolicyBatch();
            SystemPriorities.Renice(19);

            driver           = new LuceneIndexingDriver(arg_output, MINOR_VERSION, false);
            driver.TextCache = (arg_cache_text) ? new TextCache(arg_output) : null;
            if (driver.TextCache != null)
            {
                driver.TextCache.WorldReadable = true;
            }

            backing_fa_store = new FileAttributesStore_Sqlite(driver.TopDirectory, driver.Fingerprint);
            fa_store         = new FileAttributesStore(backing_fa_store);

            // Set up signal handlers
#if MONO_1_9
            Shutdown.SetupSignalHandlers(delegate(int signal)
            {
                if (signal == (int)Mono.Unix.Native.Signum.SIGINT ||
                    signal == (int)Mono.Unix.Native.Signum.SIGTERM)
                {
                    Shutdown.BeginShutdown();
                }
            });
#else
            SetupSignalHandlers();
#endif

            Thread monitor_thread = null;

            Stopwatch watch = new Stopwatch();
            watch.Start();

            if (!arg_disable_restart)
            {
                // Start the thread that monitors memory usage.
                monitor_thread = ExceptionHandlingThread.Start(new ThreadStart(MemoryMonitorWorker));
            }

            // Start indexworker to do the crawling and indexing
            IndexWorker();

            // Join any threads so that we know that we're the only thread still running
            if (monitor_thread != null)
            {
                monitor_thread.Join();
            }

            watch.Stop();
            Logger.Log.Debug("Elapsed time {0}.", watch);

            // Write this after indexing is done. This is because, if creating a new index,
            // LuceneIndexingDriver.Create() is called which purges the entire directory.

            if (prev_source == null)
            {
                Config static_index_config = Conf.LoadNew("StaticIndex.xml");

                // Write StaticIndex.xml containing:
                // The name of the source
                static_index_config.SetOption("Source", arg_source);
                static_index_config ["Source"].Description = "Source of the static index";

                if (arg_removable)
                {
                    static_index_config.SetOption("VolumeLabel", volume_label);
                    static_index_config ["VolumeLabel"].Description = "Volume label of the removable source";

                    static_index_config.SetOption("Removable", true);
                    static_index_config ["Removable"].Description = "Removable source";
                }

                Conf.SaveTo(static_index_config, config_file_path);
            }

            if (restart)
            {
                Logger.Log.Debug("Restarting beagle-build-index");
                Process p = new Process();
                p.StartInfo.UseShellExecute = false;
                // FIXME: Maybe this isn't the right way to do things?  It should be ok,
                // the PATH is inherited from the shell script which runs mono itself.
                p.StartInfo.FileName  = "mono";
                p.StartInfo.Arguments = String.Join(" ", Environment.GetCommandLineArgs());
                p.Start();
            }

            Log.Always("Exiting beagle-build-index (pid {0}) at {1}", Process.GetCurrentProcess().Id, DateTime.Now);
        }
Пример #10
0
        public static void DoMain(string[] args)
        {
            SystemInformation.InternalCallInitializer.Init();
            SystemInformation.SetProcessName("beagled");

            // Process the command-line arguments
            bool arg_debug        = false;
            bool arg_debug_memory = false;
            bool arg_fg           = false;

            int i = 0;

            while (i < args.Length)
            {
                string arg = args [i];
                ++i;
                string next_arg = i < args.Length ? args [i] : null;

                switch (arg)
                {
                case "-h":
                case "--help":
                    PrintUsage();
                    Environment.Exit(0);
                    break;

                case "--mdb":
                case "--mono-debug":
                    // Silently ignore these arguments: they get handled
                    // in the wrapper script.
                    break;

                case "--list-backends":
                    Console.WriteLine("Current available backends:");
                    Console.Write(QueryDriver.ListBackends());
                    Environment.Exit(0);
                    break;

                case "--fg":
                case "--foreground":
                    arg_fg = true;
                    break;

                case "--bg":
                case "--background":
                    arg_fg = false;
                    break;

                case "--replace":
                    arg_replace = true;
                    break;

                case "--debug":
                    arg_debug = true;
                    break;

                case "--heap-shot":
                    arg_heap_shot    = true;
                    arg_debug        = true;
                    arg_debug_memory = true;
                    break;

                case "--no-snapshots":
                case "--no-snapshot":
                    arg_heap_shot_snapshots = false;
                    break;

                case "--heap-buddy":
                case "--debug-memory":
                    arg_debug        = true;
                    arg_debug_memory = true;
                    break;

                case "--indexing-test-mode":
                    arg_indexing_test_mode = true;
                    arg_fg = true;
                    break;

                case "--backend":
                    if (next_arg == null)
                    {
                        Console.WriteLine("--backend requires a backend name");
                        Environment.Exit(1);
                        break;
                    }

                    if (next_arg.StartsWith("--"))
                    {
                        Console.WriteLine("--backend requires a backend name. Invalid name '{0}'", next_arg);
                        Environment.Exit(1);
                        break;
                    }

                    if (next_arg [0] != '+' && next_arg [0] != '-')
                    {
                        QueryDriver.OnlyAllow(next_arg);
                    }
                    else
                    {
                        if (next_arg [0] == '+')
                        {
                            QueryDriver.Allow(next_arg.Substring(1));
                        }
                        else
                        {
                            QueryDriver.Deny(next_arg.Substring(1));
                        }
                    }

                    ++i;                     // we used next_arg
                    break;

                case "--add-static-backend":
                    if (next_arg != null)
                    {
                        QueryDriver.AddStaticQueryable(next_arg);
                    }
                    ++i;
                    break;

                case "--disable-scheduler":
                    arg_disable_scheduler = true;
                    break;

                case "--indexing-delay":
                    if (next_arg != null)
                    {
                        try {
                            QueryDriver.IndexingDelay = Int32.Parse(next_arg);
                        } catch {
                            Console.WriteLine("'{0}' is not a valid number of seconds", next_arg);
                            Environment.Exit(1);
                        }
                    }

                    ++i;
                    break;

                case "--autostarted":
                    // FIXME: This option is deprecated and will be removed in a future release.
                    break;

                case "--disable-text-cache":
                    disable_textcache = true;
                    break;

                case "--version":
                    VersionFu.PrintVersion();
                    Environment.Exit(0);
                    break;

                default:
                    Console.WriteLine("Unknown argument '{0}'", arg);
                    Environment.Exit(1);
                    break;
                }
            }

            if (Environment.GetEnvironmentVariable("SABAYON_SESSION_RUNNING") == "yes")
            {
                Console.WriteLine("Beagle is running underneath Sabayon, exiting.");
                Environment.Exit(0);
            }

            if (arg_indexing_test_mode)
            {
                LuceneQueryable.OptimizeRightAway = true;
            }

            // Bail out if we are trying to run as root
            if (Environment.UserName == "root" && Environment.GetEnvironmentVariable("SUDO_USER") != null)
            {
                Console.WriteLine("You appear to be running beagle using sudo.  This can cause problems with");
                Console.WriteLine("permissions in your .beagle and .wapi directories if you later try to run");
                Console.WriteLine("as an unprivileged user.  If you need to run beagle as root, please use");
                Console.WriteLine("'su -c' instead.");
                Environment.Exit(-1);
            }

            if (Environment.UserName == "root" && !Conf.Daemon.GetOption(Conf.Names.AllowRoot, false))
            {
                Console.WriteLine("You can not run beagle as root.  Beagle is designed to run from your own");
                Console.WriteLine("user account.  If you want to create multiuser or system-wide indexes, use");
                Console.WriteLine("the beagle-build-index tool.");
                Console.WriteLine();
                Console.WriteLine("You can override this setting using the beagle-config or beagle-settings tools.");
                Environment.Exit(-1);
            }

            try {
                string tmp = PathFinder.HomeDir;
            } catch (Exception e) {
                Console.WriteLine("Unable to start the daemon: {0}", e.Message);
                Environment.Exit(-1);
            }

            MainLoopThread = Thread.CurrentThread;

            Log.Initialize(PathFinder.LogDir, "Beagle", arg_debug ? LogLevel.Debug : LogLevel.Warn, arg_fg);
            Log.Always("Starting Beagle Daemon (version {0})", ExternalStringsHack.Version);
            Log.Always("Running on {0}", SystemInformation.MonoRuntimeVersion);
            Log.Always("Command Line: {0}",
                       Environment.CommandLine != null ? Environment.CommandLine : "(null)");

            if (!ExtendedAttribute.Supported)
            {
                Logger.Log.Warn("Extended attributes are not supported on this filesystem. " +
                                "Performance will suffer as a result.");
            }

            if (disable_textcache)
            {
                Log.Warn("Running with text-cache disabled!");
                Log.Warn("*** Snippets will not be returned for documents indexed in this session.");
            }

            // Check if global configuration files are installed
            if (!Conf.CheckGlobalConfig())
            {
                Console.WriteLine("Global configuration files not found in '{0}'", PathFinder.ConfigDataDir);
                Environment.Exit(-1);
            }

            // Start our memory-logging thread
            if (arg_debug_memory)
            {
                ExceptionHandlingThread.Start(new ThreadStart(LogMemoryUsage));
            }

            // Do BEAGLE_EXERCISE_THE_DOG_HARDER-related processing.
            ExerciseTheDogHarder();

            // Initialize GObject type system
            g_type_init();

            if (SystemInformation.XssInit())
            {
                Logger.Log.Debug("Established a connection to the X server");
            }
            else
            {
                Logger.Log.Debug("Unable to establish a connection to the X server");
            }
            XSetIOErrorHandler(BeagleXIOErrorHandler);

            // Lower our CPU priority
            SystemPriorities.Renice(7);

            QueryDriver.Init();
            Server.Init();

#if MONO_1_9
            Shutdown.SetupSignalHandlers(new Shutdown.SignalHandler(HandleSignal));
#else
            SetupSignalHandlers();
#endif

            Shutdown.ShutdownEvent += OnShutdown;

            main_loop = new MainLoop();
            Shutdown.RegisterMainLoop(main_loop);

            // Defer all actual startup until the main loop is
            // running.  That way shutdowns during the startup
            // process work correctly.
            GLib.Idle.Add(new GLib.IdleHandler(StartupProcess));

            // Start our event loop.
            main_loop.Run();

            // We're out of the main loop now, join all the
            // running threads so we can exit cleanly.
            ExceptionHandlingThread.JoinAllThreads();

            // If we placed our sockets in a temp directory, try to clean it up
            // Note: this may fail because the helper is still running
            if (PathFinder.GetRemoteStorageDir(false) != PathFinder.StorageDir)
            {
                try {
                    Directory.Delete(PathFinder.GetRemoteStorageDir(false));
                } catch (IOException) { }
            }

            Log.Always("Beagle daemon process shut down cleanly.");
        }
Пример #11
0
 private static void OnEmptySchedulerQueue()
 {
     Logger.Log.Debug("Scheduler queue is empty: terminating immediately");
     Shutdown.BeginShutdown();
     Environment.Exit(0);              // Ugly work-around: We need to call Exit here to avoid deadlocking.
 }
Пример #12
0
        private void HttpRun()
        {
            http_listener = new HttpListener();

            string prefix  = null;
            int    port    = 4000;
            bool   success = false;
            string host    = "localhost";

            if (enable_network_svc)
            {
                host = "*";
            }

            do
            {
                prefix  = String.Format("http://{0}:{1}/", host, port);
                success = true;

                try {
                    http_listener.Prefixes.Add(prefix);
                    http_listener.Start();
                } catch (SocketException) {
                    http_listener.Prefixes.Remove(prefix);
                    success = false;
                    port++;
                }
            } while (!success);

            Shutdown.WorkerStart(this.http_listener, String.Format("HTTP Server '{0}'", prefix));
            Log.Always("HTTP Server: Listening on {0}", prefix);

            while (this.running)
            {
                HttpListenerContext context = null;

                try {
                    context = http_listener.GetContext();
                } catch (Exception e) {
                    // Log a warning if not due to shutdown
                    if (!this.running ||
                        (!this.enable_network_svc && !this.webinterface))
                    {
                        break;
                    }
                    Logger.Log.Warn(e, "HTTP Server: Exception while getting context:");
                }

                if (context == null)
                {
                    continue;
                }

                if (context.Request.HttpMethod == "GET")
                {
                    try {
                        WebServer.HandleStaticPages(context);
                    } catch (IOException ex1) {
                        // Socket was shut down
                        Log.Debug("Exception while serving static page: " + ex1.Message);
                        // FIXME: Should anything be done here to free "context" ? This context seems to remain in http_listener's ctxt table
                    } catch (SocketException ex2) {
                        // Socket is not connected anymore
                        Log.Debug("Exception while serving static page: " + ex2.Message);
                    }
                    continue;
                }

                if (context.Request.HttpMethod != "POST")
                {
                    // FIXME: Send better HTTP error ?
                    context.Response.StatusCode = 404;
                    context.Response.Close();
                    continue;
                }

                if (context.Request.RawUrl == "/")
                {
                    // We have received a new query request
                    Guid            guid         = Guid.NewGuid();
                    HttpItemHandler item_handler = new HttpItemHandler();
                    item_handlers [guid] = item_handler;

                    ConnectionHandler handler = new HttpConnectionHandler(guid, context, item_handler);

                    lock (live_handlers)
                        live_handlers [handler] = handler;

                    ExceptionHandlingThread.Start(new ThreadStart(handler.HandleConnection));
                }
                else
                {
                    // We have received a hit request
                    Uri    uri  = context.Request.Url;
                    string path = null;

                    // Second Uri segment contains the Guid
                    string g = uri.Segments [1];

                    if (g [g.Length - 1] == '/')
                    {
                        g = g.Remove(g.Length - 1, 1);
                    }

                    Guid guid = Guid.Empty;

                    try {
                        guid = new Guid(g);
                    } catch (FormatException) {
                        // FIXME: return HTTP error
                        Logger.Log.Debug("HTTP Server: Invalid query guid '{0}'", g);
                        context.Response.Close();
                        continue;
                    }

                    if (uri.Query.Length > 0)
                    {
                        path = uri.Query.Remove(0, 1);
                    }
                    else
                    {
                        // FIXME: return HTTP error
                        Logger.Log.Debug("HTTP Server: Empty query string in item request");
                        context.Response.Close();
                        continue;
                    }

                    System.Uri      item_uri = new Uri(path);
                    HttpItemHandler handler  = (HttpItemHandler)item_handlers [guid];

                    if (handler == null)
                    {
                        // FIXME: return HTTP error
                        Logger.Log.Debug("HTTP Server: Query ({0}) does not exist", g);
                        context.Response.Close();
                    }
                    else
                    {
                        Logger.Log.Debug("HTTP Server: Asked for item '{0}' on query '{1}'", path, g);
                        handler.HandleRequest(context, item_uri);
                    }
                }
            }


            Shutdown.WorkerFinished(http_listener);
            Logger.Log.Info("HTTP Server: '{0}' shut down...", prefix);
            http_listener = null;
        }
Пример #13
0
        public override void HandleConnection()
        {
            this.thread = Thread.CurrentThread;

            bool force_close_connection = false;

            // Read the data off the socket and store it in a
            // temporary memory buffer.  Once the end-of-message
            // character has been read, discard remaining data
            // and deserialize the request.
            byte[]       network_data = new byte [4096];
            MemoryStream buffer_stream = new MemoryStream();
            int          bytes_read, total_bytes = 0, end_index = -1;

            // We use the network_data array as an object to represent this worker.
            Shutdown.WorkerStart(network_data, String.Format("HandleConnection ({0})", ++connection_count));

            do
            {
                bytes_read = 0;

                try {
                    lock (this.blocking_read_lock)
                        this.in_blocking_read = true;

                    lock (this.client_lock) {
                        // The connection may have been closed within this loop.
                        if (this.client != null)
                        {
                            bytes_read = this.client.GetStream().Read(network_data, 0, 4096);
                        }
                    }

                    lock (this.blocking_read_lock)
                        this.in_blocking_read = false;
                } catch (Exception e) {
                    // Aborting the thread mid-read will
                    // cause an IOException to be thorwn,
                    // which sets the ThreadAbortException
                    // as its InnerException.MemoryStream
                    if (!(e is IOException || e is ThreadAbortException))
                    {
                        throw;
                    }

                    // Reset the unsightly ThreadAbortException
                    Thread.ResetAbort();

                    Logger.Log.Debug("Bailing out of HandleConnection -- shutdown requested");
                    this.thread = null;
                    Server.MarkHandlerAsKilled(this);
                    Shutdown.WorkerFinished(network_data);
                    return;
                }

                total_bytes += bytes_read;

                if (bytes_read > 0)
                {
                    // 0xff signifies end of message
                    end_index = Array.IndexOf <byte> (network_data, (byte)0xff);

                    buffer_stream.Write(network_data, 0,
                                        end_index == -1 ? bytes_read : end_index);
                }
            } while (bytes_read > 0 && end_index == -1);

            // Something just connected to our socket and then
            // hung up.  The IndexHelper (among other things) does
            // this to check that a server is still running.  It's
            // no big deal, so just clean up and close without
            // running any handlers.
            if (total_bytes == 0)
            {
                force_close_connection = true;
                goto cleanup;
            }

            buffer_stream.Seek(0, SeekOrigin.Begin);
            HandleConnection(buffer_stream);

cleanup:
            buffer_stream.Close();

            if (force_close_connection)
            {
                Close();
            }
            else
            {
                SetupWatch();
            }

            Server.MarkHandlerAsKilled(this);
            Shutdown.WorkerFinished(network_data);
        }
Пример #14
0
        public override void HandleConnection()
        {
            //Logger.Log.Debug ("HTTP Server: Serving request for {0}", context.Request.Url);

            // Query request: read content and forward to base.HandleConnection for processing
            context.Response.KeepAlive   = true;
            context.Response.ContentType = "text/txt; charset=utf-8";
            context.Response.SendChunked = true;

            Shutdown.WorkerStart(this.context.Request.InputStream, String.Format("HandleConnection ({0})", ++connection_count));

            // Read the data off the socket and store it in a
            // temporary memory buffer.  Once the end-of-message
            // character has been read, discard remaining data
            // and deserialize the request.
            byte[]       network_data = new byte [4096];
            MemoryStream buffer_stream = new MemoryStream();
            int          bytes_read, total_bytes = 0, end_index = -1;

            do
            {
                bytes_read = 0;

                try {
                    lock (this.blocking_read_lock)
                        this.in_blocking_read = true;

                    lock (this.client_lock) {
                        // The connection may have been closed within this loop.
                        if (this.context != null)
                        {
                            bytes_read = this.context.Request.InputStream.Read(network_data, 0, 4096);
                        }
                    }

                    lock (this.blocking_read_lock)
                        this.in_blocking_read = false;
                } catch (Exception e) {
                    // Aborting the thread mid-read will
                    // cause an IOException to be thorwn,
                    // which sets the ThreadAbortException
                    // as its InnerException.MemoryStream
                    if (!(e is IOException || e is ThreadAbortException))
                    {
                        throw;
                    }

                    // Reset the unsightly ThreadAbortException
                    Thread.ResetAbort();

                    Logger.Log.Debug("Bailing out of HandleConnection -- shutdown requested");
                    this.thread = null;
                    Server.MarkHandlerAsKilled(this);
                    Shutdown.WorkerFinished(context.Request.InputStream);
                    return;
                }

                total_bytes += bytes_read;

                if (bytes_read > 0)
                {
                    // 0xff signifies end of message
                    end_index = Array.IndexOf <byte> (network_data, (byte)0xff);

                    buffer_stream.Write(network_data, 0,
                                        end_index == -1 ? bytes_read : end_index);
                }
            } while (bytes_read > 0 && end_index == -1);

            //Logger.Log.Debug ("HTTP Server: Handling received request message");

            // The 0xff bytes from a remote beagled comes in a separate http request
            // and causes havoc by creating empty messages. HTTP streams do not behave
            // like a continous stream like UnixStream
            if (total_bytes > 0)
            {
                buffer_stream.Seek(0, SeekOrigin.Begin);
                base.HandleConnection(buffer_stream);
            }

            Server.MarkHandlerAsKilled(this);
            Shutdown.WorkerFinished(context.Request.InputStream);
        }