Exemplo n.º 1
0
        public SequenceFileStorage(ILoggerFactory loggerFactory, string nodeId)
        {
            _logger        = loggerFactory.CreateLogger <SequenceFileStorage>();
            _dataFileName  = $"{nodeId}-data.bin";
            _indexFileName = $"{nodeId}-data.idx";

            _sempaphore.Wait();

            try
            {
                if (_dataFS == null || _indexFS == null)
                {
                    _dataFS  = File.Open(_dataFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
                    _indexFS = File.Open(_indexFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);

                    byte[] indexBytes = new byte[BusinessCodeIndex.BYTES_LENGTH];
                    while (_indexFS.Read(indexBytes, 0, indexBytes.Length) > 0)
                    {
                        var code = new BusinessCodeIndex(indexBytes);
                        _indexQueue.Enqueue(code);
                    }
                }
            }
            finally
            {
                _sempaphore.Release();
            }
        }
Exemplo n.º 2
0
        public async Task WriteAsync(BusinessCode codeToFlush, long globalVersion)
        {
            if (codeToFlush == null)
            {
                return;
            }
            _sempaphore.Wait();

            try
            {
                byte[] dataBytes = new byte[BusinessCode.BYTES_LENGTH];
                var    code      = new BusinessCode(codeToFlush.ToBytes());// 防止2次读取不一致

                var existsCodeIndex = _indexQueue.FirstOrDefault(m => m.ApplicationID == code.ApplicationId && m.CodeType == code.CodeType);
                if (existsCodeIndex == null)
                {
                    _dataFS.Seek(0, SeekOrigin.End);
                    var indexPosition = _dataFS.Position;
                    dataBytes = code.ToBytes();
                    await _dataFS.WriteAsync(dataBytes, 0, dataBytes.Length);

                    var codeIndex = new BusinessCodeIndex
                    {
                        ApplicationID = code.ApplicationId,
                        CodeType      = code.CodeType,
                        Position      = indexPosition
                    };
                    var codeIndexBytes = codeIndex.ToBytes();
                    await _indexFS.WriteAsync(codeIndexBytes, 0, codeIndexBytes.Length);

                    _indexQueue.Enqueue(codeIndex);
                }
                else
                {
                    _dataFS.Seek(existsCodeIndex.Position, SeekOrigin.Begin);
                    _dataFS.Read(dataBytes, 0, dataBytes.Length);
                    var currentCode = new BusinessCode(dataBytes);
                    if (code.ApplicationId != currentCode.ApplicationId || code.CodeType != currentCode.CodeType)
                    {
                        _logger.LogError($"Bad file {_dataFileName}, applicationId={codeToFlush.ApplicationId}, codeType={codeToFlush.CodeType}");
                        throw new InvalidDataException($"Bad file {_dataFileName}");
                    }
                    if (code.ApplicationId == currentCode.ApplicationId && code.CodeType == currentCode.CodeType)
                    {
                        if (code.VersionId < currentCode.VersionId)
                        {
                            _logger.LogError($"Bad file {_dataFileName}, version is invalid, applicationId={codeToFlush.ApplicationId}, codeType={codeToFlush.CodeType}, versionId={codeToFlush.VersionId}");
                            throw new InvalidDataException($"Bad file {_dataFileName}");
                        }
                        if (code.Infix != currentCode.Infix || code.Sequence != currentCode.Sequence)
                        {
                            if (code.Infix == currentCode.Infix && code.Sequence < currentCode.Sequence)
                            {
                                _logger.LogError($"Bad file {_dataFileName}, sequence is invalid, applicationId={codeToFlush.ApplicationId}, codeType={codeToFlush.CodeType}, sequence={codeToFlush.Sequence}");
                                throw new InvalidDataException($"Bad file {_dataFileName}");
                            }
                            _dataFS.Seek(existsCodeIndex.Position, SeekOrigin.Begin);
                            dataBytes = code.ToBytes();
                            await _dataFS.WriteAsync(dataBytes, 0, dataBytes.Length);
                        }
                    }
                }

                // 写入全局版本号
                _dataFS.Seek(0, SeekOrigin.Begin);
                await _dataFS.WriteAsync(BitConverter.GetBytes(globalVersion), 0, 8);
            }
            catch (Exception ex)
            {
                _logger.LogError($"Write fail: {ex.Message}, applicationId={codeToFlush.ApplicationId}, codeType={codeToFlush.CodeType}", ex);
                throw;
            }
            finally
            {
                _sempaphore.Release();
            }
        }