using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace RaptorDB
{
internal class LogFile
{
public LogFile()
{
bw = new BinaryWriter(ms, Encoding.UTF8);
}
public LogFile(string filename, int number, int maxkeylen, string logNumberFormat)
{
// create a log file
FileName = filename + number.ToString(logNumberFormat);
Number = number;
_maxKeyLen = maxkeylen;
bw = new BinaryWriter(ms, Encoding.UTF8);
_file = new FileStream(FileName, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read);
WriteLogHeader();
}
public int Number;
public string FileName;
public bool Readonly;
public int CurrentCount = 0;
byte[] _header = new byte[] {
(byte)'M', (byte)'G', (byte)'L',
0 // [maxkeylen]
};
internal SafeDictionary<byte[], long> _memCache = new SafeDictionary<byte[], long>(Global.MaxItemsBeforeIndexing);
private Stream _file;
private int _maxKeyLen;
private BinaryWriter bw;
private MemoryStream ms = new MemoryStream();
private void WriteLogHeader()
{
// write log file header;
_header[3] = (byte)_maxKeyLen;
_file.Write(_header, 0, _header.Length);
_file.Flush();
}
public void Shutdown()
{
if (_file != null)
{
_file.Close();
_file = null;
_memCache = null;
}
}
public void ReadLogFile(string filename)
{
if (File.Exists(filename))
{
_file = new FileStream(filename, FileMode.Open, FileAccess.Read);
// read log header and check ok
if (ReadLogHeader())
{
// read data and put in cache
ReadData();
}
_file.Close();
_file = null;
}
}
public void DeleteLog()
{
Shutdown();
Console.Write(" D" + Number + " ");
File.Delete(FileName);
}
private void ReadData()
{
int len = 8 + 1 + _maxKeyLen;
byte[] rec = new byte[len];
while (_file.Read(rec, 0, len) == len)
{
long l = Helper.ToInt64(rec, 0);
short of = (short)rec[8];
byte[] k = new byte[of];
Buffer.BlockCopy(rec, 9, k, 0, of);
_memCache.Add(k, l);
}
}
private bool ReadLogHeader()
{
bool ok = true;
_file.Seek(0L, SeekOrigin.Begin);
byte[] hdr = new byte[_header.Length];
_file.Read(hdr, 0, _header.Length);
for (int i = 0; i < _header.Length - 1; i++)
{
if (hdr[i] != _header[i])
ok = false;
}
if (ok)
_maxKeyLen = (int)hdr[_header.Length - 1];
return ok;
}
private void SaveToLogFile(byte[] key, long offset)
{
if (Readonly == false)
{
if (_file != null)
{
byte[] b = CreateRecord(key, offset);
_file.Write(b, 0, b.Length);
_file.Flush();
}
}
}
private byte[] CreateRecord(byte[] key, long offset)
{
// create record
byte[] rec = new byte[8 + 1 + _maxKeyLen];
byte[] off = Helper.GetBytes(offset);
Buffer.BlockCopy(off,0, rec,0, off.Length);
byte[] str = key;
rec[8] = (byte)str.Length;
int len = (str.Length < _maxKeyLen ? str.Length : _maxKeyLen);
Buffer.BlockCopy(str, 0, rec, off.Length + 1, len);
return rec;
}
public long Get(byte[] k)
{
long l = -1;
_memCache.TryGetValue(k, out l);
return l;
}
public void Set(byte[] k, long val)
{
if (Readonly == false)
{
CurrentCount++;
_memCache.Add(k, val);
// write log file
SaveToLogFile(k, val);
}
}
public void Close()
{
if (_file != null)
{
_file.Flush();
_file.Close();
_file = null;
}
}
public IEnumerator<KeyValuePair<byte[], long>> GetEnumerator()
{
return _memCache.GetEnumerator();
}
}
}