3 using System
.Collections
;
6 using Mono
.Unix
.Native
;
13 public class DirectoryObject
: FileSystemObject
{
15 private bool is_root
= false;
16 private string root_path
= null;
18 int n_files_below
= 0;
21 public DirectoryObject ()
23 timestamp
= FileSystemObject
.PickTimestamp ();
27 public DirectoryObject (string root_path
)
32 this.root_path
= Path
.GetFullPath (root_path
);
38 override public bool IsRoot
{
39 get { return is_root; }
42 override public string Name
{
50 override protected string GetChildUri (FileSystemObject child
)
52 return Path
.Combine (this.Uri
, child
.Name
);
55 override public string Uri
{
58 return "file://" + root_path
;
63 override public string Extension
{
64 get { return is_root ? null : ".dir"; }
67 override public string MimeType
{
68 get { return "inode/directory"; }
71 ///////////////////////////////////////////////////////////////////////
73 static private void GetCountDeltas (FileSystemObject fso
, out int d_files
, out int d_dirs
)
75 if (fso
is DirectoryObject
) {
76 DirectoryObject dir
= (DirectoryObject
) fso
;
77 d_files
= dir
.n_files_below
;
78 d_dirs
= dir
.n_dirs_below
+ 1; // add one for ourself
79 } else if (fso
is FileObject
) {
80 d_files
= 1; // just ourself
83 throw new Exception ("Unknown type " + fso
);
87 public override void AddChild (FileSystemObject child
, EventTracker tracker
)
89 // Every time we add a child, we walk up the tree
90 // and adjust the n_*_below counts for every node
94 GetCountDeltas (child
, out d_files
, out d_dirs
);
98 while (curr
!= null) {
99 curr
.n_files_below
+= d_files
;
100 curr
.n_dirs_below
+= d_dirs
;
101 curr
= (DirectoryObject
) curr
.Parent
;
104 base.AddChild (child
, tracker
);
107 public override void RemoveChild (FileSystemObject child
, EventTracker tracker
)
109 // Likewise, we have to walk up the tree and adjust
110 // the n_*_below counts when we remove a child.
113 GetCountDeltas (child
, out d_files
, out d_dirs
);
115 DirectoryObject curr
;
117 while (curr
!= null) {
118 curr
.n_files_below
-= d_files
;
119 curr
.n_dirs_below
-= d_dirs
;
120 curr
= (DirectoryObject
) curr
.Parent
;
123 base.RemoveChild (child
, tracker
);
126 public override void MoveChild (FileSystemObject child
, FileSystemObject new_parent
, EventTracker tracker
)
129 GetCountDeltas (child
, out d_files
, out d_dirs
);
131 DirectoryObject curr
;
133 while (curr
!= null) {
134 curr
.n_files_below
-= d_files
;
135 curr
.n_dirs_below
-= d_dirs
;
136 curr
= (DirectoryObject
) curr
.Parent
;
138 curr
= (DirectoryObject
) new_parent
;
139 while (curr
!= null) {
140 curr
.n_files_below
+= d_files
;
141 curr
.n_dirs_below
+= d_dirs
;
142 curr
= (DirectoryObject
) curr
.Parent
;
145 base.MoveChild (child
, new_parent
, tracker
);
148 ///////////////////////////////////////////////////////////////////////
150 override public void AddOnDisk (EventTracker tracker
)
153 full_name
= FullName
;
154 if (full_name
== null)
155 throw new Exception ("Attempt to instantiate something other than a real file: " + Uri
);
158 // Root directories must already exist.
159 if (! Directory
.Exists (full_name
))
160 throw new Exception ("Missing root directory " + full_name
);
162 Directory
.CreateDirectory (full_name
);
163 timestamp
= Directory
.GetLastWriteTimeUtc (full_name
);
167 tracker
.ExpectingAdded (this.Uri
);
169 // Recursively add the children
170 foreach (FileSystemObject fso
in children
.Values
)
171 fso
.AddOnDisk (tracker
);
174 override public void DeleteOnDisk (EventTracker tracker
)
176 // Recursively delete the children
177 foreach (FileSystemObject fso
in children
.Values
)
178 fso
.DeleteOnDisk (tracker
);
180 // Then delete ourselves
181 Syscall
.rmdir (FullName
);
184 override public void MoveOnDisk (string old_full_name
, EventTracker tracker
)
186 Syscall
.rename (old_full_name
, FullName
);
189 override public bool VerifyOnDisk ()
191 // Make sure the directory exists.
192 if (! Directory
.Exists (FullName
)) {
193 Log
.Failure ("Missing directory '{0}'", FullName
);
197 // Make sure all of the children exist.
198 Hashtable name_hash
= new Hashtable ();
199 foreach (FileSystemObject fso
in children
.Values
) {
200 name_hash
[fso
.FullName
] = fso
;
201 if (! fso
.VerifyOnDisk ())
205 // Make sure there is nothing in the directory that shouldn't be there.
206 foreach (string name
in Directory
.GetFileSystemEntries (FullName
)) {
207 name_hash
.Remove (name
);
209 if (name_hash
.Count
> 0) {
210 Log
.Failure ("Extra items in directory '{0}'", FullName
);
211 foreach (string name
in name_hash
.Keys
)
212 Log
.Failure (" extra item: '{0}'", name
);
219 ///////////////////////////////////////////////////////////////////////
221 // All of the query parts than can possibly match a directory are handled
222 // in FileSystemObject.MatchesQuery.
223 override protected bool MatchesQueryPart (QueryPart abstract_part
)
228 ///////////////////////////////////////////////////////////////////////
230 static Random random
= new Random ();
232 public FileObject
PickChildFile ()
234 if (n_files_below
== 0)
238 i
= random
.Next (n_files_below
);
240 foreach (FileSystemObject fso
in Children
) {
241 if (fso
is FileObject
) {
243 return (FileObject
) fso
;
245 } else if (fso
is DirectoryObject
) {
247 nfb
= ((DirectoryObject
) fso
).n_files_below
;
249 return ((DirectoryObject
) fso
).PickChildFile ();
254 throw new Exception ("This shouldn't happen!");
257 public DirectoryObject
PickChildDirectory ()
259 if (n_dirs_below
== 0)
263 i
= random
.Next (n_dirs_below
);
265 foreach (FileSystemObject fso
in Children
) {
267 DirectoryObject dir
= fso
as DirectoryObject
;
275 if (i
< dir
.n_dirs_below
)
276 return dir
.PickChildDirectory ();
277 i
-= dir
.n_dirs_below
;
280 throw new Exception ("This also shouldn't happen!");
283 // Returns a directory, either a child directory or itself.
284 public DirectoryObject
PickDirectory ()
287 i
= random
.Next (n_dirs_below
+ 1);
290 return PickChildDirectory ();