Exemplo n.º 1
0
        /// <summary>
        /// Create or check the digest file
        /// </summary>
        /// <param name="DigestMode">Digest mode</param>
        /// <param name="DataFile_">Data file name</param>
        /// <param name="MapFile_">Map file name</param>
        /// <param name="DigestFile_">Digest file name</param>
        /// <param name="SegmentSize_">Segment size</param>
        public void Proc(int DigestMode, string DataFile_, string MapFile_, string DigestFile_, int SegmentSize_, bool PromptConfirm)
        {
            long DigestFileSize    = 0;
            int  DigestSegmentSize = 0;

            int SegmentSize = SegmentSize_;

            DigestSegmentSize = SegmentSize;

            MailFile MF = new MailFile();

            if (MF.Open(false, true, DataFile_, MapFile_))
            {
                MF.SetSegmentSize(SegmentSize);
                MF.CalcSegmentCount();

                long FileSize = MF.GetDataSize();
                DigestFileSize = FileSize;
                int SegmentCount__ = MF.GetSegmentCount();
                MailSegment.ConsoleLineToLog    = true;
                MailSegment.ConsoleLineToLogSum = true;
                MailSegment.Console_WriteLine("");
                MailSegment.Console_WriteLine("Data file size: " + FileSize);
                MailSegment.Console_WriteLine("Data segment count: " + SegmentCount__);
                MailSegment.ConsoleLineToLogSum = false;
                MailSegment.ConsoleLineToLog    = false;
                MailSegment.Console_WriteLine("");

                if (DigestMode != 0)
                {
                    MailFile MD = new MailFile();
                    if (MD.Open(true, DigestMode != 0, DigestFile_, null))
                    {
                        MD.SetSegmentSize(SegmentSize);
                        if (DigestFile_ != null)
                        {
                            MD.CalcSegmentCount();
                            DigestSegmentSize = MD.DigestSegmentSize;
                            DigestFileSize    = MD.DigestFileSize;
                        }
                        else
                        {
                            DigestSegmentSize = 0;
                            DigestFileSize    = 0;
                        }
                        MailSegment.Console_WriteLine("Data file size from digest file: " + DigestFileSize);
                        MailSegment.Console_WriteLine("Segment size from digest file: " + DigestSegmentSize);
                        MailSegment.Console_WriteLine("");
                        MD.Close();
                    }
                    else
                    {
                        MailSegment.Console_WriteLine("Digest file open error");
                    }
                }

                if (Program.PromptConfirm(PromptConfirm))
                {
                    if ((DigestMode == 1) && (DigestMode == 3))
                    {
                        MF.MapChange(1, 0);
                        MF.MapChange(2, 0);
                    }

                    if (DigestMode == 0)
                    {
                        try
                        {
                            if (File.Exists(DigestFile_))
                            {
                                File.Delete(DigestFile_);
                            }
                        }
                        catch
                        {
                            MailSegment.ConsoleLineToLog    = true;
                            MailSegment.ConsoleLineToLogSum = true;
                            MailSegment.Console_WriteLine("Digest file creation error");
                            MailSegment.ConsoleLineToLogSum = false;
                            MailSegment.ConsoleLineToLog    = false;
                            return;
                        }
                    }

                    MailFile MD = new MailFile();
                    if (MD.Open(true, DigestMode != 0, DigestFile_, null))
                    {
                        Stopwatch_ TSW = new Stopwatch_();
                        MailSegment.Log();
                        MailSegment.LogReset();
                        MailSegment.Log("Time stamp", "Processed segments since previous entry", "Totally processed segments", "All segments", "Processed bytes since previous entry", "Totally processed bytes", "All bytes");

                        MD.SetSegmentSize(SegmentSize);
                        if (DigestMode != 0)
                        {
                            if (DigestFile_ != null)
                            {
                                MD.CalcSegmentCount();
                                DigestSegmentSize = MD.DigestSegmentSize;
                                DigestFileSize    = MD.DigestFileSize;
                            }
                            else
                            {
                                DigestSegmentSize = 0;
                                DigestFileSize    = 0;
                            }
                        }
                        if ((DigestMode == 2) || (DigestMode == 3))
                        {
                            if (DigestSegmentSize == SegmentSize)
                            {
                                if (FileSize != DigestFileSize)
                                {
                                    MailSegment.Console_WriteLine("Data file size correction started");
                                    MF.ResizeData(DigestFileSize);
                                    MF.CalcSegmentCount();
                                    FileSize = MF.GetDataSize();
                                    MailSegment.Console_WriteLine("Data file size correction finished");
                                    MailSegment.Console_WriteLine("");
                                }
                                else
                                {
                                    MailSegment.Console_WriteLine("Data file size is correct");
                                    MailSegment.Console_WriteLine("");
                                }
                            }
                        }
                        if ((DigestSegmentSize == SegmentSize) && (FileSize == DigestFileSize))
                        {
                            if (DigestMode != 2)
                            {
                                Stopwatch_ SWProgress = new Stopwatch_();
                                long       SWWorkTime = 0;
                                SWProgress.Reset();

                                int DigestG = 0;
                                int DigestB = 0;

                                long ToLogSize         = 0;
                                bool PrintLastProgress = true;

                                for (int i = 0; i < SegmentCount__; i++)
                                {
                                    ToLogSize += MF.DataGetSize(i);
                                    if (DigestMode == 0)
                                    {
                                        if (DigestFile_ != null)
                                        {
                                            byte[] Temp = MF.DataGet(i);
                                            MD.DataSet(i, Temp, Temp.Length);
                                        }
                                        MF.MapSet(i, 1);
                                        DigestG++;
                                    }
                                    else
                                    {
                                        if ((DigestFile_ != null) && (MailSegment.BinToStr(MD.DataGetDigest(i)) == MailSegment.BinToStr(MF.DataGetDigest(i))))
                                        {
                                            MF.MapSet(i, 1);
                                            DigestG++;
                                        }
                                        else
                                        {
                                            MF.MapSet(i, 0);
                                            DigestB++;
                                        }
                                    }

                                    if (SWWorkTime < SWProgress.Elapsed())
                                    {
                                        while (SWWorkTime < SWProgress.Elapsed())
                                        {
                                            SWWorkTime += 1000L;
                                        }
                                        MailSegment.Console_WriteLine("Segment " + (i + 1) + "/" + SegmentCount__ + " (" + ((i + 1) * 100 / SegmentCount__) + "%)");
                                        MailSegment.Log(TSW.Elapsed().ToString(), MailSegment.LogDiffS(i + 1).ToString(), (i + 1).ToString(), SegmentCount__.ToString(), MailSegment.LogDiffB(ToLogSize).ToString(), ToLogSize.ToString(), FileSize.ToString());
                                        if ((i + 1) == SegmentCount__)
                                        {
                                            PrintLastProgress = false;
                                        }
                                    }
                                }
                                MF.ResizeMap();

                                if (PrintLastProgress)
                                {
                                    MailSegment.Console_WriteLine("Segment " + SegmentCount__ + "/" + SegmentCount__ + " (100%)");
                                    MailSegment.Log(TSW.Elapsed().ToString(), MailSegment.LogDiffS(SegmentCount__).ToString(), SegmentCount__.ToString(), SegmentCount__.ToString(), MailSegment.LogDiffB(ToLogSize).ToString(), ToLogSize.ToString(), FileSize.ToString());
                                }

                                MailSegment.ConsoleLineToLog    = true;
                                MailSegment.ConsoleLineToLogSum = true;
                                MailSegment.Console_WriteLine("");
                                MailSegment.Console_WriteLine("Total segments: " + (DigestG + DigestB));
                                if (DigestMode != 0)
                                {
                                    MailSegment.Console_WriteLine("Good segments: " + DigestG);
                                    MailSegment.Console_WriteLine("Bad segments: " + DigestB);
                                }
                                MailSegment.Console_WriteLine("Total time: " + MailSegment.TimeHMSM(TSW.Elapsed()));
                                MailSegment.ConsoleLineToLogSum = false;
                                MailSegment.ConsoleLineToLog    = false;
                            }
                            else
                            {
                                MailSegment.ConsoleLineToLog    = true;
                                MailSegment.ConsoleLineToLogSum = true;
                                MailSegment.Console_WriteLine("Data file contents are not checked");
                                MailSegment.Console_WriteLine("Total time: " + MailSegment.TimeHMSM(TSW.Elapsed()));
                                MailSegment.ConsoleLineToLogSum = false;
                                MailSegment.ConsoleLineToLog    = false;
                            }
                        }
                        else
                        {
                            MailSegment.ConsoleLineToLog    = true;
                            MailSegment.ConsoleLineToLogSum = true;
                            if (FileSize != DigestFileSize)
                            {
                                MailSegment.Console_WriteLine("Data file size mismatch");
                            }
                            if (DigestSegmentSize != SegmentSize)
                            {
                                MailSegment.Console_WriteLine("Segment size mismatch");
                            }
                            MailSegment.Console_WriteLine("Total time: " + MailSegment.TimeHMSM(TSW.Elapsed()));
                            MailSegment.ConsoleLineToLogSum = false;
                            MailSegment.ConsoleLineToLog    = false;
                        }

                        MD.Close();
                    }
                    else
                    {
                        MailSegment.ConsoleLineToLog    = true;
                        MailSegment.ConsoleLineToLogSum = true;
                        if (DigestMode == 0)
                        {
                            MailSegment.Console_WriteLine("Digest file creation error");
                        }
                        else
                        {
                            MailSegment.Console_WriteLine("Digest file open error");
                        }
                        MailSegment.ConsoleLineToLogSum = false;
                        MailSegment.ConsoleLineToLog    = false;
                    }
                }

                MF.Close();
            }
            else
            {
                MailSegment.ConsoleLineToLog    = true;
                MailSegment.ConsoleLineToLogSum = true;
                MailSegment.Console_WriteLine("Data file open error");
                MailSegment.ConsoleLineToLogSum = false;
                MailSegment.ConsoleLineToLog    = false;
            }
        }
        /// <summary>
        /// File upload action
        /// </summary>
        /// <param name="FileName_"></param>
        /// <param name="FilePath"></param>
        /// <param name="FileMap"></param>
        /// <param name="AccountSrc"></param>
        /// <param name="AccountDst"></param>
        /// <param name="FileSegmentSize"></param>
        /// <param name="SegmentMode"></param>
        /// <param name="SegmentImageSize"></param>
        public static void FileUpload(int FileCount, string[] FileName_, string[] FilePath, string[] FileMap, int[] AccountSrc, int[] AccountDst, int FileSegmentSize, int SegmentMode, int SegmentImageSize)
        {
            // Check account lists
            if (AccountSrc.Length == 2)
            {
                Console_WriteLine("No source accounts");
                return;
            }
            if (AccountDst.Length == 0)
            {
                Console_WriteLine("No destination accounts");
                return;
            }

            // The file name is stored as digest
            int MF_Length = FileCount;

            string[] FileName = new string[MF_Length];
            for (int i = 0; i < MF_Length; i++)
            {
                FileName[i] = Digest(FileName_[i]);
            }

            MailFile[] MF      = new MailFile[MF_Length];
            bool[]     MF_Open = new bool[MF_Length];
            bool       OpenAll = true;

            for (int i = 0; i < MF_Length; i++)
            {
                MF[i]      = new MailFile();
                MF_Open[i] = MF[i].Open(false, true, FilePath[i], FileMap[i]);
                if (!MF_Open[i])
                {
                    OpenAll = false;
                }
            }
            if (OpenAll)
            {
                Log();
                LogReset();
                Log("Time stamp", "Uploaded segments since previous entry", "Totally uploaded segments", "All segments", "Uploaded bytes since previous entry", "Totally uploaded bytes", "All bytes by segment count", "All bytes by file size");
                TSW = new Stopwatch_();
                KBPSReset();
                bool FileNotBlank = false;
                for (int i_ = 0; i_ < FileCount; i_++)
                {
                    MF[i_].MapChange(1, 2);
                    MF[i_].SetSegmentSize(FileSegmentSize);
                    if (MF[i_].CalcSegmentCount() > 0)
                    {
                        FileNotBlank = true;
                    }
                }
                if (FileNotBlank)
                {
                    List <MailSendParam> MailSendParam_ = new List <MailSendParam>();

                    using (CancellationTokenSource cancel = new CancellationTokenSource())
                    {
                        // Create SMTP client array (not create SMTP connections)
                        SmtpClient[,] SmtpClient_ = new SmtpClient[AccountSrc.Length, ThreadsUpload];
                        for (int i = 0; i < AccountSrc.Length; i++)
                        {
                            for (int ii = 0; ii < ThreadsUpload; ii++)
                            {
                                SmtpClient_[i, ii] = null;
                            }
                        }

                        int[] FileSegmentProgress = new int[MF_Length];
                        int[] FileSegmentCount    = new int[MF_Length];
                        int[] FileSegmentToDo     = new int[MF_Length];
                        for (int i_ = 0; i_ < MF_Length; i_++)
                        {
                            FileSegmentProgress[i_] = 0;
                        }

                        // Upload failure counter
                        int UploadFailureCounter = 0;

                        // Current upload group
                        int UploadGroup = 0;

                        // Map of upload account counters
                        List <int> UploadGroupN = new List <int>();

                        // Number of account which will be aggigned to each segment to send, for each group separatelly
                        for (int i = 0; i < (AccountSrc.Length - 1); i++)
                        {
                            if (AccountSrc[i] < 0)
                            {
                                UploadGroupN.Add(-1);
                            }
                            else
                            {
                                if (UploadGroupN[UploadGroupN.Count - 1] < 0)
                                {
                                    UploadGroupN[UploadGroupN.Count - 1] = i;
                                }
                            }
                        }

                        for (int FileItemI = 0; FileItemI < MF_Length; FileItemI++)
                        {
                            if (MF[FileItemI].CalcSegmentCount() > 0)
                            {
                                FileSegmentCount[FileItemI] = MF[FileItemI].GetSegmentCount();

                                MF[FileItemI].MapCalcStats();
                                FileSegmentToDo[FileItemI] = MF[FileItemI].MapCount(0);

                                // The loop iterates over all file segments, but also iterates while there are some segments to upload
                                int FileSegmentNum      = 0;
                                int FileSegmentNumDelta = 1;
                                if (SegmentMode > 9)
                                {
                                    FileSegmentNum      = FileSegmentCount[FileItemI] - 1;
                                    FileSegmentNumDelta = -1;
                                }
                                int UploadCounter = 0;

                                for (int FileSegmentNum_ = 0; FileSegmentNum_ < FileSegmentCount[FileItemI]; FileSegmentNum_++)
                                {
                                    // Creating console information prefix
                                    string ConsoleInfo = CreateConsoleInfoU(FileItemI, FileSegmentNum, FileSegmentCount[FileItemI]);

                                    // Upload only this segments, which must be uploaded based on map file
                                    if (MF[FileItemI].MapGet(FileSegmentNum) == 0)
                                    {
                                        byte[] SegmentBuf = MF[FileItemI].DataGet(FileSegmentNum);

                                        // Create a object, which keeps all needed data during whole sending process of current segment
                                        MailSendParam MailSendParam__ = new MailSendParam();
                                        MailSendParam__.FileI           = FileItemI;
                                        MailSendParam__.SegmentBuf      = SegmentBuf;
                                        MailSendParam__.FileSegmentSize = SegmentBuf.Length;
                                        MailSendParam__.FileSegmentNum  = FileSegmentNum;
                                        MailSendParam__.AccountSrcG     = UploadGroup;
                                        MailSendParam__.AccountSrcN     = UploadGroupN[UploadGroup];
                                        MailSendParam__.AccountSrc      = AccountSrc[MailSendParam__.AccountSrcN];
                                        MailSendParam__.SmtpClient_     = SmtpClient_;
                                        MailSendParam__.SmtpClientSlot  = -1;
                                        MailSendParam_.Add(MailSendParam__);

                                        // Set the next account to assign to next segment
                                        UploadGroupN[UploadGroup]++;
                                        if (AccountSrc[UploadGroupN[UploadGroup]] < 0)
                                        {
                                            UploadGroupN[UploadGroup]--;
                                            while (AccountSrc[UploadGroupN[UploadGroup]] >= 0)
                                            {
                                                UploadGroupN[UploadGroup]--;
                                            }
                                            UploadGroupN[UploadGroup]++;
                                        }
                                        Console_WriteLine(ConsoleInfo + " - to upload");
                                    }
                                    else
                                    {
                                        Console_WriteLine(ConsoleInfo + " - not to upload");
                                    }

                                    bool PerformUploadCondition = false;
                                    if (MailSendParam_.Count >= ThreadsUpload)
                                    {
                                        PerformUploadCondition = true;
                                    }
                                    if (MailSendParam_.Count > 0)
                                    {
                                        UploadCounter++;
                                        if (FileSegmentNum_ == (FileSegmentCount[FileItemI] - 1))
                                        {
                                            PerformUploadCondition = true;
                                        }
                                        if (UploadCounter >= ThreadsUpload)
                                        {
                                            PerformUploadCondition = true;
                                        }
                                    }
                                    else
                                    {
                                        UploadCounter = 0;
                                    }

                                    // If the number of segments is at least the same as number of threads, there will be attemped to send,
                                    // if none of segments are sent, the attemp will be repeated immediately
                                    while (PerformUploadCondition)
                                    {
                                        if (FileUploadMsg(AccountSrc, AccountDst, MailSendParam_, ref MF, FileName, ref FileSegmentProgress, FileSegmentCount, FileSegmentToDo, FileSegmentSize, SegmentMode, SegmentImageSize, cancel))
                                        {
                                            UploadFailureCounter = 0;
                                        }
                                        else
                                        {
                                            UploadFailureCounter++;
                                        }

                                        // If upload failed several times at a row, the group must be changed
                                        if (UploadFailureCounter >= UploadGroupChange)
                                        {
                                            UploadFailureCounter = 0;

                                            // Close all opened connections
                                            Console_WriteLine("Disconnecting existing connections");
                                            for (int i = 0; i < AccountSrc.Length; i++)
                                            {
                                                for (int ii = 0; ii < ThreadsUpload; ii++)
                                                {
                                                    if (SmtpClient_[i, ii] != null)
                                                    {
                                                        if (SmtpClient_[i, ii].IsConnected)
                                                        {
                                                            SmtpClient_[i, ii].Disconnect(true, cancel.Token);
                                                        }
                                                        SmtpClient_[i, ii].Dispose();
                                                    }
                                                }
                                            }

                                            // Change group
                                            Console_Write("Changing account group from " + UploadGroup);
                                            UploadGroup++;
                                            if (UploadGroup >= UploadGroupN.Count)
                                            {
                                                UploadGroup = 0;
                                            }
                                            Console_Write(" to " + UploadGroup);

                                            // Assign accounts from next group
                                            for (int i = 0; i < MailSendParam_.Count; i++)
                                            {
                                                MailSendParam_[i].AccountSrcG = UploadGroup;
                                                MailSendParam_[i].AccountSrcN = UploadGroupN[UploadGroup];
                                                MailSendParam_[i].AccountSrc  = AccountSrc[MailSendParam_[i].AccountSrcN];

                                                // Set the next account to assign to next segment
                                                UploadGroupN[UploadGroup]++;
                                                if (AccountSrc[UploadGroupN[UploadGroup]] < 0)
                                                {
                                                    UploadGroupN[UploadGroup]--;
                                                    while (AccountSrc[UploadGroupN[UploadGroup]] >= 0)
                                                    {
                                                        UploadGroupN[UploadGroup]--;
                                                    }
                                                    UploadGroupN[UploadGroup]++;
                                                }
                                            }
                                        }

                                        UploadCounter          = 0;
                                        PerformUploadCondition = false;
                                        if (MailSendParam_.Count > 0)
                                        {
                                            PerformUploadCondition = true;
                                        }
                                    }

                                    FileSegmentNum += FileSegmentNumDelta;
                                }
                            }
                        }

                        // Closing all opened connections
                        Console_WriteLine("Disconnecting existing connections");
                        for (int i = 0; i < AccountSrc.Length; i++)
                        {
                            for (int ii = 0; ii < ThreadsUpload; ii++)
                            {
                                try
                                {
                                    if (SmtpClient_[i, ii] != null)
                                    {
                                        if (SmtpClient_[i, ii].IsConnected)
                                        {
                                            SmtpClient_[i, ii].Disconnect(true, cancel.Token);
                                        }
                                        SmtpClient_[i, ii].Dispose();
                                    }
                                }
                                catch
                                {
                                }
                            }
                        }
                        Console_WriteLine("Disconnected");
                    }
                    ConsoleLineToLog    = true;
                    ConsoleLineToLogSum = true;
                    Console_WriteLine("");
                    for (int i_ = 0; i_ < FileCount; i_++)
                    {
                        MF[i_].MapCalcStats();
                        Console_WriteLine("Item " + (i_ + 1).ToString() + ":");
                        Console_WriteLine(" Item name: " + FileName_[i_]);
                        Console_WriteLine(" Total segments: " + MF[i_].GetSegmentCount().ToString());
                        Console_WriteLine(" Segments uploaded previously: " + MF[i_].MapCount(2).ToString());
                        Console_WriteLine(" Segments uploaded now: " + MF[i_].MapCount(1).ToString());
                    }
                    Console_WriteLine("Uploaded bytes: " + KBPS_B());
                    Console_WriteLine("Upload time: " + KBPS_T());
                    Console_WriteLine("Average upload speed: " + KBPS());
                    Console_WriteLine("Total time: " + TimeHMSM(TSW.Elapsed()));
                    ConsoleLineToLogSum = false;
                    ConsoleLineToLog    = false;
                }
                else
                {
                    ConsoleLineToLog    = true;
                    ConsoleLineToLogSum = true;
                    Console_WriteLine("");
                    Console_WriteLine("Every file is blank");
                    ConsoleLineToLogSum = false;
                    ConsoleLineToLog    = false;
                }
                for (int i_ = 0; i_ < FileCount; i_++)
                {
                    MF[i_].Close();
                }
            }
            else
            {
                ConsoleLineToLog    = true;
                ConsoleLineToLogSum = true;
                Console_WriteLine("");
                for (int i_ = 0; i_ < FileCount; i_++)
                {
                    if (!MF_Open[i_])
                    {
                        Console_WriteLine("Item " + (i_ + 1).ToString() + " - file open error: " + MF[i_].OpenError);
                    }
                }
                ConsoleLineToLogSum = false;
                ConsoleLineToLog    = false;
                return;
            }
        }
        public void CreateFile(string FileNameSrc, string FileNameDst, int SegmentSize, int CreateStats, int CreatePeriod)
        {
            string FileNameSta = FileNameDst;

            MailFile FileSrc = new MailFile();
            MailFile FileDst = new MailFile();

            if (FileSrc.Open(false, true, FileNameSrc, null))
            {
                Stopwatch_ TSW = new Stopwatch_();

                FileSrc.SetSegmentSize(SegmentSize);
                FileSrc.CalcSegmentCount();
                long FileSize    = FileSrc.GetDataSize();
                bool DstFileGood = false;
                if (FileNameDst != null)
                {
                    if (FileDst.Open(false, false, FileNameDst, null))
                    {
                        DstFileGood = true;
                    }
                    else
                    {
                        FileNameSta = FileNameSrc;
                        MailSegment.ConsoleLineToLog    = true;
                        MailSegment.ConsoleLineToLogSum = true;
                        MailSegment.Console_WriteLine("");
                        MailSegment.Console_WriteLine("Destination file create error: " + FileDst.OpenError);
                        MailSegment.ConsoleLineToLogSum = false;
                        MailSegment.ConsoleLineToLog    = false;
                    }
                }


                if (DstFileGood || (CreateStats > 0))
                {
                    ulong[] Stats = new ulong[256];
                    for (int i = 0; i < 256; i++)
                    {
                        Stats[i] = 0;
                    }

                    MailSegment.Console_WriteLine("");
                    Stopwatch_ SW = new Stopwatch_();
                    MailSegment.Log();
                    MailSegment.LogReset();
                    MailSegment.Log("Time stamp", "Processed segments since previous entry", "Totally processed segments", "All segments", "Processed bytes since previous entry", "Totally processed bytes", "All bytes");

                    long SWWorkTime = 0;
                    if (DstFileGood)
                    {
                        FileDst.SetSegmentSize(SegmentSize);
                        FileDst.CalcSegmentCount();
                    }
                    long ToLogSize = 0;


                    int  SegmentCount__    = FileSrc.GetSegmentCount();
                    bool PrintLastProgress = true;
                    for (int i = 0; i < SegmentCount__; i++)
                    {
                        byte[] Temp = FileSrc.DataGet(i);
                        if (DstFileGood)
                        {
                            FileDst.DataSet(i, Temp, Temp.Length);
                        }
                        for (int ii = Temp.Length - 1; ii >= 0; ii--)
                        {
                            Stats[Temp[ii]]++;
                        }
                        ToLogSize += Temp.LongLength;

                        if (SWWorkTime < SW.Elapsed())
                        {
                            while (SWWorkTime < SW.Elapsed())
                            {
                                SWWorkTime += 1000L;
                            }
                            MailSegment.Console_WriteLine("Segment " + (i + 1) + "/" + SegmentCount__ + " (" + ((i + 1) * 100 / SegmentCount__) + "%)");
                            MailSegment.Log(SW.Elapsed().ToString(), MailSegment.LogDiffS(i + 1).ToString(), (i + 1).ToString(), SegmentCount__.ToString(), MailSegment.LogDiffB(ToLogSize).ToString(), ToLogSize.ToString(), FileSize.ToString());
                            if ((i + 1) == SegmentCount__)
                            {
                                PrintLastProgress = false;
                            }
                        }
                    }
                    if (PrintLastProgress)
                    {
                        MailSegment.Console_WriteLine("Segment " + SegmentCount__ + "/" + SegmentCount__ + " (100%)");
                        MailSegment.Log(SW.Elapsed().ToString(), MailSegment.LogDiffS(SegmentCount__).ToString(), SegmentCount__.ToString(), SegmentCount__.ToString(), MailSegment.LogDiffB(ToLogSize).ToString(), ToLogSize.ToString(), FileSize.ToString());
                    }

                    if (DstFileGood)
                    {
                        FileDst.Close();
                    }

                    MailSegment.ConsoleLineToLog    = true;
                    MailSegment.ConsoleLineToLogSum = true;
                    MailSegment.Console_WriteLine("");
                    MailSegment.Console_WriteLine("File created in time: " + MailSegment.TimeHMSM(SW.Elapsed()));
                    if (CreateStats > 0)
                    {
                        MailSegment.Console_WriteLine("");
                        DisplayStats("File distribution", Stats, CreateStats);
                    }
                    MailSegment.ConsoleLineToLogSum = false;
                    MailSegment.ConsoleLineToLog    = false;
                }

                FileSrc.Close();

                if (CreatePeriod > 0)
                {
                    MailSegment.Console_WriteLine("");
                    MailSegment.Console_WriteLine("Searching for sequence period");

                    MailFile FileSta = new MailFile();
                    if (FileSta.Open(false, true, FileNameSta, null))
                    {
                        FileSta.DataValueFileOpen();

                        long   PeriodBufferSize = SegmentSize;
                        byte[] PeriodArray0     = new byte[PeriodBufferSize];
                        byte[] PeriodArray1     = new byte[PeriodBufferSize];

                        if (PeriodBufferSize > FileSize)
                        {
                            PeriodBufferSize = (int)FileSize;
                        }

                        long PeriodSize = 0;
                        int  PeriodChunks;
                        int  PeriodChunkOffset;
                        long PeriodChunkSize;
                        long PeriodChunkSize0;
                        long PeriodFilePos;

                        Stopwatch_ SW__ = new Stopwatch_();
                        SW__.Reset();

                        ulong[] PeriodStats = new ulong[256];
                        for (int i = 0; i < 256; i++)
                        {
                            PeriodStats[i] = 0;
                        }

                        long WorkTime = 0;

                        MailSegment.Log();
                        MailSegment.LogReset();
                        MailSegment.Log("Time stamp", "Current period length", "File length", "Current period occurence", "All period occurences");

                        for (long i = 1; i < FileSize; i++)
                        {
                            FileSta.DataGetBytes(i - 1, 1, PeriodArray0);
                            PeriodStats[PeriodArray0[0]]++;

                            bool IsPeriodical    = true;
                            bool PeriodicalPrint = true;

                            PeriodChunkSize  = PeriodBufferSize;
                            PeriodChunkSize0 = i;
                            PeriodChunks     = (int)(i / PeriodBufferSize);
                            if ((i % PeriodBufferSize) > 0)
                            {
                                PeriodChunks++;
                            }

                            long PeriodCount = (FileSize / i);
                            if ((FileSize % i) > 0)
                            {
                                PeriodCount++;
                            }

                            PeriodChunkOffset = 0;
                            for (int ii = 0; ii < PeriodChunks; ii++)
                            {
                                PeriodFilePos = PeriodChunkOffset;

                                if (PeriodChunkSize > PeriodChunkSize0)
                                {
                                    PeriodChunkSize = PeriodChunkSize0;
                                }

                                // Read the first period occurence and treat as pattern
                                FileSta.DataGetBytes(PeriodFilePos, PeriodChunkSize, PeriodArray0);

                                int PeriodChunkSize__ = 0;
                                for (long iii = (PeriodCount - 2); iii >= 0; iii--)
                                {
                                    PeriodFilePos    += i;
                                    PeriodChunkSize__ = (int)PeriodChunkSize;
                                    if (iii == 0)
                                    {
                                        int FileRemain = (int)(FileSize - PeriodFilePos);
                                        if (PeriodChunkSize__ > FileRemain)
                                        {
                                            PeriodChunkSize__ = FileRemain;
                                        }
                                    }

                                    // Read the period occurence other than first and compare with pattern,
                                    // if doest match the pattern, the reading and comparing will be broken
                                    if (PeriodChunkSize__ > 0)
                                    {
                                        FileSta.DataGetBytes(PeriodFilePos, PeriodChunkSize, PeriodArray1);

                                        for (int iiii = (PeriodChunkSize__ - 1); iiii >= 0; iiii--)
                                        {
                                            if (PeriodArray0[iiii] != PeriodArray1[iiii])
                                            {
                                                IsPeriodical = false;

                                                // Break all check iteration if data has no period by length given by i
                                                ii  = PeriodChunks;
                                                iii = (-1);
                                                break;
                                            }
                                        }
                                    }

                                    if (WorkTime < SW__.Elapsed())
                                    {
                                        while (WorkTime < SW__.Elapsed())
                                        {
                                            WorkTime += 1000L;
                                        }
                                        MailSegment.Console_WriteLine("Period " + i + "/" + FileSize + " (" + (FileSize > 0 ? (i * 100 / FileSize) : 0) + "%); occurence " + (PeriodCount - iii - 1) + "/" + PeriodCount + " (" + (PeriodCount > 0 ? (((PeriodCount - iii - 1) * 100) / PeriodCount) : 0) + "%)");
                                        MailSegment.Log(SW__.Elapsed().ToString(), i.ToString(), FileSize.ToString(), (PeriodCount - iii - 1).ToString(), PeriodCount.ToString());
                                        if (((PeriodCount - iii - 1) == PeriodCount))
                                        {
                                            PeriodicalPrint = false;
                                        }
                                    }
                                }
                                PeriodChunkOffset += (int)PeriodChunkSize;

                                PeriodChunkSize0 -= PeriodChunkSize;
                            }

                            if (IsPeriodical && PeriodicalPrint)
                            {
                                MailSegment.Console_WriteLine("Period " + i + "/" + FileSize + " (" + (FileSize > 0 ? (i * 100 / FileSize) : 0) + "%); occurence " + PeriodCount + "/" + PeriodCount + " (100%)");
                                MailSegment.Log(SW__.Elapsed().ToString(), i.ToString(), FileSize.ToString(), PeriodCount.ToString(), PeriodCount.ToString());
                                PeriodSize = i;
                                break;
                            }
                        }
                        if (PeriodSize == 0)
                        {
                            MailSegment.Console_WriteLine("Period " + FileSize + "/" + FileSize + " (100%); occurence " + "1/1" + " (100%)");
                            MailSegment.Log(SW__.Elapsed().ToString(), FileSize.ToString(), FileSize.ToString(), "1", "1");
                        }

                        FileSta.DataValueFileClose();
                        FileSta.Close();

                        MailSegment.ConsoleLineToLog    = true;
                        MailSegment.ConsoleLineToLogSum = true;
                        MailSegment.Console_WriteLine("");
                        if (PeriodSize > 0)
                        {
                            MailSegment.Console_WriteLine("Sequence period length: " + PeriodSize);
                            MailSegment.Console_WriteLine("Period search time: " + MailSegment.TimeHMSM(SW__.Elapsed()));
                            MailSegment.Console_WriteLine("");
                            DisplayStats("Sequence period distribution", PeriodStats, CreatePeriod);
                        }
                        else
                        {
                            MailSegment.Console_WriteLine("Sequence has no period");
                            MailSegment.Console_WriteLine("Period search time: " + MailSegment.TimeHMSM(SW__.Elapsed()));
                        }
                        MailSegment.ConsoleLineToLogSum = false;
                        MailSegment.ConsoleLineToLog    = false;
                    }
                    else
                    {
                        MailSegment.ConsoleLineToLog    = true;
                        MailSegment.ConsoleLineToLogSum = true;
                        MailSegment.Console_WriteLine("Period search error: " + FileSta.OpenError);
                        MailSegment.ConsoleLineToLogSum = false;
                        MailSegment.ConsoleLineToLog    = false;
                    }
                }

                MailSegment.ConsoleLineToLog    = true;
                MailSegment.ConsoleLineToLogSum = true;
                MailSegment.Console_WriteLine("");
                MailSegment.Console_WriteLine("Total time: " + MailSegment.TimeHMSM(TSW.Elapsed()));
                MailSegment.ConsoleLineToLogSum = false;
                MailSegment.ConsoleLineToLog    = false;
            }
            else
            {
                MailSegment.ConsoleLineToLog    = true;
                MailSegment.ConsoleLineToLogSum = true;
                MailSegment.Console_WriteLine("");
                MailSegment.Console_WriteLine("Source file open error: " + FileSrc.OpenError);
                MailSegment.ConsoleLineToLogSum = false;
                MailSegment.ConsoleLineToLog    = false;
            }
        }
        /// <summary>
        /// File upload packet of segments to upload in separated threads
        /// </summary>
        /// <param name="AccountSrc"></param>
        /// <param name="AccountDst"></param>
        /// <param name="MailSendParam_"></param>
        /// <param name="MF"></param>
        /// <param name="FileName"></param>
        /// <param name="FileSegmentProgress"></param>
        /// <param name="FileSegmentCount"></param>
        /// <param name="FileSegmentToDo"></param>
        /// <param name="FileSegmentSize"></param>
        /// <param name="SegmentMode"></param>
        /// <param name="SegmentImageSize"></param>
        /// <param name="cancel"></param>
        public static bool FileUploadMsg(int[] AccountSrc, int[] AccountDst, List <MailSendParam> MailSendParam_, ref MailFile[] MF, string[] FileName, ref int[] FileSegmentProgress, int[] FileSegmentCount, int[] FileSegmentToDo, int FileSegmentSize, int SegmentMode, int SegmentImageSize, CancellationTokenSource cancel)
        {
            Stopwatch_ SW = new Stopwatch_();

            // Assign slots to each used account to reuse as many of existing connection as possible
            for (int i = 0; i < AccountSrc.Length; i++)
            {
                int           SmtpClientSlot     = 0;
                HashSet <int> SmtpClientSlotUsed = new HashSet <int>();
                SmtpClientSlotUsed.Clear();
                for (int ii = 0; ii < MailSendParam_.Count; ii++)
                {
                    if (MailSendParam_[ii].AccountSrcN == i)
                    {
                        SmtpClientSlotUsed.Add(MailSendParam_[ii].SmtpClientSlot);
                    }
                }
                while (SmtpClientSlotUsed.Contains(SmtpClientSlot))
                {
                    SmtpClientSlot++;
                }
                for (int ii = 0; ii < MailSendParam_.Count; ii++)
                {
                    if (MailSendParam_[ii].AccountSrcN == i)
                    {
                        if (MailSendParam_[ii].SmtpClientSlot < 0)
                        {
                            MailSendParam_[ii].SmtpClientSlot = SmtpClientSlot;
                            SmtpClientSlot++;
                        }
                    }
                }
            }

            // Size of segment packet
            int TotalSize = 0;

            int I = 0;

            // If number of sending threads is 1, there is not necessary to create separate thread
            if (MailSendParam_.Count == 1)
            {
                MailSendParam MailSendParam___ = MailSendParam_[0];
                MailSendParam___.Idx      = I;
                MailSendParam___.ThreadNo = 1;
                MailSend(ref MailSendParam___, FileName, FileSegmentSize, FileSegmentCount, MailAccountList, AccountDst, SegmentMode, SegmentImageSize, cancel);
            }
            else
            {
                List <Thread> Thr = new List <Thread>();
                while ((I < MailSendParam_.Count) && (I < ThreadsUpload))
                {
                    MailSendParam MailSendParam___ = MailSendParam_[I];
                    MailSendParam___.Idx      = I;
                    MailSendParam___.ThreadNo = Thr.Count + 1;
                    Thread Thr_ = new Thread(() => MailSend(ref MailSendParam___, FileName, FileSegmentSize, FileSegmentCount, MailAccountList, AccountDst, SegmentMode, SegmentImageSize, cancel));
                    Thr_.Start();
                    Thr.Add(Thr_);
                    I++;
                }
                foreach (Thread Thr_ in Thr)
                {
                    Thr_.Join();
                }
                I--;
            }

            // Encounting data size and removing segments from packet, which are sent correctly,
            // changing account number to next number in current group for not sent segments
            bool UploadedSomething = false;

            while (I >= 0)
            {
                if (MailSendParam_[I].Good)
                {
                    UploadedSomething = true;
                    MF[MailSendParam_[I].FileI].MapSet(MailSendParam_[I].FileSegmentNum, 1);
                    FileSegmentProgress[MailSendParam_[I].FileI]++;
                    TotalSize += MailSendParam_[I].FileSegmentSize;
                    MailSendParam_.RemoveAt(I);
                }
                else
                {
                    MF[MailSendParam_[I].FileI].MapSet(MailSendParam_[I].FileSegmentNum, 0);
                    MailSendParam_[I].AccountSrcN++;
                    if (AccountSrc[MailSendParam_[I].AccountSrcN] < 0)
                    {
                        MailSendParam_[I].AccountSrcN--;
                        while (AccountSrc[MailSendParam_[I].AccountSrcN] >= 0)
                        {
                            MailSendParam_[I].AccountSrcN--;
                        }
                        MailSendParam_[I].AccountSrcN++;
                    }
                    MailSendParam_[I].AccountSrc     = AccountSrc[MailSendParam_[I].AccountSrcN];
                    MailSendParam_[I].SmtpClientSlot = -1;
                }
                I--;
            }

            // Print progress after packet send attemp and transfer of the packet segments
            long GetDataSizeSum         = 0;
            long GetDataSizeSegSum      = 0;
            int  FileSegmentProgressSum = 0;
            int  FileSegmentToDoSum     = 0;

            for (int i_ = 0; i_ < MF.Length; i_++)
            {
                GetDataSizeSum         += MF[i_].GetDataSize();
                GetDataSizeSegSum      += MF[i_].GetDataSizeSeg();
                FileSegmentProgressSum += FileSegmentProgress[i_];
                FileSegmentToDoSum     += FileSegmentToDo[i_];
            }
            Console_WriteLine("Upload progress: " + FileSegmentProgressSum + "/" + FileSegmentToDoSum);
            Console_WriteLine("Upload speed: " + KBPS(TotalSize, SW.Elapsed()));
            Log(TSW.Elapsed().ToString(), LogDiffS(FileSegmentProgressSum).ToString(), FileSegmentProgressSum.ToString(), FileSegmentToDoSum.ToString(), LogDiffB(KBPS_Bytes).ToString(), KBPS_B(), GetDataSizeSum.ToString(), GetDataSizeSegSum.ToString());

            // If uploaded something, return true, otherwise return false
            if (UploadedSomething)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }