blob: 49b734fd671d52d5cb230052f51ca0d567bae630 [file] [log] [blame]
using J2N.Collections.Generic.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using JCG = J2N.Collections.Generic;
namespace Lucene.Net.Store
{
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// <summary>
/// Expert: A <see cref="Directory"/> instance that switches files between
/// two other <see cref="Directory"/> instances.
///
/// <para/>Files with the specified extensions are placed in the
/// primary directory; others are placed in the secondary
/// directory. The provided <see cref="T:ISet{string}"/> must not change once passed
/// to this class, and must allow multiple threads to call
/// contains at once.
/// <para/>
/// @lucene.experimental
/// </summary>
public class FileSwitchDirectory : BaseDirectory
{
private readonly Directory secondaryDir;
private readonly Directory primaryDir;
private readonly ISet<string> primaryExtensions;
private bool doClose;
public FileSwitchDirectory(ISet<string> primaryExtensions, Directory primaryDir, Directory secondaryDir, bool doClose)
{
this.primaryExtensions = primaryExtensions;
this.primaryDir = primaryDir;
this.secondaryDir = secondaryDir;
this.doClose = doClose;
this.m_lockFactory = primaryDir.LockFactory;
}
/// <summary>
/// Return the primary directory </summary>
public virtual Directory PrimaryDir => primaryDir;
/// <summary>
/// Return the secondary directory </summary>
public virtual Directory SecondaryDir => secondaryDir;
protected override void Dispose(bool disposing)
{
if (disposing && doClose)
{
try
{
secondaryDir.Dispose();
}
finally
{
primaryDir.Dispose();
}
doClose = false;
}
}
public override string[] ListAll()
{
ISet<string> files = new JCG.HashSet<string>();
// LUCENE-3380: either or both of our dirs could be FSDirs,
// but if one underlying delegate is an FSDir and mkdirs() has not
// yet been called, because so far everything is written to the other,
// in this case, we don't want to throw a NoSuchDirectoryException
DirectoryNotFoundException exc = null;
try
{
foreach (string f in primaryDir.ListAll())
{
files.Add(f);
}
}
catch (DirectoryNotFoundException e)
{
exc = e;
}
try
{
foreach (string f in secondaryDir.ListAll())
{
files.Add(f);
}
}
catch (DirectoryNotFoundException /*e*/)
{
// we got NoSuchDirectoryException from both dirs
// rethrow the first.
if (exc != null)
{
throw exc;
}
// we got NoSuchDirectoryException from the secondary,
// and the primary is empty.
if (files.Count == 0)
{
throw; // LUCENENET: CA2200: Rethrow to preserve stack details (https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2200-rethrow-to-preserve-stack-details)
}
}
// we got NoSuchDirectoryException from the primary,
// and the secondary is empty.
if (exc != null && files.Count == 0)
{
throw exc;
}
return files.ToArray();
}
/// <summary>
/// Utility method to return a file's extension. </summary>
public static string GetExtension(string name)
{
int i = name.LastIndexOf('.');
if (i == -1)
{
return "";
}
return name.Substring(i + 1, name.Length - (i + 1));
}
private Directory GetDirectory(string name)
{
string ext = GetExtension(name);
if (primaryExtensions.Contains(ext))
{
return primaryDir;
}
else
{
return secondaryDir;
}
}
[Obsolete("this method will be removed in 5.0")]
public override bool FileExists(string name)
{
return GetDirectory(name).FileExists(name);
}
public override void DeleteFile(string name)
{
GetDirectory(name).DeleteFile(name);
}
public override long FileLength(string name)
{
return GetDirectory(name).FileLength(name);
}
public override IndexOutput CreateOutput(string name, IOContext context)
{
return GetDirectory(name).CreateOutput(name, context);
}
public override void Sync(ICollection<string> names)
{
IList<string> primaryNames = new List<string>();
IList<string> secondaryNames = new List<string>();
foreach (string name in names)
{
if (primaryExtensions.Contains(GetExtension(name)))
{
primaryNames.Add(name);
}
else
{
secondaryNames.Add(name);
}
}
primaryDir.Sync(primaryNames);
secondaryDir.Sync(secondaryNames);
}
public override IndexInput OpenInput(string name, IOContext context)
{
return GetDirectory(name).OpenInput(name, context);
}
public override IndexInputSlicer CreateSlicer(string name, IOContext context)
{
return GetDirectory(name).CreateSlicer(name, context);
}
}
}