Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Azure Storage SDK to v12, add logging for Azure Blob storage directory #198

Closed
wants to merge 48 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
688b287
POC of nomerge, no write for readonly event for v1
Nov 8, 2020
a5f09bf
add more security on missing files
Nov 24, 2020
dbd12f1
ver
Nov 24, 2020
16c3429
Merge remote-tracking branch 'github.com/v1.0.6' into bugfix/azure-bl…
Nov 24, 2020
0f58a0e
semi working ver
Nov 25, 2020
c4edc82
make no merge sheduler public
Nov 26, 2020
e342c4a
create proper readonly DIrectory with aliasing for time of resync
Nov 27, 2020
e53d62a
correct versions
Nov 27, 2020
d439b77
Merge remote-tracking branch 'github.com/master' into bugfix/azure-bl…
Nov 30, 2020
62f0fb9
move definition to new interface
Nov 30, 2020
23257d7
Separate method from new interface to new Factory
Nov 30, 2020
1ccbdec
removed unsed code and definitions
Nov 30, 2020
5ebc18e
correct definition
Nov 30, 2020
35afc28
correct nuspec and directory
Nov 30, 2020
9ee49ac
Fix ruleset so this builds
nzdev Dec 4, 2020
be6ccb7
Update blob storage package as previous obsolete. Add logging extensi…
nzdev Dec 4, 2020
fb79db7
Add logging
nzdev Dec 4, 2020
2993a68
Deduplicate isreadonly
nzdev Dec 4, 2020
2b60857
don't change name unintentionally
nzdev Dec 4, 2020
0d80363
logging for lock errors
nzdev Dec 4, 2020
9fb1f56
Renamed AzureDirectory to AzureLuceneDirectory to avoid conflicts wit…
nzdev Dec 4, 2020
b7af836
revert overwrite
nzdev Dec 4, 2020
66a16d9
Tests run (with possible bugs) in azurite
nzdev Dec 4, 2020
8c94405
allow overwrite
nzdev Dec 4, 2020
df80409
More extensibility
nzdev Dec 4, 2020
e0f5504
update nuspec
nzdev Dec 5, 2020
7e65b23
update nuspec dependencies
nzdev Dec 5, 2020
abd1216
bugfix. update nuspec
nzdev Dec 5, 2020
005632c
Prevent indexwriter's merge scheduler being replaced.
nzdev Dec 6, 2020
19feb3a
refactor
nzdev Dec 6, 2020
31176c5
optimize when Indexwriter is created to avoid creating twice due to d…
nzdev Dec 6, 2020
07770fd
Add test for readonly azuredirectory. Fix getallblobfiles.
nzdev Dec 6, 2020
b4f720c
more logging. More virtual methods so fault handling / retries can be…
nzdev Dec 6, 2020
26add11
revert changes to createnewindex
nzdev Dec 6, 2020
6f7177a
revert exists check to save on transactions.
nzdev Dec 6, 2020
2da83a6
Remove microsoft.logging. Use Trace for logs instead.
Dec 6, 2020
761826b
change version number
Dec 6, 2020
a636d95
just needs to stop writing the .lock file in the readonly cache
Dec 8, 2020
b6043f2
test passes
Dec 8, 2020
4d119d5
Fix test
Dec 8, 2020
3f0ea94
wip, use a manifest
Dec 8, 2020
0e469fb
disable writes for readonly indexes. Fix decompression.
Dec 15, 2020
5f069ce
fix documentwriting event
Dec 15, 2020
7086766
Remove cachedirectory from examinedirectory
Dec 21, 2020
8f1431c
remove commented out code
Dec 21, 2020
805b5c7
merge
nzdev Jan 9, 2021
311f347
test fix
nzdev Jan 9, 2021
c4f9483
Fix lock name (bielu). Catch exception for empty old sync dir
nzdev Jan 9, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Examine.AzureDirectory/AzureDirectoryFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public override Lucene.Net.Store.Directory CreateDirectory(DirectoryInfo luceneI
directory.IsReadOnly = _isReadOnly;
directory.SetMergePolicyAction(e => new NoMergePolicy(e));
directory.SetMergeScheduler(new NoMergeSheduler());
directory.SetDeletion(NoDeletionPolicy.INSTANCE);
directory.SetDeletion(new NoDeletionPolicy());
return directory;
}

