2 // IndexSynchronization.cs
4 // Copyright (C) 2005 Novell, Inc.
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.
29 using System
.Collections
;
30 using System
.Threading
;
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 ////////////////////////////////////////////////////////////////
49 public enum SynchronizationTarget
{
54 static public void Initialize ()
56 Logger
.Log
.Debug ("Initializing index synchronization");
58 if (! Directory
.Exists (remote_index_dir
))
59 Directory
.CreateDirectory (remote_index_dir
);
61 // Initial index synchronization
62 Synchronize (SynchronizationTarget
.Local
);
66 // Add the synchronization task to the scheduler
67 task
= Scheduler
.TaskFromHook (new Scheduler
.TaskHook (SynchronizeHook
));
68 task
.Tag
= "Synchronize Indexes";
69 task
.Priority
= Scheduler
.Priority
.Delayed
;
70 task
.TriggerTime
= DateTime
.Now
.AddMinutes (sync_interval_in_minutes
);
71 task
.Source
= synchronization_lock
;
72 Scheduler
.Global
.Add (task
);
74 // Set up the shutdown synchronization task
75 task
= Scheduler
.TaskFromHook (new Scheduler
.TaskHook (ShutdownHook
));
76 task
.Tag
= "Synchronize Indexes on Shutdown";
77 task
.Priority
= Scheduler
.Priority
.Shutdown
;
78 task
.Source
= synchronization_lock
;
79 Scheduler
.Global
.Add (task
);
82 ////////////////////////////////////////////////////////////////
84 static public void Synchronize (SynchronizationTarget target
)
86 Stopwatch watch
= new Stopwatch ();
89 lock (synchronization_lock
) {
90 Logger
.Log
.Debug ("Synchronizing... (target={0})", target
);
92 DirectoryInfo source_directory
, target_directory
;
93 source_directory
= new DirectoryInfo ((target
== SynchronizationTarget
.Local
) ? remote_index_dir
: PathFinder
.IndexDir
);
94 target_directory
= new DirectoryInfo ((target
== SynchronizationTarget
.Local
) ? PathFinder
.IndexDir
: remote_index_dir
);
96 if (SynchronizeDirectory (source_directory
, target_directory
))
97 Logger
.Log
.Debug ("Synchronized successfully in {0}", watch
);
101 ////////////////////////////////////////////////////////////////
103 static private void SynchronizeHook (Scheduler
.Task task
)
106 Synchronize (SynchronizationTarget
.Remote
);
107 } catch (Exception ex
) {
108 Logger
.Log
.Error (ex
, "Caught exception while synchronizing");
111 task
.Reschedule
= true;
112 task
.TriggerTime
= DateTime
.Now
.AddMinutes (sync_interval_in_minutes
);
115 static private void ShutdownHook (Scheduler
.Task task
)
118 Synchronize (SynchronizationTarget
.Remote
);
120 // FIXME: This may not be safe to do here
121 Logger
.Log
.Debug ("Purging locally synchronized indexes");
122 Directory
.Delete (PathFinder
.IndexDir
, true);
123 } catch (Exception ex
) {
124 Logger
.Log
.Error (ex
, "Caught exception while doing shutdown synchronization");
128 ////////////////////////////////////////////////////////////////
130 // FIXME: Non-Getto synchronization
131 static private bool SynchronizeDirectory (DirectoryInfo source_directory
,
132 DirectoryInfo target_directory
)
134 if (! source_directory
.Exists
)
135 throw new Exception ("Synchronization error: Source directory does not exist");
137 DirectoryInfo target_directory_temp
, target_directory_trash
;
139 // Setup directories for the copy/move/move/delete procedure
140 target_directory_temp
= new DirectoryInfo (target_directory
.FullName
+ ".tmp");
141 target_directory_trash
= new DirectoryInfo (target_directory
.FullName
+ ".trash");
143 if (target_directory_temp
.Exists
)
144 target_directory_temp
.Delete (true);
145 target_directory_temp
.Create ();
148 // Copy the directory structure and files
149 CopyDirectoryRecursively (source_directory
, target_directory_temp
);
151 if (target_directory_trash
.Exists
)
152 target_directory_trash
.Delete (true);
154 target_directory
.MoveTo (target_directory_trash
.FullName
);
155 target_directory_temp
.MoveTo (target_directory
.FullName
);
157 target_directory_trash
.Delete (true);
158 } catch (Exception ex
) {
159 Logger
.Log
.Error (ex
, "Caught error while synchronizing directory");
166 static private void CopyDirectoryRecursively (DirectoryInfo source_directory
,
167 DirectoryInfo target_directory
)
169 if (!target_directory
.Exists
)
170 target_directory
.Create ();
172 foreach (FileInfo source_file
in DirectoryWalker
.GetFileInfos (source_directory
)) {
173 FileInfo target_file
= new FileInfo (Path
.Combine (target_directory
.FullName
, source_file
.Name
));
175 // FIXME: Don't hard code filenames - Mono.Posix.StatMode.Regular
176 if (source_file
.Name
.IndexOf ("socket") != -1 ||
177 source_file
.Name
.EndsWith ("-journal"))
180 File
.Copy (source_file
.FullName
, target_file
.FullName
, true);
183 foreach (DirectoryInfo source_child_directory
in DirectoryWalker
.GetDirectoryInfos (source_directory
)) {
184 DirectoryInfo target_child_directory
= new DirectoryInfo (Path
.Combine (target_directory
.FullName
, source_child_directory
.Name
));
186 CopyDirectoryRecursively (source_child_directory
,
187 target_child_directory
);