blob: bf1aaa54af42dfe832ae5d41de72f4b64864f298 [file] [log] [blame]
using Lucene.Net.Diagnostics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using BitSet = Lucene.Net.Util.OpenBitSet;
namespace Lucene.Net.Codecs.SimpleText
{
/*
* 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.
*/
using ArrayUtil = Util.ArrayUtil;
using BytesRef = Util.BytesRef;
using CharsRef = Util.CharsRef;
using ChecksumIndexInput = Store.ChecksumIndexInput;
using Directory = Store.Directory;
using IBits = Util.IBits;
using IMutableBits = Util.IMutableBits;
using IndexFileNames = Index.IndexFileNames;
using IndexOutput = Store.IndexOutput;
using IOContext = Store.IOContext;
using IOUtils = Util.IOUtils;
using SegmentCommitInfo = Index.SegmentCommitInfo;
using StringHelper = Util.StringHelper;
using UnicodeUtil = Util.UnicodeUtil;
/// <summary>
/// Reads/writes plain text live docs.
/// <para>
/// <b><font color="red">FOR RECREATIONAL USE ONLY</font></b>
/// </para>
/// @lucene.experimental
/// </summary>
public class SimpleTextLiveDocsFormat : LiveDocsFormat
{
internal const string LIVEDOCS_EXTENSION = "liv";
internal static readonly BytesRef SIZE = new BytesRef("size ");
internal static readonly BytesRef DOC = new BytesRef(" doc ");
internal static readonly BytesRef END = new BytesRef("END");
public override IMutableBits NewLiveDocs(int size)
{
return new SimpleTextMutableBits(size);
}
public override IMutableBits NewLiveDocs(IBits existing)
{
var bits = (SimpleTextBits) existing;
return new SimpleTextMutableBits((BitSet)bits.bits.Clone(), bits.Length);
}
public override IBits ReadLiveDocs(Directory dir, SegmentCommitInfo info, IOContext context)
{
if (Debugging.AssertsEnabled) Debugging.Assert(info.HasDeletions);
var scratch = new BytesRef();
var scratchUtf16 = new CharsRef();
var fileName = IndexFileNames.FileNameFromGeneration(info.Info.Name, LIVEDOCS_EXTENSION, info.DelGen);
ChecksumIndexInput input = null;
var success = false;
try
{
input = dir.OpenChecksumInput(fileName, context);
SimpleTextUtil.ReadLine(input, scratch);
if (Debugging.AssertsEnabled) Debugging.Assert(StringHelper.StartsWith(scratch, SIZE));
var size = ParseInt32At(scratch, SIZE.Length, scratchUtf16);
var bits = new BitSet(size);
SimpleTextUtil.ReadLine(input, scratch);
while (!scratch.Equals(END))
{
if (Debugging.AssertsEnabled) Debugging.Assert(StringHelper.StartsWith(scratch, DOC));
var docid = ParseInt32At(scratch, DOC.Length, scratchUtf16);
bits.Set(docid);
SimpleTextUtil.ReadLine(input, scratch);
}
SimpleTextUtil.CheckFooter(input);
success = true;
return new SimpleTextBits(bits, size);
}
finally
{
if (success)
{
IOUtils.Dispose(input);
}
else
{
IOUtils.DisposeWhileHandlingException(input);
}
}
}
/// <summary>
/// NOTE: This was parseIntAt() in Lucene.
/// </summary>
private int ParseInt32At(BytesRef bytes, int offset, CharsRef scratch)
{
UnicodeUtil.UTF8toUTF16(bytes.Bytes, bytes.Offset + offset, bytes.Length - offset, scratch);
return ArrayUtil.ParseInt32(scratch.Chars, 0, scratch.Length);
}
public override void WriteLiveDocs(IMutableBits bits, Directory dir, SegmentCommitInfo info, int newDelCount,
IOContext context)
{
var set = ((SimpleTextBits) bits).bits;
var size = bits.Length;
var scratch = new BytesRef();
var fileName = IndexFileNames.FileNameFromGeneration(info.Info.Name, LIVEDOCS_EXTENSION, info.NextDelGen);
IndexOutput output = null;
var success = false;
try
{
output = dir.CreateOutput(fileName, context);
SimpleTextUtil.Write(output, SIZE);
SimpleTextUtil.Write(output, Convert.ToString(size, CultureInfo.InvariantCulture), scratch);
SimpleTextUtil.WriteNewline(output);
for (int i = set.NextSetBit(0); i >= 0; i = set.NextSetBit(i + 1))
{
SimpleTextUtil.Write(output, DOC);
SimpleTextUtil.Write(output, Convert.ToString(i, CultureInfo.InvariantCulture), scratch);
SimpleTextUtil.WriteNewline(output);
}
SimpleTextUtil.Write(output, END);
SimpleTextUtil.WriteNewline(output);
SimpleTextUtil.WriteChecksum(output, scratch);
success = true;
}
finally
{
if (success)
{
IOUtils.Dispose(output);
}
else
{
IOUtils.DisposeWhileHandlingException(output);
}
}
}
public override void Files(SegmentCommitInfo info, ICollection<string> files)
{
if (info.HasDeletions)
{
files.Add(IndexFileNames.FileNameFromGeneration(info.Info.Name, LIVEDOCS_EXTENSION, info.DelGen));
}
}
// read-only
internal class SimpleTextBits : IBits
{
internal readonly BitSet bits;
private readonly int size;
internal SimpleTextBits(BitSet bits, int size)
{
this.bits = bits;
this.size = size;
}
public virtual bool Get(int index)
{
return bits.Get(index);
}
public virtual int Length => size;
}
// read-write
internal class SimpleTextMutableBits : SimpleTextBits, IMutableBits
{
internal SimpleTextMutableBits(int size)
: this(new BitSet(size), size)
{
bits.Set(0, size);
}
internal SimpleTextMutableBits(BitSet bits, int size)
: base(bits, size)
{
}
public virtual void Clear(int bit)
{
bits.Clear(bit);
}
}
}
}