Fix a fd leak in knotes backend (stupid me) and some cleanup in kaddrbook backend.
[beagle.git] / beagled / IndexSynchronization.cs
blob748ad4625be9f042f8dbc704c79ac4c5742b8fc0
1 //
2 // IndexSynchronization.cs
3 //
4 // Copyright (C) 2005-2006 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.IO;
29 using System.Collections;
30 using System.Threading;
32 using Beagle.Util;
34 namespace Beagle.Daemon {
36 public class IndexSynchronization {
38 // 1 hour synchronization period
39 static private int sync_interval_in_minutes = 60;
41 // Synchonization lock object
42 static private object synchronization_lock = new object ();
44 // Original index storage directory
45 static private string remote_index_dir = Path.Combine (PathFinder.StorageDir, "Indexes");
47 // Locally sync'd storage directory
48 static private string local_index_dir = PathFinder.IndexDir;
50 ////////////////////////////////////////////////////////////////
52 public enum SynchronizationTarget {
53 Local,
54 Remote
57 static public void Initialize ()
59 Logger.Log.Debug ("Initializing index synchronization");
61 if (! Directory.Exists (remote_index_dir))
62 Directory.CreateDirectory (remote_index_dir);
64 Log.Debug ("Remote index storage dir {0} will be synchronized to temp local storage dir {1}", remote_index_dir, local_index_dir);
66 // Initial index synchronization
67 Synchronize (SynchronizationTarget.Local);
69 Scheduler.Task task;
71 // Add the synchronization task to the scheduler
72 task = Scheduler.TaskFromHook (new Scheduler.TaskHook (SynchronizeHook));
73 task.Tag = "Synchronize Indexes";
74 task.Priority = Scheduler.Priority.Delayed;
75 task.TriggerTime = DateTime.Now.AddMinutes (sync_interval_in_minutes);
76 task.Source = synchronization_lock;
77 Scheduler.Global.Add (task);
79 // Set up the shutdown synchronization task
80 task = Scheduler.TaskFromHook (new Scheduler.TaskHook (ShutdownHook));
81 task.Tag = "Synchronize Indexes on Shutdown";
82 task.Priority = Scheduler.Priority.Shutdown;
83 task.Source = synchronization_lock;
84 Scheduler.Global.Add (task);
87 ////////////////////////////////////////////////////////////////
89 static public void Synchronize (SynchronizationTarget target)
91 Stopwatch watch = new Stopwatch ();
92 watch.Start ();
94 lock (synchronization_lock) {
95 Logger.Log.Debug ("Synchronizing... (target={0})", target);
97 DirectoryInfo source_directory, target_directory;
98 source_directory = new DirectoryInfo ((target == SynchronizationTarget.Local) ? remote_index_dir : local_index_dir);
99 target_directory = new DirectoryInfo ((target == SynchronizationTarget.Local) ? local_index_dir : remote_index_dir);
101 if (SynchronizeDirectory (source_directory, target_directory))
102 Logger.Log.Debug ("Synchronized successfully in {0}", watch);
106 ////////////////////////////////////////////////////////////////
108 static private void SynchronizeHook (Scheduler.Task task)
110 try {
111 Synchronize (SynchronizationTarget.Remote);
112 } catch (Exception ex) {
113 Logger.Log.Error (ex, "Caught exception while synchronizing");
116 task.Reschedule = true;
117 task.TriggerTime = DateTime.Now.AddMinutes (sync_interval_in_minutes);
120 static private void ShutdownHook (Scheduler.Task task)
122 try {
123 Synchronize (SynchronizationTarget.Remote);
125 // FIXME: This may not be safe to do here
126 Logger.Log.Debug ("Purging locally synchronized indexes");
127 Directory.Delete (local_index_dir, true);
128 } catch (Exception ex) {
129 Logger.Log.Error (ex, "Caught exception while doing shutdown synchronization");
133 ////////////////////////////////////////////////////////////////
135 // FIXME: Non-Getto synchronization
136 static private bool SynchronizeDirectory (DirectoryInfo source_directory,
137 DirectoryInfo target_directory)
139 if (! source_directory.Exists)
140 throw new Exception ("Synchronization error: Source directory does not exist");
142 DirectoryInfo target_directory_temp, target_directory_trash;
144 // Setup directories for the copy/move/move/delete procedure
145 target_directory_temp = new DirectoryInfo (target_directory.FullName + ".tmp");
146 target_directory_trash = new DirectoryInfo (target_directory.FullName + ".trash");
148 if (target_directory_temp.Exists)
149 target_directory_temp.Delete (true);
150 target_directory_temp.Create ();
152 try {
153 // Copy the directory structure and files
154 CopyDirectoryRecursively (source_directory, target_directory_temp);
156 if (target_directory_trash.Exists)
157 target_directory_trash.Delete (true);
159 target_directory.MoveTo (target_directory_trash.FullName);
160 target_directory_temp.MoveTo (target_directory.FullName);
162 target_directory_trash.Delete (true);
163 } catch (Exception ex) {
164 Logger.Log.Error (ex, "Caught error while synchronizing directory");
165 return false;
168 return true;
171 static private void CopyDirectoryRecursively (DirectoryInfo source_directory,
172 DirectoryInfo target_directory)
174 if (!target_directory.Exists)
175 target_directory.Create ();
177 foreach (FileInfo source_file in DirectoryWalker.GetFileInfos (source_directory)) {
178 FileInfo target_file = new FileInfo (Path.Combine (target_directory.FullName, source_file.Name));
180 // FIXME: Don't hard code filenames - Mono.Posix.StatMode.Regular
181 if (source_file.Name.IndexOf ("socket") != -1 ||
182 source_file.Name.EndsWith ("-journal"))
183 continue;
185 File.Copy (source_file.FullName, target_file.FullName, true);
188 foreach (DirectoryInfo source_child_directory in DirectoryWalker.GetDirectoryInfos (source_directory)) {
189 DirectoryInfo target_child_directory = new DirectoryInfo (Path.Combine (target_directory.FullName, source_child_directory.Name));
191 CopyDirectoryRecursively (source_child_directory,
192 target_child_directory);