using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib.GZip;
using ICSharpCode.SharpZipLib.Tar;
using ICSharpCode.SharpZipLib.BZip2;
using log4net;
namespace wbackup
{
class ArchiveTarFile : BackupStreamBase
{
protected FileStream fileOutputStream;
protected GZipOutputStream gzipOutputStream;
protected TarOutputStream tarOutputStream;
protected int archiveCount;
protected int buffSelect;
protected int buffSize;
protected byte[][] readBuffer;
protected DateTime minLastWriteDate;
public ArchiveTarFile(string exportPath, BackupStreamBase stream = null):base(stream)
{
string postFixString = DateTime.Now.ToString("yyyyMMddHHmmss");
string zipFileName = exportPath + postFixString + ".tar.gz";
// 出力先ストリームのインスタンス生成
fileOutputStream = new FileStream(zipFileName, FileMode.Create, FileAccess.Write);
gzipOutputStream = new GZipOutputStream(fileOutputStream);
tarOutputStream = new TarOutputStream(gzipOutputStream, Encoding.UTF8);
gzipOutputStream.IsStreamOwner = false;
// ソース読込のためのバッファ生成
buffSelect = 0;
buffSize = tarOutputStream.RecordSize;
readBuffer = new byte[2][];
readBuffer[0] = new byte[buffSize];
readBuffer[1] = new byte[buffSize];
archiveCount = 0;
minLastWriteDate = DateTime.Parse("1970-12-01");
}
protected override void DisposeManagedResource()
{
tarOutputStream.Flush();
tarOutputStream.Close();
}
protected override void DoWork(string sourceFileName)
{
if (log.IsInfoEnabled) log.InfoFormat("Archive {0}, {1}", Interlocked.Increment(ref archiveCount), sourceFileName);
using (var fis = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read))
{
// 最終書込日時が小さい場合には書き換えておく
var lastWriteTime = File.GetLastWriteTime(sourceFileName);
if (lastWriteTime < minLastWriteDate)
{
File.SetLastWriteTime(sourceFileName, minLastWriteDate);
}
// ZIPファイルヘッダ作成
TarEntry tarEntry = TarEntry.CreateEntryFromFile(sourceFileName);
tarOutputStream.PutNextEntry(tarEntry);
Task<int> readResult = fis.ReadAsync(readBuffer[buffSelect], 0, buffSize);
while (true)
{
readResult.Wait();
int readSize = readResult.Result;
if (readSize <= 0)
{
break;
}
Task writeResult = tarOutputStream.WriteAsync(readBuffer[buffSelect], 0, readSize);
buffSelect ^= 1;
readResult = fis.ReadAsync(readBuffer[buffSelect], 0, buffSize);
writeResult.Wait();
}
tarOutputStream.CloseEntry();
AddNextSource(sourceFileName);
}
}
}
}