Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
BlockReader.cs
1using System;
2using System.IO;
3using System.Runtime.ExceptionServices;
5using System.Text;
6using System.Threading.Tasks;
9
11{
18 public delegate Task BinaryDataReadCallback(byte[] Data, bool More, object State);
19
23 public class BlockReader : IDisposable
24 {
25 private const int BufferSize = 65536;
26
27 private readonly byte[] buffer = new byte[BufferSize];
28 private readonly byte[] signature;
29 private readonly string collectionName;
30 private BinaryDeserializer reader;
31 private BlockHeader header = null;
32 private Stream input;
33 private readonly ulong bytes;
34 private long bytesLeft;
35 private int bufPos = 0;
36 private int bufLen = 0;
37
38 private BlockReader(Stream Input, long InputLength, string CollectionName, byte[] Signature, ulong Bytes)
39 {
40 this.input = Input;
41 this.bytesLeft = InputLength;
42 this.collectionName = CollectionName;
43 this.signature = Signature;
44 this.bytes = Bytes;
45 }
46
53 public static Stream GetStream(string FileName, NeuroLedgerProvider Provider)
54 {
55 FileStream fs = null;
56 ICryptoTransform Aes = null;
57
58 try
59 {
60 fs = File.OpenRead(FileName);
61 Aes = Provider.GetAes(FileName, false);
62 return new CryptoStream(fs, Aes, CryptoStreamMode.Read);
63 }
64 catch (Exception ex)
65 {
66 fs?.Dispose();
67 Aes?.Dispose();
68
69 ExceptionDispatchInfo.Capture(ex).Throw();
70 return null;
71 }
72 }
73
79 public static async Task<BlockReader> CreateAsync(string FileName, NeuroLedgerProvider Provider)
80 {
81 FileStream fs = null;
82 ICryptoTransform Aes = null;
83 CryptoStream cs = null;
84 BlockReader Result = null;
85
86 try
87 {
88 fs = File.OpenRead(FileName);
89 Aes = Provider.GetAes(FileName, false);
90 cs = new CryptoStream(fs, Aes, CryptoStreamMode.Read);
91
92 Result = await CreateAsync(cs, Provider);
93 }
94 catch (Exception ex)
95 {
96 cs?.Dispose();
97 fs?.Dispose();
98 Aes?.Dispose();
99
100 ExceptionDispatchInfo.Capture(ex).Throw();
101 }
102
103 return Result;
104 }
105
111 public static async Task<BlockReader> CreateAsync(Stream cs, NeuroLedgerProvider Provider)
112 {
113 int CollectionLen = cs.ReadByte();
114 if (CollectionLen == 0)
115 CollectionLen = 256;
116
117 byte[] CollectionBin = await cs.ReadAllAsync(CollectionLen);
118
119 string CollectionName = Encoding.UTF8.GetString(CollectionBin);
120
121 int Bytes = 1 + CollectionLen;
122
123 int SigLen = cs.ReadByte();
124 if (SigLen == 0)
125 SigLen = 256;
126
127 byte[] Signature = await cs.ReadAllAsync(SigLen);
128
129 Bytes += 1 + SigLen;
130
131 // TODO: Validate signature before processing contents of file.
132
133 byte[] ContentLen = await cs.ReadAllAsync(8);
134
135 long InputLength = BitConverter.ToInt64(ContentLen, 0);
136
137 Bytes += 8;
138
139 ObjectSerializer HeaderSerializer = await Provider.GetObjectSerializerEx(typeof(BlockHeader));
140 BlockReader Result = null;
141
142 try
143 {
144 Result = new BlockReader(cs, InputLength, CollectionName, Signature, (ulong)(InputLength + Bytes));
145
146 int Len = (int)Math.Min(1024, Result.bytesLeft);
147 byte[] Bin = await Result.ReadBytesAsync(Len);
148
149 Result.reader = new BinaryDeserializer(CollectionName, Encoding.UTF8, Bin, 0);
150 Result.header = (BlockHeader)await HeaderSerializer.Deserialize(Result.reader, ObjectSerializer.TYPE_OBJECT, false);
151
152 Result.bufPos -= Bin.Length - Result.reader.Position;
153 }
154 catch (Exception ex)
155 {
156 Result?.Dispose();
157 ExceptionDispatchInfo.Capture(ex).Throw();
158 }
159
160 return Result;
161 }
162
166 public ulong Bytes => this.bytes;
167
168 private async Task<byte[]> ReadBytesAsync(int Bytes)
169 {
170 byte[] Result = new byte[Bytes];
171 int Pos = 0;
172 int i;
173
174 while (Pos < Bytes)
175 {
176 if (this.bufPos >= this.bufLen)
177 await this.ReadMore();
178
179 i = Math.Min(Bytes - Pos, this.bufLen - this.bufPos);
180 System.Buffer.BlockCopy(this.buffer, this.bufPos, Result, Pos, i);
181 Pos += i;
182 this.bufPos += i;
183 }
184
185 return Result;
186 }
187
188 private async Task ReadMore()
189 {
190 this.bufPos = 0;
191 this.bufLen = await this.input.TryReadAllAsync(this.buffer, 0, BufferSize);
192 if (this.bufLen <= 0)
193 throw new IOException("Unable to read from block.");
194
195 this.bytesLeft -= this.bufLen;
196 if (this.bytesLeft < 0)
197 {
198 this.bufLen += (int)this.bytesLeft;
199 this.bytesLeft = 0;
200 }
201 }
202
203 private async Task<byte> ReadByteAsync()
204 {
205 if (this.bufPos >= this.bufLen)
206 await this.ReadMore();
207
208 return this.buffer[this.bufPos++];
209 }
210
214 public bool EOF
215 {
216 get
217 {
218 return (this.bytesLeft <= 0 && this.bufPos >= this.bufLen);
219 }
220 }
221
225 public BlockHeader Header => this.header;
226
230 public string CollectionName => this.collectionName;
231
235 public byte[] Signature => this.signature;
236
240 public byte[] Buffer => this.buffer;
241
245 public int BufferPosition => this.bufPos;
246
250 public void Dispose()
251 {
252 this.input?.Dispose();
253 this.input = null;
254 }
255
261 {
262 return this.ReadEntryAsync().Result;
263 }
264
269 public async Task<Entry> ReadEntryAsync()
270 {
271 byte[] Buf = await this.ReadBytesAsync(10);
272
273 EntryType EntryType = (EntryType)Buf[0];
274 long Ticks = BitConverter.ToInt64(Buf, 1);
275 DateTime Timestamp = new DateTime(Ticks, DateTimeKind.Utc);
276 int b = Buf[9];
277 int Len = b & 127;
278 int Offset = 7;
279
280 while ((b & 128) != 0)
281 {
282 b = await this.ReadByteAsync();
283 Len |= (b & 127) << Offset;
284 Offset += 7;
285 }
286
287 Buf = await this.ReadBytesAsync(Len);
288
289 return new Entry(EntryType, Timestamp, Buf);
290 }
291
292 }
293}
static async Task< BlockReader > CreateAsync(string FileName, NeuroLedgerProvider Provider)
Creates a block reader.
Definition: BlockReader.cs:79
static async Task< BlockReader > CreateAsync(Stream cs, NeuroLedgerProvider Provider)
Creates a block reader.
Definition: BlockReader.cs:111
async Task< Entry > ReadEntryAsync()
Reads an entry from the block.
Definition: BlockReader.cs:269
Entry ReadEntry()
Reads an entry from the block.
Definition: BlockReader.cs:260
static Stream GetStream(string FileName, NeuroLedgerProvider Provider)
Gets a stream to the contents of the block.
Definition: BlockReader.cs:53
bool EOF
If the current position is at the end of the file.
Definition: BlockReader.cs:215
ulong Bytes
Size of block, in bytes
Definition: BlockReader.cs:166
int BufferPosition
Position in internal buffer.
Definition: BlockReader.cs:245
void Dispose()
IDisposable.Dispose
Definition: BlockReader.cs:250
byte[] Signature
Signature of block.
Definition: BlockReader.cs:235
Represents an entry in a block or bucket file.
Definition: Entry.cs:11
Task< ObjectSerializer > GetObjectSerializerEx(object Object)
Gets the object serializer corresponding to a specific object.
Manages binary deserialization of data.
Serializes a class, taking into account attributes defined in Attributes.
virtual async Task< object > Deserialize(IDeserializer Reader, uint? DataType, bool Embedded)
Deserializes a value.
delegate Task BinaryDataReadCallback(byte[] Data, bool More, object State)
Delegate for binary data callback methods.
EntryType
Ledger entry type.
Definition: ILedgerEntry.cs:9