Lucene.Net  3.0.3
Lucene.Net is a .NET port of the Java Lucene Indexing Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties
FSDirectory.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using System.Collections.Generic;
20 
21 // Used only for WRITE_LOCK_NAME in deprecated create=true case:
22 using System.IO;
23 using Lucene.Net.Support;
24 using IndexFileNameFilter = Lucene.Net.Index.IndexFileNameFilter;
25 using IndexWriter = Lucene.Net.Index.IndexWriter;
26 using Constants = Lucene.Net.Util.Constants;
27 
28 namespace Lucene.Net.Store
29 {
30 
104  public abstract class FSDirectory : Directory
105  {
106  private static System.Security.Cryptography.HashAlgorithm DIGESTER;
107 
108  static FSDirectory()
109  {
110  try
111  {
112  DIGESTER = Cryptography.HashAlgorithm;
113  }
114  catch (System.Exception e)
115  {
116  throw new System.SystemException(e.ToString(), e);
117  }
118  }
119 
120  private bool checked_Renamed;
121 
122  internal void CreateDir()
123  {
124  if (!checked_Renamed)
125  {
126  if (!this.internalDirectory.Exists)
127  {
128  try
129  {
130  this.internalDirectory.Create();
131  }
132  catch (Exception)
133  {
134  throw new System.IO.IOException("Cannot create directory: " + internalDirectory);
135  }
136  this.internalDirectory.Refresh(); // need to see the creation
137  }
138 
139  checked_Renamed = true;
140  }
141  }
142 
146  protected internal void InitOutput(System.String name)
147  {
148  EnsureOpen();
149  CreateDir();
150  System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(internalDirectory.FullName, name));
151  if (file.Exists) // delete existing, if any
152  {
153  try
154  {
155  file.Delete();
156  }
157  catch (Exception)
158  {
159  throw new System.IO.IOException("Cannot overwrite: " + file);
160  }
161  }
162  }
163 
165  protected internal System.IO.DirectoryInfo internalDirectory = null;
166 
174  protected internal FSDirectory(System.IO.DirectoryInfo path, LockFactory lockFactory)
175  {
176  // new ctors use always NativeFSLockFactory as default:
177  if (lockFactory == null)
178  {
179  lockFactory = new NativeFSLockFactory();
180  }
181  // Set up lockFactory with cascaded defaults: if an instance was passed in,
182  // use that; else if locks are disabled, use NoLockFactory; else if the
183  // system property Lucene.Net.Store.FSDirectoryLockFactoryClass is set,
184  // instantiate that; else, use SimpleFSLockFactory:
185 
186  internalDirectory = path;
187 
188  // due to differences in how Java & .NET refer to files, the checks are a bit different
189  if (!internalDirectory.Exists && System.IO.File.Exists(internalDirectory.FullName))
190  {
191  throw new NoSuchDirectoryException("file '" + internalDirectory.FullName + "' exists but is not a directory");
192  }
193  SetLockFactory(lockFactory);
194 
195  // for filesystem based LockFactory, delete the lockPrefix, if the locks are placed
196  // in index dir. If no index dir is given, set ourselves
197  if (lockFactory is FSLockFactory)
198  {
199  FSLockFactory lf = (FSLockFactory)lockFactory;
200  System.IO.DirectoryInfo dir = lf.LockDir;
201  // if the lock factory has no lockDir set, use the this directory as lockDir
202  if (dir == null)
203  {
204  lf.LockDir = this.internalDirectory;
205  lf.LockPrefix = null;
206  }
207  else if (dir.FullName.Equals(this.internalDirectory.FullName))
208  {
209  lf.LockPrefix = null;
210  }
211  }
212  }
213 
234  public static FSDirectory Open(string path)
235  {
236  return Open(new DirectoryInfo(path), null);
237  }
238 
259  public static FSDirectory Open(System.IO.DirectoryInfo path)
260  {
261  return Open(path, null);
262  }
263 
267  public static FSDirectory Open(System.IO.DirectoryInfo path, LockFactory lockFactory)
268  {
269  /* For testing:
270  MMapDirectory dir=new MMapDirectory(path, lockFactory);
271  dir.setUseUnmap(true);
272  return dir;
273  */
274 
275  if (Constants.WINDOWS)
276  {
277  return new SimpleFSDirectory(path, lockFactory);
278  }
279  else
280  {
281  //NIOFSDirectory is not implemented in Lucene.Net
282  //return new NIOFSDirectory(path, lockFactory);
283  return new SimpleFSDirectory(path, lockFactory);
284  }
285  }
286 
297  public static System.String[] ListAll(System.IO.DirectoryInfo dir)
298  {
299  if (!dir.Exists)
300  {
301  throw new NoSuchDirectoryException("directory '" + dir.FullName + "' does not exist");
302  }
303  else if (System.IO.File.Exists(dir.FullName))
304  {
305  throw new NoSuchDirectoryException("File '" + dir.FullName + "' does not exist");
306  }
307 
308  // Exclude subdirs, only the file names, not the paths
309  System.IO.FileInfo[] files = dir.GetFiles();
310  System.String[] result = new System.String[files.Length];
311  for (int i = 0; i < files.Length; i++)
312  {
313  result[i] = files[i].Name;
314  }
315 
316  // no reason to return null, if the directory cannot be listed, an exception
317  // will be thrown on the above call to dir.GetFiles()
318  // use of LINQ to create the return value array may be a bit more efficient
319 
320  return result;
321  }
322 
328  public override System.String[] ListAll()
329  {
330  EnsureOpen();
331  return ListAll(internalDirectory);
332  }
333 
335  public override bool FileExists(System.String name)
336  {
337  EnsureOpen();
338  System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(internalDirectory.FullName, name));
339  return file.Exists;
340  }
341 
343  public override long FileModified(System.String name)
344  {
345  EnsureOpen();
346  System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(internalDirectory.FullName, name));
347  return (long)file.LastWriteTime.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds; //{{LUCENENET-353}}
348  }
349 
351  public static long FileModified(System.IO.FileInfo directory, System.String name)
352  {
353  System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name));
354  return (long)file.LastWriteTime.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalMilliseconds; //{{LUCENENET-353}}
355  }
356 
358  public override void TouchFile(System.String name)
359  {
360  EnsureOpen();
361  System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(internalDirectory.FullName, name));
362  file.LastWriteTime = System.DateTime.Now;
363  }
364 
366  public override long FileLength(System.String name)
367  {
368  EnsureOpen();
369  System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(internalDirectory.FullName, name));
370  return file.Exists ? file.Length : 0;
371  }
372 
374  public override void DeleteFile(System.String name)
375  {
376  EnsureOpen();
377  System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(internalDirectory.FullName, name));
378  try
379  {
380  file.Delete();
381  }
382  catch (Exception)
383  {
384  throw new System.IO.IOException("Cannot delete " + file);
385  }
386  }
387 
388  public override void Sync(System.String name)
389  {
390  EnsureOpen();
391  System.IO.FileInfo fullFile = new System.IO.FileInfo(System.IO.Path.Combine(internalDirectory.FullName, name));
392  bool success = false;
393  int retryCount = 0;
394  System.IO.IOException exc = null;
395  while (!success && retryCount < 5)
396  {
397  retryCount++;
398  System.IO.FileStream file = null;
399  try
400  {
401  try
402  {
403  file = new System.IO.FileStream(fullFile.FullName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
404  FileSupport.Sync(file);
405  success = true;
406  }
407  finally
408  {
409  if (file != null)
410  file.Close();
411  }
412  }
413  catch (System.IO.IOException ioe)
414  {
415  if (exc == null)
416  exc = ioe;
417 
418  // Pause 5 msec
419  System.Threading.Thread.Sleep(5);
420 
421  }
422  }
423 
424  if (!success && exc != null)
425  // Throw original exception
426  throw exc;
427  }
428 
429  // Inherit javadoc
430  public override IndexInput OpenInput(System.String name)
431  {
432  EnsureOpen();
433  return OpenInput(name, BufferedIndexInput.BUFFER_SIZE);
434  }
435 
437  private static readonly char[] HEX_DIGITS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
438 
439 
440  public override string GetLockId()
441  {
442  EnsureOpen();
443  System.String dirName; // name to be hashed
444  try
445  {
446  dirName = internalDirectory.FullName;
447  }
448  catch (System.IO.IOException e)
449  {
450  throw new System.SystemException(e.ToString(), e);
451  }
452 
453  byte[] digest;
454  lock (DIGESTER)
455  {
456  digest = DIGESTER.ComputeHash(System.Text.Encoding.UTF8.GetBytes(dirName));
457  }
458  System.Text.StringBuilder buf = new System.Text.StringBuilder();
459  buf.Append("lucene-");
460  for (int i = 0; i < digest.Length; i++)
461  {
462  int b = digest[i];
463  buf.Append(HEX_DIGITS[(b >> 4) & 0xf]);
464  buf.Append(HEX_DIGITS[b & 0xf]);
465  }
466 
467  return buf.ToString();
468  }
469 
470  protected override void Dispose(bool disposing)
471  {
472  lock (this)
473  {
474  isOpen = false;
475  }
476  }
477 
478  // Java Lucene implements GetFile() which returns a FileInfo.
479  // For Lucene.Net, GetDirectory() is more appropriate
480 
481  public virtual DirectoryInfo Directory
482  {
483  get
484  {
485  EnsureOpen();
486  return internalDirectory;
487  }
488  }
489 
491  public override System.String ToString()
492  {
493  return this.GetType().FullName + "@" + internalDirectory + " lockFactory=" + LockFactory;
494  }
495 
502  public static readonly int DEFAULT_READ_CHUNK_SIZE = Constants.JRE_IS_64BIT ? int.MaxValue: 100 * 1024 * 1024;
503 
504  // LUCENE-1566
505  private int chunkSize = DEFAULT_READ_CHUNK_SIZE;
506 
512  public int ReadChunkSize
513  {
514  get
515  {
516  // LUCENE-1566
517  return chunkSize;
518  }
519  set
520  {
521  // LUCENE-1566
522  if (value <= 0)
523  {
524  throw new System.ArgumentException("chunkSize must be positive");
525  }
526  if (!Constants.JRE_IS_64BIT)
527  {
528  this.chunkSize = value;
529  }
530  }
531  }
532  }
533 }