Пример #1
0
        public Archiver(string outputFile, int fileAlignment)
        {
            archiveFile      = outputFile;
            newWriteSignal   = new Semaphore(0, Int32.MaxValue);
            exitEvent        = new ManualResetEvent(false);
            writeData        = new List <byte[]>(4000);
            outstandingReads = new GT2.RefCounter();
            wasFinished      = 0;
            writeThread      = new Thread(new ParameterizedThreadStart(WriteThread));
            writeThread.SetApartmentState(ApartmentState.STA);
#if DEBUG
            writeThread.Name = "Archiver Write Thread";
#endif
            writeThread.Start(--fileAlignment);
        }
Пример #2
0
        private void WriteThread(object o)
        {
#if TEST_AS_FRENCH
            Tools.SetThreadToFrench();
#endif
            int            fileAlignment      = (int)o;
            string         idxFile            = Path.ChangeExtension(archiveFile, ".idx");
            MemoryStream   memoryIdx          = new MemoryStream(4000 * 4);
            int            bytesWrittenSoFar  = 0;
            int            writeIndexSoFar    = 0;
            GT2.RefCounter completeWriteCount = new GT2.RefCounter();
            FileStream     archive            = new FileStream(archiveFile, FileMode.Create, FileAccess.Write, FileShare.None, UInt16.MaxValue, true);
            using (BinaryWriter idxWriter = new BinaryWriter(memoryIdx))
            {
                WaitHandle[] waitables = new WaitHandle[2] {
                    newWriteSignal, exitEvent
                };
                bool exitLoop = false;
                while (!exitLoop)
                {
                    int signalled = WaitHandle.WaitAny(waitables, Timeout.Infinite, false);
                    if (signalled == 0)
                    {
                        int count;
                        lock (writeData)
                        {
                            count = writeData.Count;
                        }
                        while (writeIndexSoFar < count)
                        {
                            // the reads can complete out of order, but we need to write the archive file
                            // in order. So if the alert we got wasn't for the next file, go back and wait
                            // this is also why it's a while loop, so that when we eventually get the signal
                            // for the next file, we can process the other ones we've aleady seen the signal for
                            byte[] nextData = writeData[writeIndexSoFar];
                            if (nextData != null)
                            {
                                WriteState ws                  = new WriteState(archive, completeWriteCount);
                                int        dataLen             = nextData.Length;
                                int        lengthWithAlignment = dataLen;
                                int        padAmount           = 0;
                                if (fileAlignment > 0)
                                {
                                    lengthWithAlignment = (lengthWithAlignment + fileAlignment) & ~fileAlignment;
                                    padAmount           = lengthWithAlignment - dataLen;
                                    Array.Resize(ref nextData, lengthWithAlignment);
                                }
                                archive.Position = bytesWrittenSoFar;
                                archive.BeginWrite(nextData, 0, lengthWithAlignment, new AsyncCallback(WriteComplete), ws);

                                idxWriter.Write(bytesWrittenSoFar | padAmount);
                                bytesWrittenSoFar += lengthWithAlignment;
                                ++writeIndexSoFar;
                            }
                        }
                    }
                    else
                    {
                        exitLoop = true;
                    }
                    Debug.Assert(signalled >= 0 && signalled <= 1, "Archive write thread got a signal other than 0 or 1!");
                }
            }
            bool cancelled = (Thread.VolatileRead(ref wasFinished) == 0);
            if (!cancelled)
            {
                using (BinaryWriter idxFileWriter = new BinaryWriter(new FileStream(idxFile, FileMode.Create, FileAccess.Write, FileShare.None)))
                {
                    // how many
                    idxFileWriter.Write(writeIndexSoFar);
                    // the offsets
                    idxFileWriter.Write(memoryIdx.ToArray());
                    // file size
                    idxFileWriter.Write(bytesWrittenSoFar);
                }
            }
            while (!completeWriteCount.HasReached(writeIndexSoFar))
            {
                Thread.Sleep(100);
            }
            archive.Dispose();
            if (cancelled)
            {
                File.Delete(archiveFile);
            }
        }
Пример #3
0
 public WriteState(FileStream file, GT2.RefCounter count)
 {
     refCount = count;
     archive  = file;
 }