Newer
Older
wbackup / wbackup / ArchiveTarFile.cs
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 zipFileName = exportPath + ".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);
            }
        }
    }
}