//Will return 0, 1, or 2 batches public SafeOrderedReturn Ordered(SafeEnvelope msg, int index) { try { SafeBatch[] batches = new SafeBatch[2]; bool ispendingbatch = true; ulong MsgSizeBytes = (ulong)msg.Payload.Length; //Length of byte array = size in bytes //Message is too big and thus will overflow, send pending and this msg in its own batch if (MsgSizeBytes > MaxPendingSizeBytes) { if (PendingBatch.Messages.Count() > 0) { batches[0] = Cut(); //Add pending batch to return } SafeBatch newbatch = new SafeBatch(); newbatch.Messages = new SafeEnvelope[1]; newbatch.Messages[0] = msg; batches[1] = newbatch; ispendingbatch = false; } else { //Message will cause overflow, cut pending batch if (PendingBatchSizeBytes + MsgSizeBytes > MaxPendingSizeBytes) { batches[0] = Cut(); //Add pending batch to return } while (index > MsgNum || pendinglocked) { } //Wait for it to be this msg's turn and not currently cutting batch AddToPending(msg, MsgSizeBytes, index); //Add message to pending batch //Pending batch has reached max count, must cut //If the last if statement was true, this one will not be true if (PendingBatch.MsgCount >= MaxPendingMsgCount) { pendinglocked = true; batches[1] = Cut(); //Add pending batch to return ispendingbatch = false; } Interlocked.Add(ref MsgNum, 1); //Increment msgnum } SafeOrderedReturn toreturn = new SafeOrderedReturn(); toreturn.Batches = batches; toreturn.IsPendingBatch = ispendingbatch; return(toreturn); } catch { int a = 1; return(new SafeOrderedReturn()); } }
//Return and reset pending batch public SafeBatch Cut() { SafeBatch returnbatch = PendingBatch; //Set batch to return PendingBatch = new SafeBatch(); PendingBatch.Messages = new SafeEnvelope[MaxPendingMsgCount]; PendingBatch.MsgCount = 0; PendingBatchSizeBytes = 0; pendinglocked = false; return(returnbatch); }
public static unsafe void HandleMessageCPU(SafeMessage msg, int index) { Console.WriteLine(String.Format("HandleMessageCPU {0}", index)); //Check if configmsg is initialized. If not, it's a normal message. bool config = false; if (config) //It's a config message { //Cut pending batch so we can make and send the block then a config block SafeBatch newbatch = Cutter.Cut(); Console.WriteLine("Config Message, newbatch message count={0}", newbatch.Messages.Count()); if (newbatch.Messages.Count() > 0) { Task.Factory.StartNew(() => MakeBlockCPU(newbatch, false)); } //Now make a config block SafeBatch newconfigbatch = new SafeBatch(); newconfigbatch.Messages = new SafeEnvelope[1]; newconfigbatch.Messages[0] = msg.ConfigMsg; Task.Factory.StartNew(() => MakeBlockCPU(newconfigbatch, true)); } else //It's a normal message { //Stopwatch sw1 = new Stopwatch(); //sw1.Start(); SafeOrderedReturn OR = Cutter.Ordered(msg.NormalMsg, index); //sw1.Stop(); //string output = "Time taken: " + sw1.ElapsedTicks + " ticks" + Environment.NewLine; //Console.WriteLine(output); //Ordered returns 0, 1, or 2 batches, process each one Console.WriteLine("Normal Message, batches: {0}, {1}", OR.Batches[0], OR.Batches[1]); Parallel.For(0, 2, i => { if (OR.Batches[i] != null) { Task.Factory.StartNew(() => MakeBlockCPU(OR.Batches[i], false)); } }); //Handle setting of timer bool pending = OR.IsPendingBatch; //There is a pending batch bool timernull = Timer == new DateTime(); //Timer is default value if (!timernull && !pending) //There is a timer but no pending batches, unnecessary { Timer = new DateTime(); //Set timer to default value } else if (timernull && pending) { Timer = DateTime.Now; //Start timer } } }
public Block CreateNextBlockCPU(SafeBatch newbatch) { byte[] previousblockhash = BlockHeaderHash(PreviousBlockHeader); BlockData blockdata = new BlockData(); byte[][] data = new byte[newbatch.Messages.Count()][]; //Convert each message to byte format to add to data Parallel.For(0, newbatch.Messages.Count(), i => { data[i] = Marshal(newbatch.Messages[i]); }); blockdata.Data = data; Block newblock = NewBlock(PreviousBlockHeader.Number + 1, previousblockhash); newblock.Header.DataHash = BlockDataHash(blockdata); newblock.Data = blockdata; PreviousBlockHeader = newblock.Header; return(newblock); }
//Uses blockwriter to create a new block and then write it down static void MakeBlockCPU(SafeBatch newbatch, bool config) { DateTime blockwritetimer = DateTime.Now; Block newblock = Writer.CreateNextBlockCPU(newbatch); if (config) { Writer.WriteConfigBlock(newblock); } else { Interlocked.Increment(ref BlockCount); //Writer.WriteBlock(newblock); } string blockoutput = "Creating " + (config ? "config" : "normal") + " block " + newblock.Header.Number + Environment.NewLine; blockoutput += "Message count: " + newbatch.MsgCount + Environment.NewLine; blockoutput += "Time taken: " + (DateTime.Now - blockwritetimer).TotalMilliseconds + "ms" + Environment.NewLine; blockoutput += "---------------------------------------------------------------------" + Environment.NewLine; Console.WriteLine(blockoutput); }