Expand Down
2 changes: 2 additions & 0 deletions src/Examine.AzureDirectory/AzureIndexInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading;
using Azure.Storage.Blobs;
using Examine.LuceneEngine.Directories;
Expand All @@ -26,6 +27,7 @@ public class AzureIndexInput : IndexInput
public AzureIndexInput(AzureLuceneDirectory azuredirectory, BlobClient blob)
{
_name = blob.Uri.Segments[blob.Uri.Segments.Length - 1];
_name = _name.Split(new string[] { "%2F" }, StringSplitOptions.RemoveEmptyEntries).Last();
_azureDirectory = azuredirectory ?? throw new ArgumentNullException(nameof(azuredirectory));
#if FULLDEBUG
Trace.WriteLine($"opening {_name} ");
Expand Down
5 changes: 2 additions & 3 deletions src/Examine.AzureDirectory/AzureLuceneDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ protected virtual BlobContainerClient GetBlobContainerClient(string containerNam

public string RootFolder { get; }
public bool CompressBlobs { get; }
public Lucene.Net.Store.Directory CacheDirectory { get; protected set; }

public void ClearCache()
{
Expand All @@ -118,7 +117,7 @@ public void ClearCache()
CacheDirectory.DeleteFile(file);
}
}
public void RebuildCache()
public virtual void RebuildCache()
{
Trace.WriteLine($"INFO Rebuilding index cache {RootFolder}");
try
Expand Down Expand Up @@ -160,7 +159,7 @@ internal string[] GetAllBlobFiles()
{
return results.ToArray();
}
var names = results.Select(x => x.Replace(RootFolder, "")).ToArray();
var names = results.Where(x => !x.EndsWith(".lock")).Select(x => x.Replace(RootFolder, "")).ToArray();
nzdev marked this conversation as resolved.
Show resolved Hide resolved
return names;
}

Expand Down
125 changes: 46 additions & 79 deletions src/Examine.AzureDirectory/AzureReadOnlyLuceneDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,47 +66,54 @@ private void CreateOrReadCache()

}
}

public void RebuildCache()
private object _rebuildLock = new object();
public override void RebuildCache()
{

Trace.WriteLine("INFO Rebuilding cache");
var tempDir = new DirectoryInfo(
Path.Combine(_cacheDirectoryPath,
_cacheDirectoryName, DateTimeOffset.UtcNow.ToString("yyyyMMddTHHmmssfffffff")));
if (tempDir.Exists == false)
tempDir.Create();
Lucene.Net.Store.Directory newIndex = new SimpleFSDirectory(tempDir);
foreach (string file in GetAllBlobFiles())
lock (_rebuildLock)
{
// newIndex.TouchFile(file);
var blob = _blobContainer.GetBlobClient(RootFolder + file);
SyncFile(newIndex,blob, file);
}

var oldIndex = CacheDirectory;
newIndex.Dispose();
newIndex = new SimpleFSDirectory(tempDir);

CacheDirectory = newIndex;
_lockFactory = newIndex.LockFactory;
if (oldIndex != null)
{
oldIndex.ClearLock("write.lock");
foreach (var file in oldIndex.ListAll())
//Needs locking
Trace.WriteLine("INFO Rebuilding cache");
var tempDir = new DirectoryInfo(
Path.Combine(_cacheDirectoryPath,
_cacheDirectoryName, DateTimeOffset.UtcNow.ToString("yyyyMMddTHHmmssfffffff")));
if (tempDir.Exists == false)
tempDir.Create();
Lucene.Net.Store.Directory newIndex = new SimpleFSDirectory(tempDir);
foreach (string file in GetAllBlobFiles())
{
if (oldIndex.FileExists(file))
// newIndex.TouchFile(file);
if ("write.lock".Equals(file))
nzdev marked this conversation as resolved.
Show resolved Hide resolved
{
oldIndex.DeleteFile(file);
continue;
}
var blob = _blobContainer.GetBlobClient(RootFolder + file);
SyncFile(newIndex, blob, file);
}
oldIndex.Dispose();
DirectoryInfo oldindex = new DirectoryInfo(Path.Combine(_cacheDirectoryPath,
_cacheDirectoryName,OldIndexFolderName));
oldindex.Delete();

var oldIndex = CacheDirectory;
newIndex.Dispose();
newIndex = new SimpleFSDirectory(tempDir);

CacheDirectory = newIndex;
_lockFactory = newIndex.LockFactory;
if (oldIndex != null)
{
oldIndex.ClearLock("write.lock");
foreach (var file in oldIndex.ListAll())
{
if (oldIndex.FileExists(file))
{
oldIndex.DeleteFile(file);
}
}
oldIndex.Dispose();
DirectoryInfo oldindex = new DirectoryInfo(Path.Combine(_cacheDirectoryPath,
_cacheDirectoryName, OldIndexFolderName));
oldindex.Delete();
}
OldIndexFolderName = tempDir.Name;
}
OldIndexFolderName = tempDir.Name;

}
private void SyncFile(Directory newIndex, BlobClient blob, string fileName)
{
Expand Down Expand Up @@ -150,52 +157,12 @@ protected void InflateStream(Lucene.Net.Store.Directory newIndex, BlobClient blo

}
}
public override string[] ListAll()
{
return CacheDirectory.ListAll();
}

