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 ("Caught exception while synchronizing");
109 Logger
.Log
.Error (ex
);
112 task
.Reschedule
= true;
113 task
.TriggerTime
= DateTime
.Now
.AddMinutes (sync_interval_in_minutes
);
116 static private void ShutdownHook (Scheduler
.Task task
)
119 Synchronize (SynchronizationTarget
.Remote
);
121 // FIXME: This may not be safe to do here
122 Logger
.Log
.Debug ("Purging locally synchronized indexes");
123 Directory
.Delete (PathFinder
.IndexDir
, true);
124 } catch (Exception ex
) {
125 Logger
.Log
.Error ("Caught exception while doing shutdown synchronization");
126 Logger
.Log
.Error (ex
);
130 ////////////////////////////////////////////////////////////////
132 // FIXME: Non-Getto synchronization
133 static private bool SynchronizeDirectory (DirectoryInfo source_directory
,
134 DirectoryInfo target_directory
)
136 if (! source_directory
.Exists
)
137 throw new Exception ("Synchronization error: Source directory does not exist");
139 DirectoryInfo target_directory_temp
, target_directory_trash
;
141 // Setup directories for the copy/move/move/delete procedure
142 target_directory_temp
= new DirectoryInfo (target_directory
.FullName
+ ".tmp");
143 target_directory_trash
= new DirectoryInfo (target_directory
.FullName
+ ".trash");
145 if (target_directory_temp
.Exists
)
146 target_directory_temp
.Delete (true);
147 target_directory_temp
.Create ();
150 // Copy the directory structure and files
151 CopyDirectoryRecursively (source_directory
, target_directory_temp
);
153 if (target_directory_trash
.Exists
)
154 target_directory_trash
.Delete (true);
156 target_directory
.MoveTo (target_directory_trash
.FullName
);
157 target_directory_temp
.MoveTo (target_directory
.FullName
);
159 target_directory_trash
.Delete (true);
160 } catch (Exception ex
) {
161 Logger
.Log
.Error ("Caught error while synchronizing directory");
162 Logger
.Log
.Error (ex
);
169 static private void CopyDirectoryRecursively (DirectoryInfo source_directory
,
170 DirectoryInfo target_directory
)
172 if (!target_directory
.Exists
)
173 target_directory
.Create ();
175 foreach (FileInfo source_file
in DirectoryWalker
.GetFileInfos (source_directory
)) {
176 FileInfo target_file
= new FileInfo (Path
.Combine (target_directory
.FullName
, source_file
.Name
));
178 // FIXME: Don't hard code filenames - Mono.Posix.StatMode.Regular
179 if (source_file
.Name
.IndexOf ("socket") != -1 ||
180 source_file
.Name
.EndsWith ("-journal"))
183 File
.Copy (source_file
.FullName
, target_file
.FullName
, true);
186 foreach (DirectoryInfo source_child_directory
in DirectoryWalker
.GetDirectoryInfos (source_directory
)) {
187 DirectoryInfo target_child_directory
= new DirectoryInfo (Path
.Combine (target_directory
.FullName
, source_child_directory
.Name
));
189 CopyDirectoryRecursively (source_child_directory
,
190 target_child_directory
);