public void FlushOnLowWatermarkDualStream() { SetupQuery(DisorderPolicy.Throw(reorderLatency: 500)); // These will be buffered due to reorderLatency this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1, 0)); // key 0: 1-2 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 101, 0)); // key 0: 101-102 // This will batch the first point (0: 1-2)); but the second point ( key 0: 101-102) remains batched, since 101 > 100. // Since we use the default policy, FlushOnLowWatermark, the first point will also be flushed at this point. this.input.OnNext(PartitionedStreamEvent.CreateLowWatermark <int, int>(100)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1005, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1100, 0)); // OnCompletedPolicy.EndOfStream adds the last two points to the batch then flushes all var expected = new PartitionedStreamEvent <int, int>[] { // Flushed in response to low watermark PartitionedStreamEvent.CreatePoint(0, 1, 0), PartitionedStreamEvent.CreateLowWatermark <int, int>(100), // Flushed in response to OnCompleted PartitionedStreamEvent.CreatePoint(0, 101, 0), PartitionedStreamEvent.CreatePoint(0, 1005, 0), PartitionedStreamEvent.CreatePoint(0, 1100, 0), // Generated by the default OnCompletedPolicy EndOfStream PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime), }; FinishQuery(expected); }
protected void ReorderLatencyDisorderingBase(DisorderPolicy disorderPolicy, PeriodicLowWatermarkPolicy lowWatermarkPolicy) { TestSetup(disorderPolicy, lowWatermarkPolicy); // Partition 0 - locally disordered AddEvent(0, 100); AddEvent(0, 95); AddEvent(0, 89); // Partition 1 - globally disordered AddEvent(1, 80); AddEvent(1, 85); AddEvent(1, 90); AddEvent(1, 95); AddEvent(1, 100); // Partition 2 - locally and globally disordered AddEvent(2, 80); AddEvent(2, 85); AddEvent(2, 90); AddEvent(2, 95); AddEvent(2, 100); AddEvent(2, 99); AddEvent(2, 94); AddEvent(2, 89); AddEvent(2, 84); AddEvent(2, 79); RunAndValidate(); }
public void ReorderTest2ColumnarSmallBatch() { var oldSortingTechnique = Config.IngressSortingTechnique; Config.IngressSortingTechnique = SortingTechnique.PriorityQueue; var outputList = new List <StreamEvent <int> >(); double disorderFraction = 0.5; int reorderLatency = 202; int disorderAmount = 200; var rand = new Random(2); var disorderedData = Enumerable.Range(disorderAmount, 500000).ToList() .Select(e => StreamEvent.CreateStart(rand.NextDouble() < disorderFraction ? e - rand.Next(0, disorderAmount) : e, 0)) .ToList(); var stream = disorderedData.ToObservable().ToStreamable(DisorderPolicy.Drop(reorderLatency)); stream.ToStreamEventObservable().ForEachAsync(e => { if (e.IsData) { outputList.Add(e); } }).Wait(); disorderedData.Sort((a, b) => a.SyncTime.CompareTo(b.SyncTime)); Assert.IsTrue(disorderedData.SequenceEqual(outputList)); Config.IngressSortingTechnique = oldSortingTechnique; }
/// <summary> /// /// </summary> /// <typeparam name="TPayload"></typeparam> /// <param name="observable"></param> /// <param name="startEdgeSelector"></param> /// <param name="endEdgeSelector"></param> /// <param name="disorderPolicy"></param> /// <param name="partitionPolicy"></param> /// <returns></returns> public IQStreamable <TPayload> RegisterStream <TPayload>( IObservable <TPayload> observable, Expression <Func <TPayload, long> > startEdgeSelector, Expression <Func <TPayload, long> > endEdgeSelector, DisorderPolicy disorderPolicy, PartitionPolicy partitionPolicy) => throw new NotImplementedException();
public void TestSetup(DisorderPolicy disorderPolicy, PeriodicLowWatermarkPolicy lowWatermarkPolicy) { this.disorderPolicy = disorderPolicy; this.lowWatermarkPolicy = lowWatermarkPolicy; // This establishes three partitions with keys 0,1,2 PartitionedStreamEvent <int, int> point; for (int key = 0; key < 3; key++) { point = PartitionedStreamEvent.CreatePoint(key, 0, key); this.input.Add(point); this.expected[key].Add(point); this.batchMarker[key] = 1; } // Add a point at 100 for key 0 as a baseline, and a low watermark if necessary this.highWatermark = 100; point = PartitionedStreamEvent.CreatePoint(0, this.highWatermark, 0); this.input.Add(point); UpdateExpectedLowWatermark(this.highWatermark); this.expected[0].Insert(this.batchMarker[0]++, point); // If we have a nonzero reorder latency, the event at 100 will be buffered, so add another point at // 100+ReorderLatency to push the real highwatermark to 100 if (this.ReorderLatency > 0) { AddEvent(0, this.highWatermark + this.ReorderLatency); } }
public void ReorderTest1Row() { using (var modifier = new ConfigModifier().IngressSortingTechnique(SortingTechnique.ImpatienceSort).Modify()) { var outputList = new List <StreamEvent <int> >(); double disorderFraction = 0.5; int reorderLatency = 202; int disorderAmount = 200; var rand = new Random(2); var disorderedData = Enumerable.Range(disorderAmount, 500000).ToList() .Select(e => StreamEvent.CreateStart(rand.NextDouble() < disorderFraction ? e - rand.Next(0, disorderAmount) : e, 0)) .ToList(); var stream = disorderedData.ToObservable().ToStreamable(DisorderPolicy.Drop(reorderLatency)); stream.ToStreamEventObservable().ForEachAsync(e => { if (e.IsData) { outputList.Add(e); } }).Wait(); disorderedData.Sort((a, b) => a.SyncTime.CompareTo(b.SyncTime)); Assert.IsTrue(disorderedData.SequenceEqual(outputList)); } }
internal TriPartitionedOrderedTestsBase( ConfigModifier config, DisorderPolicy disorderPolicy, PeriodicPunctuationPolicy punctuationPolicy, PeriodicLowWatermarkPolicy lowWatermarkPolicy) : base(config) { this.disorderPolicy = disorderPolicy; this.punctuationPolicy = punctuationPolicy; this.lowWatermarkPolicy = lowWatermarkPolicy; }
internal FlushTestBase( DisorderPolicy disorderPolicy, FlushPolicy flushPolicy, PeriodicPunctuationPolicy punctuationPolicy, OnCompletedPolicy completedPolicy) : base(baseConfigModifier) { this.disorderPolicy = disorderPolicy; this.flushPolicy = flushPolicy; this.punctuationPolicy = punctuationPolicy; this.completedPolicy = completedPolicy; }
public void AlterLifeTimeWithFlushDoubles() { var startDate = new DateTime(100); var data = new[] { new { Time = startDate, DeviceId = 4, Value = 4 }, new { Time = startDate, DeviceId = 4, Value = 4 }, new { Time = startDate, DeviceId = 6, Value = 6 }, new { Time = startDate, DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(1), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(1), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(2), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(2), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(3), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(3), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(11), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(11), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(5), DeviceId = 4, Value = 4 }, new { Time = startDate.AddMinutes(5), DeviceId = 4, Value = 4 }, new { Time = startDate.AddMinutes(12), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(12), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(13), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(13), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(14), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(14), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(15), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(15), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(16), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(16), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(17), DeviceId = 4, Value = 4 }, new { Time = startDate.AddMinutes(17), DeviceId = 4, Value = 4 }, new { Time = startDate.AddMinutes(21), DeviceId = 6, Value = 6 }, new { Time = startDate.AddMinutes(21), DeviceId = 6, Value = 6 }, } .Select(e => PartitionedStreamEvent.CreateInterval(e.DeviceId, e.Time.Ticks, StreamEvent.MaxSyncTime, e.Value)); var res = new List <Notification <PartitionedStreamEvent <int, int> > >(); using (data.ToObservable() .ToStreamable( DisorderPolicy.Adjust(0), PartitionedFlushPolicy.FlushOnLowWatermark, PeriodicPunctuationPolicy.Time(36000)) .AlterEventDuration(1) .ToStreamEventObservable() .Subscribe(res.NotificationListObserver())) { } Assert.IsTrue(res.Count > 0, "There should be some results."); }
public void ReorderLatencyWithExplicitPunctuation() { var disorderPolicy = DisorderPolicy.Drop(reorderLatency: 10); SetupQuery(disorderPolicy); // These will be buffered and reordered due to reorderLatency of 10 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 30, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 25, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 20, 0)); // This will update partition 0's current time to 30. Anything before 30 after this point will be out of order. this.input.OnNext(PartitionedStreamEvent.CreatePunctuation <int, int>(0, 30)); // Even though these events are before the partitions high watermark (30) - reorder latency (10) = 20, // they will still be dropped due to the punctuation at 30. this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 25, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 20, 0)); // Events at or after the punctuation are still valid this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 30, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 35, 0)); // Each partition is independent, so a new partition is unaffected by another's high watermark/reorderLatency this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 1, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 10, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 5, 0)); var expected = new PartitionedStreamEvent <int, int>[] { // Events are reordered within the reorderLatency PartitionedStreamEvent.CreatePoint(0, 20, 0), PartitionedStreamEvent.CreatePoint(0, 25, 0), PartitionedStreamEvent.CreatePoint(0, 30, 0), PartitionedStreamEvent.CreatePunctuation <int, int>(0, 30), PartitionedStreamEvent.CreatePoint(0, 30, 0), PartitionedStreamEvent.CreatePoint(0, 35, 0), // Each partition acts independently PartitionedStreamEvent.CreatePoint(1, 1, 0), PartitionedStreamEvent.CreatePoint(1, 5, 0), PartitionedStreamEvent.CreatePoint(1, 10, 0), // Generated by the default OnCompletedPolicy EndOfStream PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime), }; FinishQuery(expected); }
/// <summary> /// Create query and register subscriber /// </summary> private void CreateQuery() { this.queryContainer = new QueryContainer(); this.input = new Subject <StreamEvent <long> >(); var inputStream = this.queryContainer.RegisterInput( this.input, DisorderPolicy.Drop(), FlushPolicy.FlushOnPunctuation, PeriodicPunctuationPolicy.Time(1)); var query = inputStream.AlterEventDuration(StreamEvent.InfinitySyncTime).Count(); var async = this.queryContainer.RegisterOutput(query); async.Where(e => e.IsStart).ForEachAsync(o => Console.WriteLine($"{o}")); }
public void SorterDequeueUntillRow() { var oldSortingTechnique = Config.IngressSortingTechnique; Config.IngressSortingTechnique = SortingTechnique.ImpatienceSort; var input = new List <Tuple <int, int> >() { Tuple.Create(0, 1), Tuple.Create(1, 1), Tuple.Create(0, 3), Tuple.Create(0, 5), Tuple.Create(1, 3), Tuple.Create(1, 20), Tuple.Create(0, 6), Tuple.Create(0, 7), Tuple.Create(0, 8), Tuple.Create(1, 2), Tuple.Create(0, 2), Tuple.Create(1, 30), Tuple.Create(0, 13) }; var expectedoutput = new List <Tuple <int, int> >() { Tuple.Create(1, 1), Tuple.Create(1, 3), Tuple.Create(1, 20), Tuple.Create(0, 1), Tuple.Create(0, 2), Tuple.Create(0, 3), Tuple.Create(0, 5), Tuple.Create(0, 6), Tuple.Create(0, 7), Tuple.Create(0, 8), Tuple.Create(0, 13), Tuple.Create(1, 30) }; var prog = input.Select(x => PartitionedStreamEvent.CreateStart(x.Item1, x.Item2, x.Item2)).ToObservable() .ToStreamable(DisorderPolicy.Drop(10)).ToStreamEventObservable(); var outevents = prog.ToEnumerable().ToList(); var output = outevents.Where(o => o.IsData).ToList(); var success = output.SequenceEqual(expectedoutput.Select(t => PartitionedStreamEvent.CreateStart(t.Item1, t.Item2, t.Item2))); Config.IngressSortingTechnique = oldSortingTechnique; Assert.IsTrue(success); }
private void SetupQuery( DisorderPolicy disorderPolicy, PartitionedFlushPolicy flushPolicy = PartitionedFlushPolicy.FlushOnLowWatermark, PeriodicPunctuationPolicy punctuationPolicy = null, // Default: PeriodicPunctuationPolicy.None() PeriodicLowWatermarkPolicy lowWatermarkPolicy = null, // Default: PeriodicLowWatermarkPolicy.None() OnCompletedPolicy completedPolicy = OnCompletedPolicy.EndOfStream) { var qc = new QueryContainer(); this.input = new Subject <PartitionedStreamEvent <int, int> >(); var ingress = qc.RegisterInput(this.input, disorderPolicy, flushPolicy, punctuationPolicy, lowWatermarkPolicy, completedPolicy); this.output = new List <PartitionedStreamEvent <int, int> >(); this.egress = qc.RegisterOutput(ingress).ForEachAsync(o => this.output.Add(o)); this.process = qc.Restore(); this.validateByPartition = disorderPolicy.reorderLatency > 0; }
public void ReorderLatencyAdjust() { var disorderPolicy = DisorderPolicy.Adjust(reorderLatency: 10); SetupQuery(disorderPolicy); // These will be buffered and reordered due to reorderLatency of 10 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 30, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 25, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 20, 0)); // These will be adjusted to the minimum, since they are before the partition's high watermark (30) - reorder latency (10) = 20 this.input.OnNext(PartitionedStreamEvent.CreateInterval(0, 8, 30, 0)); // Will be adjusted to 20 this.input.OnNext(PartitionedStreamEvent.CreateInterval(0, 9, 30, 0)); // Will be adjusted to 20 // This will be dropped, since Trill will not adjust intervals whose end times are before the minimum this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 8, 0)); // Will be dropped this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 9, 0)); // Will be dropped // Each partition is independent, so a new partition is unaffected by another's high watermark/reorderLatency this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 1, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 10, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 5, 0)); var expected = new PartitionedStreamEvent <int, int>[] { // Events are reordered within the reorderLatency, and out of order events are adjusted to minimum PartitionedStreamEvent.CreatePoint(0, 20, 0), PartitionedStreamEvent.CreateInterval(0, 20, 30, 0), PartitionedStreamEvent.CreateInterval(0, 20, 30, 0), PartitionedStreamEvent.CreatePoint(0, 25, 0), PartitionedStreamEvent.CreatePoint(0, 30, 0), // Each partition acts independently PartitionedStreamEvent.CreatePoint(1, 1, 0), PartitionedStreamEvent.CreatePoint(1, 5, 0), PartitionedStreamEvent.CreatePoint(1, 10, 0), // Generated by the default OnCompletedPolicy EndOfStream PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime), }; FinishQuery(expected); }
public void FlushOnLowWatermarkSimple() { SetupQuery(DisorderPolicy.Throw(reorderLatency: 10), PartitionedFlushPolicy.FlushOnLowWatermark, null, null, OnCompletedPolicy.None); // This will be buffered due to reorderLatency this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1, 0)); // Since we specify FlushOnLowWatermark, this will flush the point above, as well as the low watermark itself this.input.OnNext(PartitionedStreamEvent.CreateLowWatermark <int, int>(9000)); var expected = new PartitionedStreamEvent <int, int>[] { // Flushed in response to low watermark PartitionedStreamEvent.CreatePoint(0, 1, 0), PartitionedStreamEvent.CreateLowWatermark <int, int>(9000), }; FinishQuery(expected); }
public void LowWatermark() { var disorderPolicy = DisorderPolicy.Drop(reorderLatency: 10); SetupQuery(disorderPolicy, PartitionedFlushPolicy.None); // This will be buffered due to reorderLatency this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1, 0)); // This will set the entire stream's lower bound to 100 this.input.OnNext(PartitionedStreamEvent.CreateLowWatermark <int, int>(100)); // If any partition, new or existing, specifies a timestamp before 100, it is considered out of order // and since we specify DisorderPolicy.Drop, they will be dropped this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 50, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 50, 0)); // Any points at or after the low watermark of 100 will be processed as usual this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 100, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 100, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 105, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 105, 0)); var expected = new PartitionedStreamEvent <int, int>[] { // Flushed in response to the default OnCompletedPolicy.EndOfStream PartitionedStreamEvent.CreatePoint(0, 1, 0), PartitionedStreamEvent.CreateLowWatermark <int, int>(100), // Points at time 50 are dropped PartitionedStreamEvent.CreatePoint(0, 100, 0), PartitionedStreamEvent.CreatePoint(1, 100, 0), PartitionedStreamEvent.CreatePoint(0, 105, 0), PartitionedStreamEvent.CreatePoint(1, 105, 0), // Generated by the default OnCompletedPolicy EndOfStream PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime), }; FinishQuery(expected); }
protected void LocalDisorderingBase(DisorderPolicy disorderPolicy, PeriodicLowWatermarkPolicy lowWatermarkPolicy) { TestSetup(disorderPolicy, lowWatermarkPolicy); // Add events that are locally disordered // Partition 0 AddEvent(0, 100); // Partition 1 AddEvent(1, 100); AddEvent(1, 95); AddEvent(1, 89); // Partition 2 AddEvent(2, 96); AddEvent(2, 94); AddEvent(2, 91); RunAndValidate(); }
public void PunctuationTimeGeneration() { SetupQuery( DisorderPolicy.Throw(), PartitionedFlushPolicy.FlushOnLowWatermark, PeriodicPunctuationPolicy.Time(generationPeriod: 1000)); // This establishes three partitions with keys 1,2,3 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 0, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 0, 1)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(2, 0, 2)); // Since the next point arrives at 10001, which is exactly PeriodicPunctuationPolicy.generationPeriod after // the first point, this will generate a punctuation at 10001 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 10001, 0)); // These are still valid, since the punctuation generated above only affects key 0 this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 1, 1)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(2, 1, 2)); var expected = new PartitionedStreamEvent <int, int>[] { // Flushed in response to OnCompleted PartitionedStreamEvent.CreatePoint(0, 0, 0), PartitionedStreamEvent.CreatePoint(1, 0, 1), PartitionedStreamEvent.CreatePoint(2, 0, 2), // Punctuation snapped to the leftmost generationPeriod boundary PartitionedStreamEvent.CreatePunctuation <int, int>(0, 10000), PartitionedStreamEvent.CreatePoint(0, 10001, 0), PartitionedStreamEvent.CreatePoint(1, 1, 1), PartitionedStreamEvent.CreatePoint(2, 1, 2), // Generated by the default OnCompletedPolicy EndOfStream PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime), }; FinishQuery(expected); }
private static void PassThrough() { // var inputStream = GetTollReadings(); // Display(inputStream); // var subscription = TollReadingEvents.ToAtemporalStreamable(); // Display(subscription); { var queryContainer = new QueryContainer(); var inputStream = queryContainer.RegisterInput( TollReadingEvents, DisorderPolicy.Drop(), FlushPolicy.FlushOnPunctuation, PeriodicPunctuationPolicy.Time(1)); var query = inputStream.HoppingWindowLifetime(TimeSpan.FromSeconds(10).Ticks, TimeSpan.FromSeconds(1).Ticks) .Count() .AlterEventDuration(1); var async = queryContainer.RegisterOutput(query); Display("1) ", 1, async); queryProcess1 = queryContainer.Restore(); } }
public void ReorderLatencyDrop() { var disorderPolicy = DisorderPolicy.Drop(reorderLatency: 10); SetupQuery(disorderPolicy); // These will be buffered and reordered due to reorderLatency of 10 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 30, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 25, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 20, 0)); // These will be dropped since they are before the partition's high watermark (30) - reorder latency (10) = 20 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 8, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 9, 0)); // Each partition is independent, so a new partition is unaffected by another's high watermark/reorderLatency this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 1, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 10, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 5, 0)); var expected = new PartitionedStreamEvent <int, int>[] { // Events are reordered within the reorderLatency PartitionedStreamEvent.CreatePoint(0, 20, 0), PartitionedStreamEvent.CreatePoint(0, 25, 0), PartitionedStreamEvent.CreatePoint(0, 30, 0), // Each partition acts independently PartitionedStreamEvent.CreatePoint(1, 1, 0), PartitionedStreamEvent.CreatePoint(1, 5, 0), PartitionedStreamEvent.CreatePoint(1, 10, 0), // Generated by the default OnCompletedPolicy EndOfStream PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime), }; FinishQuery(expected); }
private static IObservable <StreamEvent <Toll> > GetTollObservable(QueryContainer queryContainer) { var inputStream = queryContainer.RegisterInput(TollReadingEvents, DisorderPolicy.Drop(), FlushPolicy.FlushOnPunctuation, PeriodicPunctuationPolicy.Time(1)); var partitionedSlidingWindow1 = inputStream.AlterEventDuration((start, end) => end - start + TimeSpan.FromSeconds(2).Ticks) .HoppingWindowLifetime(TimeSpan.FromSeconds(2).Ticks, TimeSpan.FromSeconds(2).Ticks) .GroupApply( r => r.TollId, r => r.Multicast( perTollBoth => perTollBoth.Sum(e => e.Toll) .Join(perTollBoth.Count(), (sum, count) => new { Sum = sum, Count = count })), (key, result) => new Toll { TollId = key.Key, TollAmount = result.Sum, VehicleCount = result.Count }); var retval = queryContainer.RegisterOutput(partitionedSlidingWindow1); return(retval); }
public FlushOnBatchBoundary_OnCompletedEndOfStream() : base(DisorderPolicy.Throw(), FlushPolicy.FlushOnBatchBoundary, PeriodicPunctuationPolicy.None(), OnCompletedPolicy.EndOfStream) { }
public FlushNone_OnCompletedEndOfStream() : base(DisorderPolicy.Throw(), FlushPolicy.None, PeriodicPunctuationPolicy.None(), OnCompletedPolicy.EndOfStream) { }
public FlushOnPunctuation_OnCompletedFlush() : base(DisorderPolicy.Throw(), FlushPolicy.FlushOnPunctuation, PeriodicPunctuationPolicy.None(), OnCompletedPolicy.Flush) { }
public static void Main(string[] args) { // start networking string ip = "127.0.0.1"; int port = 8000; // We make a new thread dedicated to the Socket // detach from observer logic to provide multiple subscriptions ThreadedListener listener = new ThreadedListener(ip, port); Thread listenerThread = new Thread(new ThreadStart(listener.StartListener)); listenerThread.Start(); /* * source: Observable that adds an Observer to the listener when subscribed to, i.e. called ToObservable() on */ IObservable <StreamEvent <Payload> > source = Observable.Create <StreamEvent <Payload> >( observer => { listener.AddObserver(observer); return(Disposable.Create(() => Console.WriteLine("Unsubscribed"))); }); /* * inputStream: Streamable that ingresses from source * Uses a FlushPolicy and Punctuations, which inject empty events in order to force the stream to process * Flush policy does not take precedence over windows, i.e. HoppingWindows retain their time frame when queries are being run */ var inputStream = source.ToStreamable( DisorderPolicy.Drop()); // a sample query var query1 = inputStream.Where(e => e.EventID == 0); /////////////////////////// ///// BEGIN USE CASES ///// /////////////////////////// /* * TEMPORAL CASES: use *temporal* stream * control window with temporalWindow */ var temporalWindow = 8.0; var temporal = inputStream .HoppingWindowLifetime(TimeSpan.FromSeconds(temporalWindow).Ticks, TimeSpan.FromSeconds(1.0).Ticks); /* * 1: Detect when event B occurs within x minutes of event A */ var temporalA = temporal.Where(e => e.EventID == 0); var temporalB = temporal.Where(e => e.EventID == 1); // join currently matches on IsTemporal, which is always null... var temporal1 = temporalA.Join(temporalB, e => e.IsTemporal, e => e.IsTemporal, (left, right) => new { leftID = left.DeviceID, rightID = right.DeviceID, leftTS = left.Timestamp, rightTS = left.Timestamp, leftEventID = left.EventID, rightEventID = right.EventID }) .Select(e => new { e.leftID, e.rightID, e.leftEventID, e.rightEventID }); // Linq-syntax analog of the above var temporalFinalLinq = from left in temporalA join right in temporalB on left.IsTemporal equals right.IsTemporal select new { leftID = left.DeviceID, rightID = right.DeviceID, leftTS = left.Timestamp, rightTS = left.Timestamp, leftEventID = left.EventID, rightEventID = right.EventID }; /* * 2: Detect when event A occurs at least n times within x minutes */ // reuse the temporalA above var temporal2 = temporalA.Count(); //////////////////////////// /* * Spatial cases: use spatial stream * control window with spatialWindow */ var spatialWindow = 30.0; var spatial = inputStream .Select(payload => new { payload.DeviceID, payload.EventID, Location = new Location(payload.EventData) }) .HoppingWindowLifetime(TimeSpan.FromSeconds(spatialWindow).Ticks, TimeSpan.FromSeconds(1.0).Ticks); /* * 1: Detect two objects within x feet of each other */ double spatialThreshold = 15.0; var spatialLat = spatial.Select(payload => new { payload.DeviceID, payload.Location.latitude }); var spatialLong = spatial.Select(payload => new { payload.DeviceID, payload.Location.longitude }); var latitudes = spatialLat .Join( spatialLat, (left, right) => new { leftID = left.DeviceID, rightID = right.DeviceID, difference = Math.Abs(left.latitude - right.latitude) }) .Where(e => (e.leftID != e.rightID) && (e.difference <= spatialThreshold)); var longitudes = spatialLong .Join( spatialLong, (left, right) => new { leftID = left.DeviceID, rightID = right.DeviceID, difference = Math.Abs(left.longitude - right.longitude) }) .Where(e => (e.leftID != e.rightID) && (e.difference <= spatialThreshold)); var spatial1 = from e1 in latitudes join e2 in longitudes on new { e1.leftID, e1.rightID } equals new { e2.leftID, e2.rightID } select new { e1.leftID, e1.rightID, latDiff = e1.difference, longDiff = e2.difference }; //////////////////////////// /* * SEQUENTIAL CASES * control window with seqWindow */ var seqWindow = 60.0; var sequence = inputStream; /* * 1: Detect when event A occurs, followed by event B, followed by event C */ var sequence1 = sequence.FollowedByImmediate( (event1) => event1.EventID == 0, (event2) => event2.EventID == 1, (first, second) => second, TimeSpan.FromSeconds(seqWindow).Ticks) .FollowedByImmediate( sequence, (event2) => event2.EventID == 1, (event3) => event3.EventID == 2, (second, third) => third, TimeSpan.FromSeconds(seqWindow).Ticks); /* * 2: Detect when event A occurs, followed by event B or event C, followed by event D */ var sequence2 = sequence.FollowedByImmediate( (event1) => event1.EventID == 0, (event2) => event2.EventID == 1 || event2.EventID == 2, (first, second) => second, TimeSpan.FromSeconds(seqWindow).Ticks) .FollowedByImmediate( sequence, (event2) => true, (event3) => event3.EventID == 3, (second, third) => third, TimeSpan.FromSeconds(seqWindow).Ticks); //////////////////////////// /* * EVALUATION CASES * value to compare is evalThreshold * control window with evalWindow */ var evalThreshold = 20; var evalWindow = 10.0; var evaluation = inputStream .HoppingWindowLifetime(TimeSpan.FromSeconds(evalWindow).Ticks, TimeSpan.FromSeconds(1.0).Ticks); //var evaluation1 = evaluation.Where(e => Int32.Parse(e.EventData) > evalThreshold); /////////////////////////// ////// END USE CASES ////// /////////////////////////// /* * Egress: each stream query is egressed to an Observable * Objects in the Observable are written via the arrow function (`() => new { }`) * Constructor parameters (`(start, end, payload)`) determine the data to pull from the query * action code goes in ForEachAsync block */ inputStream.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(m => Console.WriteLine("Events detected! " + m.Payload.EventData)); // Temporal output //temporal1.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(m => Console.WriteLine("Events detected! " + m)); //temporal2.ToStreamEventObservable() // .Where(e => e.IsData) // .ForEachAsync(m => { // Console.WriteLine("Number of event A detected: " + m.Payload); // // do things with m here... // ulong n = 4; // if (m.Payload >= n) { // Console.WriteLine("More than n event A detected!"); // } // }); // Spatial output spatial1.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(m => Console.WriteLine("Devices " + m.Payload.leftID + " and " + m.Payload.rightID + " have a lat/long diff of (" + m.Payload.latDiff + ", " + m.Payload.longDiff + ")")); // Sequence output //sequence1.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(m => Console.WriteLine(m.StartTime + ", " + m.EndTime)); //sequence2.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(m => Console.WriteLine(m)); // Evaluation output //evaluation1.ToTemporalObservable((start, end, payload) => new { payload.DeviceID, payload.EventID }).ForEachAsync(m => Console.WriteLine(m)); }
public static void Test() { // This program is a supplement to the Trill Users Guide #region Section 2 IObservable <ContextSwitch> cSTicksObs = new[] { new ContextSwitch(0, 1, 1, 120), new ContextSwitch(0, 3, 2, 121), new ContextSwitch(0, 5, 3, 124), new ContextSwitch(120, 2, 1, 123), new ContextSwitch(300, 1, 1, 122), new ContextSwitch(1800, 4, 2, 125), new ContextSwitch(3540, 2, 1, 119), new ContextSwitch(3600, 1, 1, 120), }.ToObservable(); Console.WriteLine("Figure 11: Complete Pass-Through Trill Query Program"); var cSTicksEventObs = cSTicksObs.Select( e => StreamEvent.CreateInterval(e.CSTicks, e.CSTicks + 1, e)); var cSTicksStream = cSTicksEventObs.ToStreamable(DisorderPolicy.Drop()); var origCSTicksEventObs = cSTicksStream.ToStreamEventObservable(); origCSTicksEventObs.Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}\tCPUTemp={5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.CPUTemp)).Wait(); Console.WriteLine(); #endregion #region Section 3 Console.WriteLine("Figure 13: Where Query Code"); var cSTicks2Cores = cSTicksStream.Where(p => p.CID == 1 || p.CID == 2); cSTicks2Cores.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}\tCPUTemp={5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.CPUTemp)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 16: Select Query Code"); var cSNarrowTicks2Cores = cSTicks2Cores.Select( e => new { CSTicks = e.CSTicks, PID = e.PID, CID = e.CID }); cSNarrowTicks2Cores.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 17: Alternate Select Query Code"); var cSNarrowTicks2Cores2 = cSTicks2Cores.Select( e => new { CSTicks = e.CSTicks, PID = e.PID, CID = e.CID }); cSNarrowTicks2Cores2.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 19: Where and Select with the LinQ Comprehension Syntax"); var cSNarrowTicks2Cores3 = from e in cSTicksStream where e.CID == 1 || e.CID == 2 select new { e.CSTicks, e.PID, e.CID }; cSNarrowTicks2Cores3.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID)).Wait(); Console.WriteLine(); #endregion #region Section 4 Console.WriteLine("Figure 22: Join Query Code"); var processNamesObs = new[] { new ProcessName(1, "Word"), new ProcessName(2, "Internet Explorer"), new ProcessName(3, "Excel"), new ProcessName(4, "Visual Studio"), new ProcessName(5, "Outlook"), }.ToObservable(); var pNamesStream = processNamesObs. Select(e => StreamEvent.CreateInterval(0, 10000, e)). ToStreamable(); var cSTicks2CoresWithPNames = cSNarrowTicks2Cores.Join(pNamesStream, e => e.PID, e => e.PID, (leftPayload, rightPayload) => new { leftPayload.CSTicks, leftPayload.PID, leftPayload.CID, PName = rightPayload.PName }); cSTicks2CoresWithPNames.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}\tPName={5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.PName)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 24: Join Query Comprehension Syntax"); var cSTicks2CoresWithPNames2 = from leftPayload in cSNarrowTicks2Cores join rightPayload in pNamesStream on leftPayload.PID equals rightPayload.PID select new { leftPayload.CSTicks, leftPayload.PID, leftPayload.CID, PName = rightPayload.PName }; cSTicks2CoresWithPNames2.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}\tPName={5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.PName)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 25: Entire Join Query Comprehension Syntax"); var cSTicks2CoresWithPNames3 = from leftPayload in cSTicksStream join rightPayload in pNamesStream on leftPayload.PID equals rightPayload.PID where leftPayload.CID == 1 || leftPayload.CID == 2 select new { leftPayload.CSTicks, leftPayload.PID, leftPayload.CID, rightPayload.PName }; cSTicks2CoresWithPNames3.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}\tPName={5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.PName)).Wait(); Console.WriteLine(); #endregion #region Section 5 Console.WriteLine("Figure 26: AlterEventDuration Query Code"); var infinitecSTicks2Cores = cSTicks2CoresWithPNames.AlterEventDuration(StreamEvent.InfinitySyncTime); infinitecSTicks2Cores.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}\tPName={5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.PName)).Wait(); Console.WriteLine(); #endregion Section 6 #region Section 6 Console.WriteLine("Figure 28: ClipEventDuration Query Code"); var clippedCSTicks2Cores = infinitecSTicks2Cores. ClipEventDuration(infinitecSTicks2Cores, e => e.CID, e => e.CID); clippedCSTicks2Cores.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}\tPName={5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.PName)).Wait(); Console.WriteLine(); #endregion #region Section 7 Console.WriteLine("Figure 30: Multicast Version of ClipEventDuration Query Code"); var clippedCSTicks2Cores2 = infinitecSTicks2Cores.Multicast( s => s.ClipEventDuration(s, e => e.CID, e => e.CID)); clippedCSTicks2Cores2.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}\tPName={5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.PName)).Wait(); Console.WriteLine(); #endregion #region Section 8 Console.WriteLine("Figure 32: ShiftEventLifetime Query Code"); var shiftedClippedCS = clippedCSTicks2Cores.ShiftEventLifetime(startTime => 1); shiftedClippedCS.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks={2}\tPID={3}\tCID={4}\tPName={5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.PName)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 34: Timeslices Query Code"); var timeslices = shiftedClippedCS.Join(cSTicks2CoresWithPNames, e => e.CID, e => e.CID, (left, right) => new { left.PID, left.CID, left.PName, Timeslice = right.CSTicks - left.CSTicks }); timeslices.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tPID={2}\tCID={3}\tPName={4}\tTimeslice={5}", e.StartTime, e.EndTime, e.Payload.PID, e.Payload.CID, e.Payload.PName, e.Payload.Timeslice)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 36: Timeslices Query Code Using Multicast"); var timeslices2 = cSTicks2CoresWithPNames.Multicast( t => t.AlterEventDuration(StreamEvent.InfinitySyncTime). Multicast(s => s.ClipEventDuration(s, e => e.CID, e => e.CID)). ShiftEventLifetime(startTime => 1). Join(t, e => e.CID, e => e.CID, (left, right) => new { left.PID, left.CID, left.PName, Timeslice = right.CSTicks - left.CSTicks })); timeslices2.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tPID={2}\tCID={3}\tPName={4}\tTimeslice={5}", e.StartTime, e.EndTime, e.Payload.PID, e.Payload.CID, e.Payload.PName, e.Payload.Timeslice)).Wait(); Console.WriteLine(); #endregion #region Section 9 Console.WriteLine("Figure 40: Rassigning Timeslice Lifetimes with AlterEventLifetime"); var pID1CID1Timeslices = timeslices.Where(e => e.PID == 1 && e.CID == 1); var windowedTimeslices = pID1CID1Timeslices. AlterEventLifetime(origStartTime => (1 + (origStartTime - 1) / 3600) * 3600, 3600); windowedTimeslices.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tPID={2}\tCID={3}\tPName={4}\tTimeslice={5}", e.StartTime, e.EndTime, e.Payload.PID, e.Payload.CID, e.Payload.PName, e.Payload.Timeslice)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 41: Reassigning Lifetimes with HoppingWindowLifetime"); var windowedTimeslices2 = pID1CID1Timeslices.HoppingWindowLifetime(3600, 3600); windowedTimeslices2.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tPID={2}\tCID={3}\tPName={4}\tTimeslice={5}", e.StartTime, e.EndTime, e.Payload.PID, e.Payload.CID, e.Payload.PName, e.Payload.Timeslice)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 42: Sum Query Code"); var totalConsumptionPerPeriod = windowedTimeslices.Sum(e => e.Timeslice); totalConsumptionPerPeriod.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tPayload={2}", e.StartTime, e.EndTime, e.Payload)).Wait(); Console.WriteLine(); #endregion #region Section 10 Console.WriteLine("Figure 44: Group and Apply Query Code"); var totalConsumptionPerPeriodAllCoresAllProcesses = timeslices.GroupApply( e => new { e.CID, e.PID, e.PName }, s => s.HoppingWindowLifetime(3600, 3600).Sum(e => e.Timeslice), (g, p) => new { g.Key.CID, g.Key.PName, TotalTime = p }); totalConsumptionPerPeriodAllCoresAllProcesses.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCID={2}\tPName={3}\tTotaltime={4}", e.StartTime, e.EndTime, e.Payload.CID, e.Payload.PName, e.Payload.TotalTime)).Wait(); Console.WriteLine(); #endregion #region Section 11 Console.WriteLine("Figure 49: Chop Query Code"); Console.WriteLine("NB: This query is expected to fail!"); var altCSTicksObs = new[] { new ContextSwitch(0, 1, 1, 120), new ContextSwitch(0, 3, 2, 121), new ContextSwitch(0, 5, 3, 124), new ContextSwitch(120, 2, 1, 123), new ContextSwitch(300, 1, 1, 122), new ContextSwitch(1800, 4, 2, 125), new ContextSwitch(3540, 2, 1, 119), new ContextSwitch(3600, 1, 1, 120), new ContextSwitch(5400, 3, 2, 122), new ContextSwitch(7200, 4, 2, 121), }.ToObservable(); var altCSTicksEventObs = altCSTicksObs.Select( e => StreamEvent.CreateInterval(e.CSTicks, e.CSTicks + 1, e)); var altCSTicksStream = altCSTicksEventObs.ToStreamable(DisorderPolicy.Drop()); var cSTicksWithExtraCS = altCSTicksStream.AlterEventDuration(StreamEvent.InfinitySyncTime). Multicast(s => s.ClipEventDuration(s, e => e.CID, e => e.CID)). Chop(0, 3600). Select((origStartTime, e) => new { CSTicks = origStartTime, e.PID, e.CID, e.CPUTemp }). AlterEventDuration(1); try { cSTicksWithExtraCS.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks{2}\tPID={3}\tCID={4}\tCPUTemp{5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.CPUTemp)).Wait(); } catch (AggregateException e) { foreach (var ex in e.InnerExceptions) { Console.WriteLine("{0}", ex.Message); } } catch (Exception e) { Console.WriteLine("{0}", e.Message); } Console.WriteLine(); Console.WriteLine("Figure 51: Improved Chop Query Code"); var cSTicksWithExtraCSImp = altCSTicksStream. AlterEventDuration(StreamEvent.InfinitySyncTime). Multicast(s => s.ClipEventDuration(s, e => e.CID, e => e.CID)). Join(new[] { StreamEvent.CreateInterval(0, 10800, Unit.Default) }. ToObservable().ToStreamable(), (left, right) => left).Chop(0, 3600).Select((origStartTime, e) => new { e.CID, e.PID, e.CPUTemp, CSTicks = origStartTime }). AlterEventDuration(1); cSTicksWithExtraCSImp.ToStreamEventObservable().Where(e => e.IsData).ForEachAsync(e => Console.WriteLine( "Start Time={0}\tEnd Time={1}\tCSTicks{2}\tPID={3}\tCID={4}\tCPUTemp{5}", e.StartTime, e.EndTime, e.Payload.CSTicks, e.Payload.PID, e.Payload.CID, e.Payload.CPUTemp)).Wait(); Console.WriteLine(); #endregion #region Section 12 Console.WriteLine("Figure 53: Out of Order Input (Throw)"); var ooStreamableThrow = new[] { StreamEvent.CreateInterval(10, 100, 1), StreamEvent.CreateInterval(0, 50, 2), StreamEvent.CreateInterval(0, 10, 3), StreamEvent.CreateInterval(11, 90, 4) }.ToObservable().ToStreamable(DisorderPolicy.Throw()); try { ooStreamableThrow.ToStreamEventObservable().Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); } catch (Exception e) { Console.WriteLine("{0}", e.Message); } Console.WriteLine(); Console.WriteLine("Figure 54: Out of Order Input (Drop)"); var ooStreamableDrop = new[] { StreamEvent.CreateInterval(10, 100, 1), StreamEvent.CreateInterval(0, 50, 2), StreamEvent.CreateInterval(0, 10, 3), StreamEvent.CreateInterval(11, 90, 4) }.ToObservable().ToStreamable(DisorderPolicy.Drop()); ooStreamableDrop.ToStreamEventObservable().Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 55: Out of Order Input (Adjust)"); var ooStreamableAdjust = new[] { StreamEvent.CreateInterval(10, 100, 1), StreamEvent.CreateInterval(0, 50, 2), StreamEvent.CreateInterval(0, 10, 3), StreamEvent.CreateInterval(11, 90, 4) }.ToObservable().ToStreamable(DisorderPolicy.Adjust()); ooStreamableAdjust.ToStreamEventObservable().Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 57: Creating PNamesStream with Edge Events"); var pNamesStream2 = processNamesObs.Select(e => StreamEvent.CreateStart(0, e)). Concat(processNamesObs.Select( e => StreamEvent.CreateEnd(10000, 0, e))). ToStreamable(); pNamesStream2.ToStreamEventObservable().Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 58: Creating PNameStream using Interval and Edge Events"); var processNamesObs1 = new[] { new ProcessName(1, "Word"), new ProcessName(2, "Internet Explorer"), new ProcessName(3, "Excel"), }.ToObservable(); var processNamesObs2 = new[] { new ProcessName(4, "Visual Studio"), new ProcessName(5, "Outlook"), }.ToObservable(); var pNamesStream3 = processNamesObs1.Select(e => StreamEvent.CreateInterval(0, 10000, e)). Concat(processNamesObs2.Select(e => StreamEvent.CreateStart(0, e))). Concat(processNamesObs2.Select(e => StreamEvent.CreateEnd(10000, 0, e))). ToStreamable(); pNamesStream3.ToStreamEventObservable().Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 59: Coalescing Matching Edges"); pNamesStream3.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges).Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 60: Input with Punctuations"); var streamablePunctuations = new[] { StreamEvent.CreateInterval(0, 1, 1), StreamEvent.CreateInterval(3, 4, 2), StreamEvent.CreatePunctuation <int>(10), StreamEvent.CreatePunctuation <int>(20), StreamEvent.CreatePunctuation <int>(30), StreamEvent.CreatePunctuation <int>(40), StreamEvent.CreateInterval(40, 41, 3) }.ToObservable().ToStreamable(DisorderPolicy.Drop()); streamablePunctuations.ToStreamEventObservable().Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); /* * Console.WriteLine("Figure 61: Input with Generated Punctuations After Every Event"); * var streamableIthEventPunctuations = new[] * { * StreamEvent.CreateInterval(0, 1, 1), * StreamEvent.CreateInterval(3, 4, 2), * StreamEvent.CreateInterval(40, 41, 3) * }.ToObservable().ToStreamable(DisorderPolicy.Drop(), * PeriodicPunctuationPolicy.Count(1)); * streamableIthEventPunctuations.ToStreamEventObservable().Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); * Console.WriteLine(); */ Console.WriteLine("Figure 62: Input with Generated Punctuations After 10 Tick Periods"); var streamableTimePeriodEventPunctuations = new[] { StreamEvent.CreateInterval(0, 1, 1), StreamEvent.CreateInterval(10, 4, 2), StreamEvent.CreateInterval(19, 4, 3), StreamEvent.CreateInterval(40, 41, 4) }.ToObservable().ToStreamable(DisorderPolicy.Drop(), FlushPolicy.FlushOnPunctuation, PeriodicPunctuationPolicy.Time(10)); streamableTimePeriodEventPunctuations.ToStreamEventObservable().Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 63: Query with No Output"); var IncompleteOutputQuery1 = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2) }.ToObservable().ToStreamable().Count().ToStreamEventObservable(); IncompleteOutputQuery1.Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 64: Query with Output up to Time 1"); var IncompleteOutputQuery2 = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2), StreamEvent.CreatePunctuation <int>(1) }.ToObservable().ToStreamable().Count().ToStreamEventObservable(); IncompleteOutputQuery2.Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 65: Alternate Query with Output up to Time 1"); var IncompleteOutputQuery3 = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2) }.ToObservable().ToStreamable().Count().ToStreamEventObservable(); IncompleteOutputQuery3.Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 66: Query with all Output"); var CompleteOutputQuery1 = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2), StreamEvent.CreatePunctuation <int>(StreamEvent.InfinitySyncTime) }.ToObservable().ToStreamable().Count().ToStreamEventObservable(); CompleteOutputQuery1.Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 67: Alternate Query with all Output"); var CompleteOutputQuery2 = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2) }.ToObservable().ToStreamable().Count(). ToStreamEventObservable(); CompleteOutputQuery2.Where(e => e.IsData || e.IsPunctuation).ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine("The end ..."); #endregion }
public static void Main(string[] args) { // This program is a supplement to the Trill Query Writing Guide #region Section 2 IObservable <ContextSwitch> contextSwitchObservable = new[] { new ContextSwitch(0, 1, 1, 120), new ContextSwitch(0, 3, 2, 121), new ContextSwitch(0, 5, 3, 124), new ContextSwitch(120, 2, 1, 123), new ContextSwitch(300, 1, 1, 122), new ContextSwitch(1800, 4, 2, 125), new ContextSwitch(3540, 2, 1, 119), new ContextSwitch(3600, 1, 1, 120), }.ToObservable(); Console.WriteLine("Figure 11: Complete Pass-Through Trill Query Program"); IObservable <StreamEvent <ContextSwitch> > contextSwitchStreamEventObservable = contextSwitchObservable.Select(e => StreamEvent.CreateInterval(e.Tick, e.Tick + 1, e)); IObservableIngressStreamable <ContextSwitch> contextSwitchIngressStreamable = contextSwitchStreamEventObservable.ToStreamable(DisorderPolicy.Drop()); var contextSwitchStreamable = (IStreamable <Empty, ContextSwitch>)contextSwitchIngressStreamable; IObservable <StreamEvent <ContextSwitch> > passthroughContextSwitchStreamEventObservable = contextSwitchStreamable.ToStreamEventObservable(); passthroughContextSwitchStreamEventObservable.Where(e => e.IsData) .ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 12: Non-StreamEvent Passthrough"); var payloadStreamable = contextSwitchObservable.ToTemporalStreamable(cs => cs.Tick); var passthroughPayloadObservable = payloadStreamable.ToTemporalObservable((start, cs) => cs); passthroughPayloadObservable.ForEachAsync(cs => Console.WriteLine(cs.ToString())).Wait(); Console.WriteLine(); #endregion #region Section 3 Console.WriteLine("Figure 14: Where Query Code"); var contextSwitchTwoCores = contextSwitchStreamable.Where(p => p.CpuId == 1 || p.CpuId == 2); contextSwitchTwoCores.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => WriteEvent(e)) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 17: Select Query Code"); var contextSwitchTwoCoresNoTemp = contextSwitchTwoCores.Select( e => new { e.Tick, e.ProcessId, e.CpuId }); contextSwitchTwoCoresNoTemp.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\t" + $"Tick = {e.Payload.Tick, 4}\tProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}")) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 18: Alternate Select Query Code"); contextSwitchTwoCoresNoTemp = contextSwitchTwoCores.Select( e => new { e.Tick, e.ProcessId, e.CpuId }); contextSwitchTwoCoresNoTemp.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\t" + $"Tick = {e.Payload.Tick, 4}\tProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}")) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 20: Where and Select with the LINQ Comprehension Syntax"); contextSwitchTwoCoresNoTemp = from e in contextSwitchStreamable where e.CpuId == 1 || e.CpuId == 2 select new { e.Tick, e.ProcessId, e.CpuId }; contextSwitchTwoCoresNoTemp.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\t" + $"Tick = {e.Payload.Tick, 4}\tProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}")) .Wait(); Console.WriteLine(); #endregion #region Section 4 Console.WriteLine("Figure 23: Join Query Code"); var processNamesObservable = new[] { new ProcessName(1, "Word"), new ProcessName(2, "Internet Explorer"), new ProcessName(3, "Excel"), new ProcessName(4, "Visual Studio"), new ProcessName(5, "Outlook"), }.ToObservable(); var namesStream = processNamesObservable. Select(e => StreamEvent.CreateInterval(0, 10000, e)). ToStreamable(); var contextSwitchWithNames = contextSwitchTwoCoresNoTemp.Join(namesStream, e => e.ProcessId, e => e.ProcessId, (leftPayload, rightPayload) => new { leftPayload.Tick, leftPayload.ProcessId, leftPayload.CpuId, rightPayload.Name }); contextSwitchWithNames.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\t" + $"Tick = {e.Payload.Tick, 4}\tProcessId = {e.Payload.ProcessId}\t" + $"CpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}")) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 25: Join Query Comprehension Syntax"); contextSwitchWithNames = from leftPayload in contextSwitchTwoCoresNoTemp join rightPayload in namesStream on leftPayload.ProcessId equals rightPayload.ProcessId select new { leftPayload.Tick, leftPayload.ProcessId, leftPayload.CpuId, rightPayload.Name }; contextSwitchWithNames.ToStreamEventObservable().Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\t" + $"Tick = {e.Payload.Tick, 4}\tProcessId = {e.Payload.ProcessId}\t" + $"CpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}")) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 26: Entire Join Query Comprehension Syntax"); contextSwitchWithNames = from leftPayload in contextSwitchStreamable join rightPayload in namesStream on leftPayload.ProcessId equals rightPayload.ProcessId where leftPayload.CpuId == 1 || leftPayload.CpuId == 2 select new { leftPayload.Tick, leftPayload.ProcessId, leftPayload.CpuId, rightPayload.Name }; contextSwitchWithNames.ToStreamEventObservable().Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\t" + $"Tick = {e.Payload.Tick, 4}\t" + $"ProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}")) .Wait(); Console.WriteLine(); #endregion #region Section 5 Console.WriteLine("Figure 27: AlterEventDuration Query Code"); var infiniteContextSwitch = contextSwitchWithNames.AlterEventDuration(StreamEvent.InfinitySyncTime); infiniteContextSwitch.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 20}\tTick = {e.Payload.Tick, 4}\t" + $"ProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}")) .Wait(); Console.WriteLine(); #endregion #region Section 6 Console.WriteLine("Figure 29: ClipEventDuration Query Code"); var clippedContextSwitch = infiniteContextSwitch .ClipEventDuration(infiniteContextSwitch, e => e.CpuId, e => e.CpuId); clippedContextSwitch.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges) .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 20}\tTick = {e.Payload.Tick, 4}\t" + $"ProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}")) .Wait(); Console.WriteLine(); #endregion #region Section 7 Console.WriteLine("Figure 31: Multicast Version of ClipEventDuration Query Code"); clippedContextSwitch = infiniteContextSwitch.Multicast( s => s.ClipEventDuration(s, e => e.CpuId, e => e.CpuId)); clippedContextSwitch.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges) .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 20}\tTick = {e.Payload.Tick, 4}\t" + $"ProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}")) .Wait(); Console.WriteLine(); #endregion #region Section 8 Console.WriteLine("Figure 33: ShiftEventLifetime Query Code"); var shiftedClippedContextSwitch = clippedContextSwitch.ShiftEventLifetime(1); shiftedClippedContextSwitch.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges) .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 20}\tTick = {e.Payload.Tick, 4}\t" + $"ProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}")) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 35: Timeslices Query Code"); var timeslices = shiftedClippedContextSwitch.Join(contextSwitchWithNames, e => e.CpuId, e => e.CpuId, (left, right) => new { left.ProcessId, left.CpuId, left.Name, Timeslice = right.Tick - left.Tick }); timeslices.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges) .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\tProcessId = {e.Payload.ProcessId}\t" + $"CpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}\tTimeslice = {e.Payload.Timeslice}")) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 37: Timeslices Query Code Using Multicast"); timeslices = contextSwitchWithNames.Multicast(t => t .AlterEventDuration(StreamEvent.InfinitySyncTime) .Multicast(s => s .ClipEventDuration(s, e => e.CpuId, e => e.CpuId)) .ShiftEventLifetime(1) .Join(t, e => e.CpuId, e => e.CpuId, (left, right) => new { left.ProcessId, left.CpuId, left.Name, Timeslice = right.Tick - left.Tick })); timeslices.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges) .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\tProcessId = {e.Payload.ProcessId}\t" + $"CpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}\tTimeslice = {e.Payload.Timeslice}")) .Wait(); Console.WriteLine(); #endregion #region Section 9 Console.WriteLine("Figure 41: Rassigning Timeslice Lifetimes with AlterEventLifetime"); var timeslicesForProcess1Cpu1 = timeslices.Where(e => e.ProcessId == 1 && e.CpuId == 1); var windowedTimeslicesForProcess1Cpu1 = timeslicesForProcess1Cpu1. AlterEventLifetime(origStartTime => (1 + ((origStartTime - 1) / 3600)) * 3600, 3600); windowedTimeslicesForProcess1Cpu1.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\tProcessId = {e.Payload.ProcessId}\t" + $"CpuId = {e.Payload.CpuId}\tName = {e.Payload.Name}\tTimeslice = {e.Payload.Timeslice}")) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 42: Reassigning Lifetimes with HoppingWindowLifetime"); var windowedTimeslices2 = timeslicesForProcess1Cpu1.HoppingWindowLifetime(3600, 3600); windowedTimeslices2.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\tProcessId = {e.Payload.ProcessId}\t" + $"CpuId = {e.Payload.CpuId}\tName = {e.Payload.Name}\tTimeslice = {e.Payload.Timeslice}")) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 43: Sum Query Code"); var totalConsumptionPerPeriodForProcess1Cpu1 = windowedTimeslicesForProcess1Cpu1.Sum(e => e.Timeslice); totalConsumptionPerPeriodForProcess1Cpu1.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges) .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\tPayload = {e.Payload}")) .Wait(); Console.WriteLine(); #endregion #region Section 10 Console.WriteLine("Figure 45: Group and Apply Query Code"); var totalConsumptionPerPeriod = timeslices.GroupApply( e => new { e.CpuId, e.ProcessId, e.Name }, s => s.HoppingWindowLifetime(3600, 3600).Sum(e => e.Timeslice), (g, p) => new { g.Key.CpuId, g.Key.Name, TotalTime = p }); totalConsumptionPerPeriod.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges) .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\t" + $"CpuId = {e.Payload.CpuId}\tName = {e.Payload.Name, 18}\tTotalTime = {e.Payload.TotalTime}")) .Wait(); Console.WriteLine(); #endregion #region Section 11 Console.WriteLine("Figure 50: Chop Query Code"); Console.WriteLine("NB: This query is expected to fail!"); var alternativeContextSwitchStream = new[] { new ContextSwitch(0, 1, 1, 120), new ContextSwitch(0, 3, 2, 121), new ContextSwitch(0, 5, 3, 124), new ContextSwitch(120, 2, 1, 123), new ContextSwitch(300, 1, 1, 122), new ContextSwitch(1800, 4, 2, 125), new ContextSwitch(3540, 2, 1, 119), new ContextSwitch(3600, 1, 1, 120), new ContextSwitch(5400, 3, 2, 122), new ContextSwitch(7200, 4, 2, 121), }.ToObservable() .Select(e => StreamEvent.CreateInterval(e.Tick, e.Tick + 1, e)) .ToStreamable(DisorderPolicy.Drop()); var contextSwitchChoppedUnbounded = alternativeContextSwitchStream .AlterEventDuration(StreamEvent.InfinitySyncTime) .Multicast(s => s.ClipEventDuration(s, e => e.CpuId, e => e.CpuId)) .Chop(0, 3600) .Select((origStartTime, e) => new { Tick = origStartTime, e.ProcessId, e.CpuId, e.CpuTemp }) .AlterEventDuration(1); try { contextSwitchChoppedUnbounded.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\tTick{e.Payload.Tick, 4}\t" + $"ProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}\tCPUTemp{e.Payload.CpuTemp}")) .Wait(); } catch (AggregateException e) { foreach (var ex in e.InnerExceptions) { Console.WriteLine("{0}", ex.Message); } } catch (Exception e) { Console.WriteLine("{0}", e.Message); } Console.WriteLine(); Console.WriteLine("Figure 52: Improved Chop Query Code"); var fixedInterval = new[] { StreamEvent.CreateInterval(0, 10800, Unit.Default) } .ToObservable().ToStreamable(); var contextSwitchChopped = alternativeContextSwitchStream .AlterEventDuration(StreamEvent.InfinitySyncTime) .Multicast(s => s.ClipEventDuration(s, e => e.CpuId, e => e.CpuId)) .Join(fixedInterval, (left, right) => left) .Chop(0, 3600) .Select((origStartTime, e) => new { e.CpuId, e.ProcessId, e.CpuTemp, Tick = origStartTime }) .AlterEventDuration(1); contextSwitchChopped.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"StartTime = {e.StartTime, 4}\tEndTime = {e.EndTime, 4}\tTick = {e.Payload.Tick, 4}\t" + $"ProcessId = {e.Payload.ProcessId}\tCpuId = {e.Payload.CpuId}\tCPUTemp = {e.Payload.CpuTemp}")) .Wait(); Console.WriteLine(); #endregion #region Section 12 Console.WriteLine("Figure 54: Final Query"); var choppedContextSwitch = alternativeContextSwitchStream .Where(cs => cs.CpuId == 1 || cs.CpuId == 2) .AlterEventDuration(StreamEvent.InfinitySyncTime) .Multicast(s => s.ClipEventDuration(s, e => e.CpuId, e => e.CpuId)) .Join(fixedInterval, (left, right) => left) .Chop(0, 3600) .Select((start, e) => new { Tick = start, e.ProcessId, e.CpuId, e.CpuTemp }) .AlterEventDuration(1); var choppedContextSwitchWithNames = choppedContextSwitch .Join(namesStream, e => e.ProcessId, e => e.ProcessId, (left, right) => new { left.Tick, left.ProcessId, left.CpuId, right.Name }); var timeslicesPerCpu = choppedContextSwitchWithNames .Multicast(t => t .AlterEventDuration(StreamEvent.InfinitySyncTime) .Multicast(s => s.ClipEventDuration(s, e => e.CpuId, e => e.CpuId)) .ShiftEventLifetime(1) .Join(t, e => e.CpuId, e => e.CpuId, (left, right) => new { left.ProcessId, left.CpuId, left.Name, Timeslice = right.Tick - left.Tick })); var mostCpuConsumedPerPeriod = timeslicesPerCpu .GroupApply( e => new { e.ProcessId, e.Name }, s => s.HoppingWindowLifetime(3600, 3600).Sum(e => e.Timeslice), (g, p) => new { g.Key.Name, TotalTime = p }) .Max((l, r) => l.TotalTime.CompareTo(r.TotalTime)) .Select((startTime, payload) => new { PeriodStart = startTime - 3600, PeriodEnd = startTime, ProcessName = payload.Name, TotalCpuConsumed = payload.TotalTime }); mostCpuConsumedPerPeriod.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges) .Where(e => e.IsData) .ForEachAsync(e => Console.WriteLine( $"PeriodStart = {e.Payload.PeriodStart, 4}\tPeriodEnd = {e.Payload.PeriodEnd, 4}\t" + $"Name = {e.Payload.ProcessName}\tTotalTime = {e.Payload.TotalCpuConsumed}")) .Wait(); Console.WriteLine(); #endregion #region Section 13.1 Console.WriteLine("Figure 56: Out of Order Input (Throw)"); var outOfOrderStreamableThrow = new[] { StreamEvent.CreateInterval(10, 100, 1), StreamEvent.CreateInterval(0, 50, 2), StreamEvent.CreateInterval(0, 10, 3), StreamEvent.CreateInterval(11, 90, 4) }.ToObservable().ToStreamable(DisorderPolicy.Throw()); try { outOfOrderStreamableThrow.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => WriteEvent(e)) .Wait(); } catch (Exception e) { Console.WriteLine("{0}", e.Message); } Console.WriteLine(); Console.WriteLine("Figure 57: Out of Order Input (Drop)"); var outOfOrderStreamableDrop = new[] { StreamEvent.CreateInterval(10, 100, 1), StreamEvent.CreateInterval(0, 50, 2), StreamEvent.CreateInterval(0, 10, 3), StreamEvent.CreateInterval(11, 90, 4) }.ToObservable().ToStreamable(DisorderPolicy.Drop()); outOfOrderStreamableDrop.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => WriteEvent(e)) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 58: Out of Order Input (Adjust)"); var outOfOrderStreamableAdjust = new[] { StreamEvent.CreateInterval(10, 100, 1), StreamEvent.CreateInterval(0, 50, 2), StreamEvent.CreateInterval(0, 10, 3), StreamEvent.CreateInterval(11, 90, 4) }.ToObservable().ToStreamable(DisorderPolicy.Adjust()); outOfOrderStreamableAdjust.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => WriteEvent(e)) .Wait(); Console.WriteLine(); #endregion #region Section 13.3 Console.WriteLine("Figure 60: Creating namesStream with Edge Events"); namesStream = processNamesObservable.Select(e => StreamEvent.CreateStart(0, e)). Concat(processNamesObservable.Select(e => StreamEvent.CreateEnd(10000, 0, e))). ToStreamable(); namesStream.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => WriteEvent(e)) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 61: Creating namesStream using Interval and Edge Events"); var namesObservable1 = new[] { new ProcessName(1, "Word"), new ProcessName(2, "Internet Explorer"), new ProcessName(3, "Excel"), }.ToObservable(); var namesObservable2 = new[] { new ProcessName(4, "Visual Studio"), new ProcessName(5, "Outlook"), }.ToObservable(); namesStream = namesObservable1.Select(e => StreamEvent.CreateInterval(0, 10000, e)) .Concat(namesObservable2.Select(e => StreamEvent.CreateStart(0, e))) .Concat(namesObservable2.Select(e => StreamEvent.CreateEnd(10000, 0, e))) .ToStreamable(); namesStream.ToStreamEventObservable() .Where(e => e.IsData) .ForEachAsync(e => WriteEvent(e)) .Wait(); Console.WriteLine(); Console.WriteLine("Figure 62: Coalescing Matching Edges"); namesStream.ToStreamEventObservable(ReshapingPolicy.CoalesceEndEdges) .Where(e => e.IsData) .ForEachAsync(e => WriteEvent(e)) .Wait(); Console.WriteLine(); #endregion #region Section 13.4 Console.WriteLine("Figure 63: Input with Punctuations"); var streamablePunctuations = new[] { StreamEvent.CreateInterval(0, 1, 1), StreamEvent.CreateInterval(3, 4, 2), StreamEvent.CreatePunctuation <int>(10), StreamEvent.CreatePunctuation <int>(20), StreamEvent.CreatePunctuation <int>(30), StreamEvent.CreatePunctuation <int>(40), StreamEvent.CreateInterval(40, 41, 3) }.ToObservable().ToStreamable(DisorderPolicy.Drop(), FlushPolicy.FlushOnPunctuation, null, OnCompletedPolicy.None); streamablePunctuations.ToStreamEventObservable() .ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 64: Input with Generated Punctuations After 10 Tick Periods"); var streamableTimePeriodEventPunctuations = new[] { StreamEvent.CreateInterval(0, 1, 1), StreamEvent.CreateInterval(10, 4, 2), StreamEvent.CreateInterval(19, 4, 3), StreamEvent.CreateInterval(40, 41, 4) }.ToObservable().ToStreamable(DisorderPolicy.Drop(), FlushPolicy.FlushOnPunctuation, PeriodicPunctuationPolicy.Time(10), OnCompletedPolicy.None); streamableTimePeriodEventPunctuations.ToStreamEventObservable() .ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 65: Query with No Output"); var incompleteOutputQuery = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2) }.ToObservable() .ToStreamable(null, FlushPolicy.FlushOnPunctuation, null, OnCompletedPolicy.None) .Count() .ToStreamEventObservable(); incompleteOutputQuery.ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 66: Query with Output up to Time 1"); incompleteOutputQuery = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2), StreamEvent.CreatePunctuation <int>(1) }.ToObservable() .ToStreamable(null, FlushPolicy.FlushOnPunctuation, null, OnCompletedPolicy.None) .Count() .ToStreamEventObservable(); incompleteOutputQuery.ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 67: Alternate Query with Output up to Time 1"); incompleteOutputQuery = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2) }.ToObservable() .ToStreamable(null, FlushPolicy.FlushOnPunctuation, null, OnCompletedPolicy.Flush) .Count() .ToStreamEventObservable(); incompleteOutputQuery.ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 68: Query with all Output"); var completeOutputQuery = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2), StreamEvent.CreatePunctuation <int>(StreamEvent.InfinitySyncTime) }.ToObservable() .ToStreamable(null, FlushPolicy.FlushOnPunctuation, null, OnCompletedPolicy.None) .Count() .ToStreamEventObservable(); completeOutputQuery.ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); Console.WriteLine("Figure 69: Alternate Query with all Output"); completeOutputQuery = new[] { StreamEvent.CreateInterval(0, 10, 1), StreamEvent.CreateInterval(1, 11, 2) }.ToObservable() .ToStreamable(null, FlushPolicy.FlushOnPunctuation, null, OnCompletedPolicy.EndOfStream) .Count() .ToStreamEventObservable(); completeOutputQuery.ForEachAsync(e => WriteEvent(e)).Wait(); Console.WriteLine(); #endregion Console.ReadLine(); }
private QueryContainer CreateQuery() { var query = new QueryContainer(); Config.ForceRowBasedExecution = true; // incoming events are received via a conduit _tweetConduit = new Subject <StreamEvent <Tweet> >(); var streamInput = query.RegisterInput(_tweetConduit, OnCompletedPolicy.None(), DisorderPolicy.Drop(TimeSpan.FromSeconds(3).Ticks), PeriodicPunctuationPolicy.Time((ulong)TimeSpan.FromMilliseconds(1).Ticks)); // outgoing events are pushed to the dashboard var myOutput = query.RegisterOutput(TwitterAnalytics(streamInput), ReshapingPolicy.None()); myOutput.Subscribe(tweetEvent => Publish(tweetEvent)); return(query); }
public void LowWatermarkAndPunctuationGeneration() { SetupQuery(DisorderPolicy.Throw(), PartitionedFlushPolicy.None, PeriodicPunctuationPolicy.Time(generationPeriod: 20), PeriodicLowWatermarkPolicy.Time(generationPeriod: 50, lowWatermarkTimestampLag: 0)); // This establishes three partitions with keys 0,1 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 0, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 0, 1)); // These points do not generate punctuations or low watermarks since neither period has lapsed. this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 15, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 19, 1)); // These points generate punctuations (period of 20) but not low watermarks (period of 50) this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 22, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 20, 1)); // This point generates a low watermark, since it is >= the last watermark (none/0) + the low watermark // generation period of 50 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 50, 0)); // These points do not generate punctuations, even though "punctuations" specifically haven't been generated // for these partitions since time 22/20, because the low watermark at 50 supersedes punctuations. this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 55, 1)); // Punctuation generation continues once the punctuation generation period lapses from the low watermark this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 70, 2)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 71, 1)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 90, 2)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 91, 1)); var expected = new PartitionedStreamEvent <int, int>[] { PartitionedStreamEvent.CreatePoint(0, 0, 0), PartitionedStreamEvent.CreatePoint(1, 0, 1), PartitionedStreamEvent.CreatePoint(0, 15, 0), PartitionedStreamEvent.CreatePoint(1, 19, 1), // Punctuations generated after the punctuation period of 20 from time 0, snapped to the leftmost generationPeriod boundary PartitionedStreamEvent.CreatePunctuation <int, int>(0, 20), PartitionedStreamEvent.CreatePoint(0, 22, 0), PartitionedStreamEvent.CreatePunctuation <int, int>(1, 20), PartitionedStreamEvent.CreatePoint(1, 20, 1), // Low watermark generated after the low watermark period of 50 from time 0 PartitionedStreamEvent.CreateLowWatermark <int, int>(50), PartitionedStreamEvent.CreatePoint(0, 50, 0), PartitionedStreamEvent.CreatePoint(1, 55, 1), // Punctuations generated after the punctuation period of 20 from time 50 (low watermark time), snapped to the leftmost generationPeriod boundary PartitionedStreamEvent.CreatePunctuation <int, int>(0, 60), PartitionedStreamEvent.CreatePoint(0, 70, 2), PartitionedStreamEvent.CreatePunctuation <int, int>(1, 60), PartitionedStreamEvent.CreatePoint(1, 71, 1), // Punctuations generated after the punctuation period of 20 from times 60 (last punctuation time), snapped to the leftmost generationPeriod boundary PartitionedStreamEvent.CreatePunctuation <int, int>(0, 80), PartitionedStreamEvent.CreatePoint(0, 90, 2), PartitionedStreamEvent.CreatePunctuation <int, int>(1, 80), PartitionedStreamEvent.CreatePoint(1, 91, 1), // Generated by the default OnCompletedPolicy EndOfStream PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime), }; FinishQuery(expected); }
public void LowWatermarkGenerationWithReorderLatency() { SetupQuery( DisorderPolicy.Drop(reorderLatency: 50), PartitionedFlushPolicy.None, PeriodicPunctuationPolicy.None(), PeriodicLowWatermarkPolicy.Time(generationPeriod: 100, lowWatermarkTimestampLag: 10)); // This establishes three partitions with keys 0,1,2 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 0, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 0, 1)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(2, 0, 2)); // This will not yet generate a low watermark, since 99 - 0 is less than the generation period of 100 this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 99, 0)); // This will generate a low watermark, since (110 - lowWatermarkTimestampLag of 10) is greater than the // last watermark timestamp (in this case, none) + generation period (100). // The timestamp will be 110 - (lowWatermarkTimestampLag of 10) = 100. this.input.OnNext(PartitionedStreamEvent.CreatePoint(2, 110, 0)); // These will be dropped due to our PartitionedDisorderPolicy.Drop, since the low watermark is now 100, // even as they approach the low watermark, since any event before the low watermark is out of order. this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 90, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 99, 1)); // These will be honored, since they are >= low watermark this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 100, 1)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 105, 2)); // This will be reordered since it is >= low watermark and within the partition's // high watermark (110) - reorderLatency (50) this.input.OnNext(PartitionedStreamEvent.CreatePoint(2, 100, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 120, 0)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 150, 1)); this.input.OnNext(PartitionedStreamEvent.CreatePoint(2, 190, 2)); // This will generate a low watermark, since (260 - lowWatermarkTimestampLag of 10) is greater than the // last watermark timestamp (100) + generation period (100). // The timestamp will be 260 - (lowWatermarkTimestampLag of 10) = 250. this.input.OnNext(PartitionedStreamEvent.CreatePoint(2, 260, 0)); // An explicitly ingressed low watermark will update/reset the generationPeriod this.input.OnNext(PartitionedStreamEvent.CreateLowWatermark <int, int>(300)); // Even though (370 - lowWatermarkTimestampLag of 10) is greater than the last automatically generated // low watermark timestamp (100) + the generation period (100)); the lowWatermarkGeneration period was // updated to start at 300, so the next generated low watermark will be at timestamp >= // (300 + generationPeriod of 100) this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 370, 1)); // This will generate a low watermark, since (410 - lowWatermarkTimestampLag of 10) is >= the last low // watermark timestamp (300) + the generation period (100). // The timestamp will be 410 - (lowWatermarkTimestampLag of 10) = 400. this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 410, 1)); var expected = new PartitionedStreamEvent <int, int>[] { PartitionedStreamEvent.CreatePoint(0, 0, 0), PartitionedStreamEvent.CreatePoint(1, 0, 1), PartitionedStreamEvent.CreatePoint(2, 0, 2), PartitionedStreamEvent.CreatePoint(0, 99, 0), // Generated automatically because of PeriodicLowWatermarkPolicy in response to point (key 2:100) PartitionedStreamEvent.CreateLowWatermark <int, int>(100), PartitionedStreamEvent.CreatePoint(0, 100, 1), PartitionedStreamEvent.CreatePoint(2, 100, 0), PartitionedStreamEvent.CreatePoint(1, 105, 2), PartitionedStreamEvent.CreatePoint(2, 110, 0), PartitionedStreamEvent.CreatePoint(0, 120, 0), PartitionedStreamEvent.CreatePoint(1, 150, 1), PartitionedStreamEvent.CreatePoint(2, 190, 2), // Generated automatically because of PeriodicLowWatermarkPolicy in response to point (key 2:260), // snapped to the leftmost generationPeriod boundary PartitionedStreamEvent.CreateLowWatermark <int, int>(200), PartitionedStreamEvent.CreatePoint(2, 260, 0), // Explicitly ingressed low watermark PartitionedStreamEvent.CreateLowWatermark <int, int>(300), PartitionedStreamEvent.CreatePoint(0, 370, 1), // Generated automatically because of PeriodicLowWatermarkPolicy in response to point (key 0:410) PartitionedStreamEvent.CreateLowWatermark <int, int>(400), PartitionedStreamEvent.CreatePoint(0, 410, 1), // Generated by the default OnCompletedPolicy EndOfStream PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime), }; FinishQuery(expected); }