public override bool FileExists(string name)
{
return CacheDirectory.FileExists(name);
}

public override long FileModified(string name)
{
return CacheDirectory.FileModified(name);
}

public override void TouchFile(string name)
{
CacheDirectory.TouchFile(name);
}

public override void DeleteFile(string name)
{
CacheDirectory.DeleteFile(name);
}

public override long FileLength(string name)
{
return CacheDirectory.FileLength(name);
}

public override IndexOutput CreateOutput(string name)
{
return CacheDirectory.CreateOutput(name);
}

public override IndexInput OpenInput(string name)
{
CheckDirty();
return CacheDirectory.OpenInput(name);
}

protected override void Dispose(bool disposing)
{
CacheDirectory.Dispose();
}
protected virtual void HandleOutOfSync()

//protected override void Dispose(bool disposing)
//{
// CacheDirectory.Dispose();
//}
protected override void HandleOutOfSync()
{
RebuildCache();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public override Lucene.Net.Store.Directory CreateDirectory(DirectoryInfo luceneI
directory.IsReadOnly = _isReadOnly;
directory.SetMergePolicyAction(e => new NoMergePolicy(e));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth an ext to do this configuration instead of duplicating this code

directory.SetMergeScheduler(new NoMergeSheduler());
directory.SetDeletion(NoDeletionPolicy.INSTANCE);
directory.SetDeletion(new NoDeletionPolicy());
return directory;
}
protected string GetLocalStorageDirectory(DirectoryInfo indexPath)
Expand Down
101 changes: 97 additions & 4 deletions src/Examine.Test/AzureDirectoryTests/IntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,13 @@ public void TestReadAndWrite()

azureDirectory.SetMergePolicyAction(e => new NoMergePolicy(e));
azureDirectory.SetMergeScheduler(new NoMergeSheduler());
azureDirectory.SetDeletion(NoDeletionPolicy.INSTANCE);
azureDirectory.SetDeletion(new NoDeletionPolicy());
using (var indexWriter = new IndexWriter(azureDirectory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30), !IndexReader.IndexExists(azureDirectory),
azureDirectory.GetDeletionPolicy(), new Lucene.Net.Index.IndexWriter.MaxFieldLength(IndexWriter.DEFAULT_MAX_FIELD_LENGTH)))
{
indexWriter.SetRAMBufferSizeMB(10.0);
indexWriter.SetMergePolicy(azureDirectory.GetMergePolicy(indexWriter));
indexWriter.SetMergeScheduler(azureDirectory.GetMergeScheduler());

for (int iDoc = 0; iDoc < 10000; iDoc++)
{
var doc = new Document();
Expand Down Expand Up @@ -92,7 +91,7 @@ public void TestReadOnlyAndWrite()

azureReadWriteDirectory.SetMergePolicyAction(e => new NoMergePolicy(e));
azureReadWriteDirectory.SetMergeScheduler(new NoMergeSheduler());
azureReadWriteDirectory.SetDeletion(NoDeletionPolicy.INSTANCE);
azureReadWriteDirectory.SetDeletion(new NoDeletionPolicy());
using (var indexWriter = new IndexWriter(azureReadWriteDirectory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30),
!IndexReader.IndexExists(azureReadWriteDirectory), azureReadWriteDirectory.GetDeletionPolicy(),
new Lucene.Net.Index.IndexWriter.MaxFieldLength(IndexWriter.DEFAULT_MAX_FIELD_LENGTH)))
Expand Down Expand Up @@ -127,7 +126,7 @@ public void TestReadOnlyAndWrite()
var azureReadOnlyDirectory = new AzureReadOnlyLuceneDirectory(connectionString, containerName, readonlyDirectoryFolder.FullName, containerName);
azureReadOnlyDirectory.SetMergePolicyAction(e => new NoMergePolicy(e));
azureReadOnlyDirectory.SetMergeScheduler(new NoMergeSheduler());
azureReadOnlyDirectory.SetDeletion(NoDeletionPolicy.INSTANCE);
azureReadOnlyDirectory.SetDeletion(new NoDeletionPolicy());
for (var i = 0; i < 100; i++)
{
using (var searcher = new IndexSearcher(azureReadOnlyDirectory))
Expand Down Expand Up @@ -156,6 +155,100 @@ public void TestReadOnlyAndWrite()

}

[Explicit("Requires storage emulator to be running")]
[Test]
public void TestWritingToReadonly()
{
var connectionString = Environment.GetEnvironmentVariable("DataConnectionString") ?? "UseDevelopmentStorage=true";
string containerName = "testcatalog";

var readWriteCacheDirectory = new RandomIdRAMDirectory();
AzureLuceneDirectory azureReadWriteDirectory = null;
AzureReadOnlyLuceneDirectory azureReadOnlyDirectory = null;
var readonlyDirectoryFolder = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "TEMP", containerName));
try
{
// default AzureDirectory stores cache in local temp folder
azureReadWriteDirectory = new AzureLuceneDirectory(connectionString, containerName, readWriteCacheDirectory);

azureReadWriteDirectory.SetMergePolicyAction(e => new NoMergePolicy(e));
azureReadWriteDirectory.SetMergeScheduler(new NoMergeSheduler());
azureReadWriteDirectory.SetDeletion(new NoDeletionPolicy());
using (var indexWriter = new IndexWriter(azureReadWriteDirectory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30),
!IndexReader.IndexExists(azureReadWriteDirectory), azureReadWriteDirectory.GetDeletionPolicy(),
new Lucene.Net.Index.IndexWriter.MaxFieldLength(IndexWriter.DEFAULT_MAX_FIELD_LENGTH)))
{

indexWriter.SetRAMBufferSizeMB(10.0);
indexWriter.SetMergePolicy(azureReadWriteDirectory.GetMergePolicy(indexWriter));
indexWriter.SetMergeScheduler(azureReadWriteDirectory.GetMergeScheduler());

for (int iDoc = 0; iDoc < 10000; iDoc++)
{
var doc = new Document();
doc.Add(new Field("id", DateTime.Now.ToFileTimeUtc().ToString() + "-" + iDoc.ToString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
doc.Add(new Field("Title", GeneratePhrase(10), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
doc.Add(new Field("Body", GeneratePhrase(40), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO));
indexWriter.AddDocument(doc);
}

Console.WriteLine("Total docs is {0}", indexWriter.NumDocs());
}
for (var i = 0; i < 100; i++)
{
using (var searcher = new IndexSearcher(azureReadWriteDirectory))
{
Assert.AreNotEqual(0, SearchForPhrase(searcher, "dog"));
Assert.AreNotEqual(0, SearchForPhrase(searcher, "cat"));
Assert.AreNotEqual(0, SearchForPhrase(searcher, "car"));
}
}

readonlyDirectoryFolder.Create();
azureReadOnlyDirectory = new AzureReadOnlyLuceneDirectory(connectionString, containerName, readonlyDirectoryFolder.FullName, containerName);
azureReadOnlyDirectory.SetMergePolicyAction(e => new NoMergePolicy(e));
azureReadOnlyDirectory.SetMergeScheduler(new NoMergeSheduler());
azureReadOnlyDirectory.SetDeletion(new NoDeletionPolicy());

using (var indexWriter = new IndexWriter(azureReadOnlyDirectory, new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30),
!IndexReader.IndexExists(azureReadOnlyDirectory), azureReadOnlyDirectory.GetDeletionPolicy(),
new Lucene.Net.Index.IndexWriter.MaxFieldLength(IndexWriter.DEFAULT_MAX_FIELD_LENGTH)))
{

indexWriter.SetRAMBufferSizeMB(10.0);
indexWriter.SetMergePolicy(azureReadOnlyDirectory.GetMergePolicy(indexWriter));
indexWriter.SetMergeScheduler(azureReadOnlyDirectory.GetMergeScheduler());
//TODO: Use Test index. adding documents should be blocked
}
for (var i = 0; i < 100; i++)
{
using (var searcher = new IndexSearcher(azureReadOnlyDirectory))
{
Assert.AreEqual(0, SearchForPhrase(searcher, "Sony"));
Assert.AreEqual(0, SearchForPhrase(searcher, "Nintendo"));
}
}
//Use
}
finally
{
readWriteCacheDirectory?.Dispose();
azureReadOnlyDirectory?.Dispose();
azureReadWriteDirectory?.Dispose();
// check the container exists, and delete it
var containerClient = new BlobContainerClient(connectionString, containerName);
var exists = containerClient.Exists();
if (exists)
containerClient.Delete();

if (readonlyDirectoryFolder.Exists)
{
readonlyDirectoryFolder.Delete(true);
}
}

}

static int SearchForPhrase(IndexSearcher searcher, string phrase)
{
var parser = new Lucene.Net.QueryParsers.QueryParser(Lucene.Net.Util.Version.LUCENE_CURRENT, "Body", new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_CURRENT));
Expand Down
Loading