Example #1
0
        /// <summary>
        /// 写入数据
        /// </summary>
        private unsafe void write()
        {
            FileBuffers buffer = default(FileBuffers);
            int         bigBufferSize;
            bool        isCopyBuffer, isNeedDispose = false;

            try
            {
                bufferPool.Get(ref buffer.Buffer);
                DateTime callbackTime = Date.NowTime.Now;
                fixed(byte *bufferFixed = buffer.Buffer.Buffer)
                {
                    byte *bufferStart = bufferFixed + buffer.Buffer.StartIndex;

GETQUEUE:
                    //Thread.Sleep(0);
                    Buffer head = bufferQueue.GetClear();

                    if (head != null)
                    {
                        int    index = PacketHeaderSize, dataCount = 0;
                        Buffer data = head;
                        do
                        {
                            data.Identity = identity;
                            int dataSize = data.Data.GetSerializeBufferSize(out isCopyBuffer);
CHECKSIZE:
                            if (dataSize + index <= buffer.Buffer.Length)
                            {
                                data.Data.SerializeBuffer(bufferStart + index);
                                if (isCopyBuffer)
                                {
                                    data.Data.SerializeBuffer(ref buffer.Buffer, index);
                                }
                                index += dataSize;
                                ++dataCount;
                                ++identity;
                            }
                            else if (dataCount != 0)
                            {
                                *(int *)bufferStart = index - PacketHeaderSize;
                                *(int *)(bufferStart + sizeof(int)) = dataCount;
                                write(ref buffer, bufferStart);
                                index     = PacketHeaderSize;
                                dataCount = 0;
                                goto CHECKSIZE;
                            }
                            else
                            {
                                #region 写入大数据
                                ++identity;
                                if (bigBuffer.Length < (bigBufferSize = dataSize + PacketHeaderSize))
                                {
                                    bigBuffer = new byte[Math.Max(bigBufferSize, bigBuffer.Length << 1)];
                                    fixed(byte *bigBufferFixed = bigBuffer)
                                    {
                                        *(int *)bigBufferFixed = dataSize;
                                        *(int *)(bigBufferFixed + sizeof(int)) = 1;
                                        data.Data.SerializeBuffer(bigBufferFixed + PacketHeaderSize, bigBuffer);
                                        if (dataSize >= Config.MinCompressSize)
                                        {
                                            if (AutoCSer.IO.Compression.DeflateCompressor.Get(bigBuffer, PacketHeaderSize, dataSize, ref buffer.CompressionBuffer, ref buffer.CompressionData, PacketHeaderSize + sizeof(int), PacketHeaderSize + sizeof(int)))
                                            {
                                                writeCompression(ref buffer.CompressionData, bigBufferFixed);
                                                buffer.CompressionBuffer.TryFree();
                                                goto CHECKIDENTITY;
                                            }
                                            buffer.CompressionBuffer.TryFree();
                                        }
                                    }
                                    dataFileStream.Write(bigBuffer, 0, bigBufferSize);
                                    dataFileLength += bigBufferSize;
                                    setIndex();
                                    #endregion
                            }
CHECKIDENTITY:
                            if (((uint)identity & (DataCountPerFile - 1)) == 0)
                            {
                                #region 切换数据文件
                                if (dataCount != 0)
                                {
                                    *(int *)bufferStart = index - PacketHeaderSize;
                                    *(int *)(bufferStart + sizeof(int)) = dataCount;
                                    write(ref buffer, bufferStart);
                                    index     = PacketHeaderSize;
                                    dataCount = 0;
                                }
                                dataFileStream.Flush(true);
                                dataFileStream.Dispose();
                                dataFileStream = null;
                                writeState(ref buffer.Buffer);
                                writeIndex(ref buffer.Buffer);

                                FileInfo dataFileInfo = new FileInfo(dataFileName);
                                if (dataFileInfo.Exists)
                                {
                                    if (dataFileInfo.Length == 0)
                                    {
                                        dataFileInfo.Delete();
                                    }
                                    else
                                    {
                                        AutoCSer.IO.File.MoveBak(dataFileInfo.FullName);
                                    }
                                }
                                dataFileStream = new FileStream(dataFileInfo.FullName, FileMode.CreateNew, FileAccess.Write, FileShare.Read, bufferPool.Size, FileOptions.None);
                                dataFileLength = 0;
                                #endregion
                            }
                            else if (dataCount == MaxPacketCount)
                            {
                                *(int *)bufferStart = index - PacketHeaderSize;
                                *(int *)(bufferStart + sizeof(int)) = MaxPacketCount;
                                write(ref buffer, bufferStart);
                                index     = PacketHeaderSize;
                                dataCount = 0;
                            }

                            if (data.LinkNext == null)
                            {
                                if (bufferQueue.IsEmpty || callbackTime != Date.NowTime.Now)
                                    break; }
                                data.LinkNext = bufferQueue.GetClear();
                            }
                            data = data.LinkNext;
                        }while (true);

                        if (dataCount != 0)
                        {
                            *(int *)bufferStart = index - PacketHeaderSize;
                            *(int *)(bufferStart + sizeof(int)) = dataCount;
                            write(ref buffer, bufferStart);
                        }
                        dataFileStream.Flush(true);
                        writeState(ref buffer.Buffer);
                        if (ReadCount == 0)
                        {
                            do
                            {
                                head.Callback(ref head);
                            }while (head != null);
                        }
                        else
                        {
                            new QueueTaskThread.Append(head).AddQueueTaskLinkThread();
                        }
                        callbackTime = Date.NowTime.Now;
                    }
                    if (this.isNeedDispose != 0)
                    {
                        isNeedDispose = true;
                        return;
                    }
                    if (!bufferQueue.IsEmpty)
                    {
                        goto GETQUEUE;
                    }
                    Interlocked.Exchange(ref isWrite, 0);
                    if (!bufferQueue.IsEmpty && Interlocked.CompareExchange(ref isWrite, 1, 0) == 0)
                    {
                        goto GETQUEUE;
                    }
                }
            }
            catch (Exception error)
            {
                isNeedDispose = true;
                AutoCSer.Log.Pub.Log.Add(Log.LogType.Fatal, error);
            }
            finally
            {
                buffer.Free();
                if (isNeedDispose)
                {
                    Dispose();
                }
            }
        }