blob: 567cb2f07561ca83f4c70664446a7d605631de7a [file] [log] [blame]
using Lucene.Net.Diagnostics;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Lucene.Net.Util;
using System;
namespace Lucene.Net.Codecs.Lucene3x
{
/*
* 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>
/// @lucene.experimental </summary>
#pragma warning disable 612, 618
internal sealed class PreFlexRWStoredFieldsWriter : StoredFieldsWriter
{
private readonly Directory directory;
private readonly string segment;
#pragma warning disable CA2213 // Disposable fields should be disposed
private IndexOutput fieldsStream;
private IndexOutput indexStream;
#pragma warning restore CA2213 // Disposable fields should be disposed
public PreFlexRWStoredFieldsWriter(Directory directory, string segment, IOContext context)
{
if (Debugging.AssertsEnabled) Debugging.Assert(directory != null);
this.directory = directory;
this.segment = segment;
bool success = false;
try
{
fieldsStream = directory.CreateOutput(IndexFileNames.SegmentFileName(segment, "", Lucene3xStoredFieldsReader.FIELDS_EXTENSION), context);
indexStream = directory.CreateOutput(IndexFileNames.SegmentFileName(segment, "", Lucene3xStoredFieldsReader.FIELDS_INDEX_EXTENSION), context);
fieldsStream.WriteInt32(Lucene3xStoredFieldsReader.FORMAT_CURRENT);
indexStream.WriteInt32(Lucene3xStoredFieldsReader.FORMAT_CURRENT);
success = true;
}
finally
{
if (!success)
{
Abort();
}
}
}
// Writes the contents of buffer into the fields stream
// and adds a new entry for this document into the index
// stream. this assumes the buffer was already written
// in the correct fields format.
public override void StartDocument(int numStoredFields)
{
indexStream.WriteInt64(fieldsStream.GetFilePointer());
fieldsStream.WriteVInt32(numStoredFields);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
try
{
IOUtils.Dispose(fieldsStream, indexStream);
}
finally
{
fieldsStream = indexStream = null;
}
}
}
public override void Abort()
{
try
{
Dispose();
}
catch (Exception)
{
// ignored
}
IOUtils.DeleteFilesIgnoringExceptions(directory,
IndexFileNames.SegmentFileName(segment, "", Lucene3xStoredFieldsReader.FIELDS_EXTENSION),
IndexFileNames.SegmentFileName(segment, "", Lucene3xStoredFieldsReader.FIELDS_INDEX_EXTENSION));
}
public override void WriteField(FieldInfo info, IIndexableField field)
{
fieldsStream.WriteVInt32(info.Number);
int bits = 0;
BytesRef bytes;
string @string;
// TODO: maybe a field should serialize itself?
// this way we don't bake into indexer all these
// specific encodings for different fields? and apps
// can customize...
// LUCENENET specific - To avoid boxing/unboxing, we don't
// call GetNumericValue(). Instead, we check the field.NumericType and then
// call the appropriate conversion method.
if (field.NumericType != NumericFieldType.NONE)
{
switch (field.NumericType)
{
case NumericFieldType.BYTE:
case NumericFieldType.INT16:
case NumericFieldType.INT32:
bits |= Lucene3xStoredFieldsReader.FIELD_IS_NUMERIC_INT;
break;
case NumericFieldType.INT64:
bits |= Lucene3xStoredFieldsReader.FIELD_IS_NUMERIC_LONG;
break;
case NumericFieldType.SINGLE:
bits |= Lucene3xStoredFieldsReader.FIELD_IS_NUMERIC_FLOAT;
break;
case NumericFieldType.DOUBLE:
bits |= Lucene3xStoredFieldsReader.FIELD_IS_NUMERIC_DOUBLE;
break;
default:
throw new ArgumentException("cannot store numeric type " + field.NumericType);
}
@string = null;
bytes = null;
}
else
{
bytes = field.GetBinaryValue();
if (bytes != null)
{
bits |= Lucene3xStoredFieldsReader.FIELD_IS_BINARY;
@string = null;
}
else
{
@string = field.GetStringValue();
if (@string == null)
{
throw new ArgumentException("field " + field.Name + " is stored but does not have binaryValue, stringValue nor numericValue");
}
}
}
fieldsStream.WriteByte((byte)bits);
if (bytes != null)
{
fieldsStream.WriteVInt32(bytes.Length);
fieldsStream.WriteBytes(bytes.Bytes, bytes.Offset, bytes.Length);
}
else if (@string != null)
{
fieldsStream.WriteString(field.GetStringValue());
}
else
{
switch (field.NumericType)
{
case NumericFieldType.BYTE:
case NumericFieldType.INT16:
case NumericFieldType.INT32:
fieldsStream.WriteInt32(field.GetInt32Value().Value);
break;
case NumericFieldType.INT64:
fieldsStream.WriteInt64(field.GetInt64Value().Value);
break;
case NumericFieldType.SINGLE:
fieldsStream.WriteInt32(J2N.BitConversion.SingleToInt32Bits(field.GetSingleValue().Value));
break;
case NumericFieldType.DOUBLE:
fieldsStream.WriteInt64(J2N.BitConversion.DoubleToInt64Bits(field.GetDoubleValue().Value));
break;
default:
if (Debugging.AssertsEnabled) Debugging.Assert(false);
break;
}
}
}
public override void Finish(FieldInfos fis, int numDocs)
{
if (4 + ((long)numDocs) * 8 != indexStream.GetFilePointer())
// this is most likely a bug in Sun JRE 1.6.0_04/_05;
// we detect that the bug has struck, here, and
// throw an exception to prevent the corruption from
// entering the index. See LUCENE-1282 for
// details.
{
throw new Exception("fdx size mismatch: docCount is " + numDocs + " but fdx file size is " + indexStream.GetFilePointer() + " file=" + indexStream.ToString() + "; now aborting this merge to prevent index corruption");
}
}
}
#pragma warning restore 612, 618
}