Compare commits

...
Author SHA1 Message Date
Mohammad Arham 8ee94a53e3 platformmap needed value for glbx 2023-12-11 06:30:41 -08:00
Mohammad Arham ca7769efe3 added assert to avoid arthematic crash 2023-11-16 18:02:49 -08:00
Mohammad Arham f5d0468e41 changes to code will revert 2023-11-15 12:45:36 -08:00
Mohammad Arham 9a5f377465 disabled web build 2023-11-06 08:08:29 -08:00
Mohammad Arham 9c4f33e4b7 changes to hook cme 2023-11-06 08:08:19 -08:00
Mohammad Arham d45c79c44b Merge branch 'development' of bitbucket.org:bluetradesys/spark into development 2023-11-02 07:46:49 -07:00
John Colvin cba32be99d fix build: Use relative path in csproj references
The build was broken because Spark.csproj was looking for SharedStreams
at some hardcoded path on taha's comp
2023-10-26 14:37:56 -04:00
John Colvin 292fa54dda fix: Get rid of hardcoded path to dll
Use Assembly.Location instead

Bugs (fixed):
  * PubSubServer throws an exception on startup because it can't find
    dll at hardcoded path
2023-10-26 14:31:20 -04:00
John Colvin 3b059ebdfa fix: Format arguments properly in DataStream code gen
Previously, all arguments were formatted as "Bts.DataStream.Argument"
(from the default ToString)
2023-10-26 14:24:32 -04:00
John Colvin d0d3c9de4e feat: Allow line-comments in DataStream parser
Supports c#/c++ style line comments (i.e., that begin with '//')

TODO: block comments
2023-10-26 12:59:44 -04:00
John Colvin 633163518a fix: Fix divide token typo (should be fwd slash) 2023-10-26 12:59:44 -04:00
John Colvin 0a466052e0 cleanup: Remove old submodules (again)
* docker/linux
* docker/windows
2023-10-26 10:52:15 -04:00
John Colvin 7e139ddf0a cleanup: Remove old submodule docker\linux (again) 2023-10-26 10:48:47 -04:00
John Colvin dcac260efe fix (hack): Pass lines as array to cloud stream
Rather than a single multi-line string. This hack will have to do
until we implement multi-line strings in the parser.
2023-10-25 17:42:59 -04:00
Taha 81ea106ce3 Fixing the DSQA query box font color 2023-10-23 15:18:44 -04:00
Taha 88bf04e5f1 TimeSeries and TimeBucketStreams, Stream offloading etc 2023-10-23 14:18:31 -04:00
Taha 33030b1212 Market data streams work now 2023-10-16 00:01:29 -04:00
Taha 140c0c4152 MDStream uses MarketDataClient instead of MDConsumer now 2023-10-03 18:35:23 -04:00
Taha 7d63718602 MDStream uses MarketDataClient instead of MDConsumer now 2023-10-03 18:35:23 -04:00
John Colvin 9cb94fabdb fix: Add cross-type NumericComparer for BooleanExpressions
Bugs (fixed):
   * FilterStream throws exception when comparing numeric arguments
2023-10-02 22:02:35 -04:00
John Colvin e37a39f9fc chore: Add SharedStreams to default loaded assemblies cfg 2023-10-02 21:03:54 -04:00
John Colvin 7e307504cb chore: Remove redundant reference from csproj 2023-10-02 20:53:26 -04:00
John Colvin d01809e49c refactor: Move ProtoHelper to spark_api
So it can be used by other csprojs (was previously stuck in Spark)
2023-10-02 20:45:32 -04:00
John Colvin 292ed2dc0e refactor: Convert WebsocketServerParams to proto 2023-10-02 20:45:32 -04:00
John Colvin 623fce6e8f build: Enable nullable in proto generated cs 2023-10-02 20:45:32 -04:00
John Colvin 7d6d4c03b0 build: Update IronPython to v3.4.1 2023-10-02 20:45:32 -04:00
John Colvin 4962556a6c build: Update protobuf-net to v3.2.26
Also update System.Collections.Immutable to v7.0.0 to new deps
2023-10-02 20:45:32 -04:00
John Colvin 5ad9d9a0e6 build: Update System.Reactive to v6.0.0 2023-10-02 20:45:12 -04:00
John Colvin a091a95f50 build: Add .cmd wrapper script for build_data_stream.py 2023-10-02 19:38:38 -04:00
John Colvin 0bd06da929 build: Upgrade Google.Protobuf to 3.24.3
Now all csprojs are on the same Google.Protobuf version. Previously,
DataStreamSuite projs were on this (newer) version, while Spark projs
were on 3.21.12
2023-10-02 19:38:38 -04:00
Taha af9dd0c1fe PubSub Streams to get list of tags etc 2023-10-02 19:38:38 -04:00
John Colvin fd9eaa65ed build: Add script to build DataStreamSuite and cpp deps 2023-09-30 13:54:58 -04:00
John Colvin 1c744329e5 chore: Add SharedStreams.csproj bones 2023-09-30 13:08:03 -04:00
Taha f8c9148609 Adding tests 2023-09-30 12:59:02 -04:00
Taha fa4da63c24 Streams can be published across PubSub now 2023-09-30 12:59:02 -04:00
Taha 7bb7f1a5e2 PubSub is working now 2023-09-30 12:53:51 -04:00
Taha 3fa37397d9 AsyncTCPCOnnection2 done 2023-09-30 12:52:37 -04:00
Taha d75f97ba1f Both SImpleTCPClient and SimpleTCPServer use non async calls now 2023-09-30 12:52:37 -04:00
Taha 404698152e Merging, and adding test project 2023-09-30 12:52:37 -04:00
183 changed files with 9421 additions and 4171 deletions

No files matched your search

+2 -2
View File
@@ -25,7 +25,7 @@ if (WIN32)
set(BUILD_ADMIN_WEB_APP OFF CACHE BOOL "Build the Admin WebApp")
else()
set(BUILD_SPARKD ON CACHE BOOL "Build sparkd")
set(BUILD_ADMIN_WEB_APP ON CACHE BOOL "Build the Admin WebApp")
# set(BUILD_ADMIN_WEB_APP ON CACHE BOOL "Build the Admin WebApp")
endif()
include_directories(BEFORE SYSTEM ${SPARK_INCLUDE} ${EXTERNALS_ROOT}/include/zlib)
@@ -117,7 +117,7 @@ else()
endif()
add_subdirectory(src/lib)
if (BUILD_ADMIN_WEB_APP)
add_subdirectory(src/Spark.Admin.WebApp)
# add_subdirectory(src/Spark.Admin.WebApp)
endif()
if(BUILD_DOCS)
add_subdirectory(doc/user)
-1
View File
@@ -267,7 +267,6 @@
"hidden": true,
"targets": [
"data_files_dir",
"admin_web_app_bundle",
"install",
"libspark",
"rapidjson_project",
@@ -14,7 +14,7 @@ ParenthesisClose \)
Add \+
Subtract \-
Multiply \*
Divide \\
Divide /
Equals =
Comma ,
@@ -2,6 +2,8 @@ namespace Bts.BooleanExpressions.Arguments;
using bts;
using Spark.Core.Collections;
static class ArgumentComparer {
public static int Compare(
IArgument value1, IArgument value2, IDictionary<string,object?> env) {
@@ -14,7 +16,10 @@ static class ArgumentComparer {
var cmp1 = value1.Cast<IComparable>();
var cmp2 = value2.Cast<IComparable>();
try {
return cmp1.GetValue(env).CompareTo(cmp2.GetValue(env));
var v1 = cmp1.GetValue(env);
var v2 = cmp2.GetValue(env);
return v1.GetType().IsNumeric() ?
new NumericComparer().Compare(v1, v2) : v1.CompareTo(v2);
} catch (Exception ex) {
Log.Ui.error($"Comparison failed: {ex}");
throw;
@@ -44,7 +44,7 @@
%%
BoundExpression : Definitions Expression { $$ = new($2, $1); }
| Expression;
| Expression { $$ = new($1, ImmutableList<Definition>.Empty); };
Definitions :
Definition { $$ = ImmutableList<Definition>.Empty.Add($1); }
@@ -57,46 +57,70 @@ Definition :
Expression :
Expression OR Expression {
$$ = new(env => $1.Evaluate(env) || $3.Evaluate(env));
var left = $1;
var right = $3;
$$ = new(env => left.Evaluate(env) || right.Evaluate(env));
}
| Expression AND Expression {
$$ = new(env => $1.Evaluate(env) && $3.Evaluate(env));
var left = $1;
var right = $3;
$$ = new(env => left.Evaluate(env) && right.Evaluate(env));
}
| Expression XOR Expression {
$$ = new(env => $1.Evaluate(env) != $3.Evaluate(env));
var left = $1;
var right = $3;
$$ = new(env => left.Evaluate(env) != right.Evaluate(env));
}
| NOT Expression {
$$ = new(env => !$2.Evaluate(env));
var exp = $2;
$$ = new(env => !exp.Evaluate(env));
}
| PARENTHESIS_OPEN Expression PARENTHESIS_CLOSE {
$$ = $2;
}
| Argument GREATER Argument {
$$ = new(env => Arguments.ArgumentComparer.Compare($1, $3, env) > 0);
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) > 0);
}
| Argument GREATER_EQUAL Argument {
$$ = new(env => Arguments.ArgumentComparer.Compare($1, $3, env) >= 0);
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) >= 0);
}
| Argument EQUAL Argument {
$$ = new(env => Arguments.ArgumentComparer.Compare($1, $3, env) == 0);
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) == 0);
}
| Argument LESS_EQUAL Argument {
$$ = new(env => Arguments.ArgumentComparer.Compare($1, $3, env) <= 0);
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) <= 0);
}
| Argument LESS Argument {
$$ = new(env => Arguments.ArgumentComparer.Compare($1, $3, env) < 0);
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) < 0);
}
| Argument DIFFERENT Argument {
$$ = new(env => Arguments.ArgumentComparer.Compare($1, $3, env) != 0);
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) != 0);
}
| Argument DIFFERENT2 Argument {
$$ = new(env => Arguments.ArgumentComparer.Compare($1, $3, env) != 0);
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentComparer.Compare(left, right, env) != 0);
}
| Argument MATCHES Argument {
$$ = new(env => Arguments.ArgumentMatcher.Match($1, $3, env));
var left = $1;
var right = $3;
$$ = new(env => Arguments.ArgumentMatcher.Match(left, right, env));
}
| Argument {
$$ = new(env => (bool)$1.GetValue(env));
var arg = $1;
$$ = new(env => (bool)arg.GetValue(env));
}
;
@@ -7,7 +7,7 @@
<ItemGroup>
<ProjectReference Include="..\ArithmeticExpressions\ArithmeticExpressions.csproj" />
<ProjectReference Include="..\BaseUtilities\BaseUtilities.csproj" />
<ProjectReference Include="..\BaseUtilities\BaseUtilities.csproj" />
<ProjectReference Include="..\BooleanExpressions\BooleanExpressions.csproj" />
<ProjectReference Include="..\DataStreamCore\DataStreamCore.csproj" />
<ProjectReference Include="..\DataStreamExpressions\DataStreamExpressions.csproj" />
@@ -0,0 +1,32 @@
using BCG;
namespace BCG
{
// this is a stream so we can run it from the DSQA (since dsqa can only load streams)
[DataStreamUserRespresentation("add_to_cloud")]
public class AddToCloudStream : ViewStream
{
private readonly string _name, _stream_exp;
private StreamOffloadRequestor _requestor = new StreamOffloadRequestor();
public AddToCloudStream(string name, params string[] lines)
: this(name, 0, lines)
{
}
public AddToCloudStream(string name, int persist, params string[] lines)
{
_name = name;
_stream_exp = getExpression(lines);
_requestor.add_to_cloud(_name, _stream_exp, persist == 1);
mySetRealSource(new TableStream("cloud_streams"));
}
static string getExpression(params string[] lines) {
for (int i = 0; i < lines.Length; i++) {
// unescape quotes
lines[i] = lines[i].Replace("\\\"", "\"");
}
return string.Join("\n", lines);
}
}
}
@@ -0,0 +1,100 @@
using BCG;
using System;
using System.Collections.Generic;
using mbts.config;
using bts.utils;
using System.Threading.Tasks;
using Bts.DataStreamExpressions;
using System.Collections.Generic;
using BCG.Utilities.General;
namespace BCG
{
// listens to the requests posted on "cloud_streams" request table, and
// if unfulfilled starts a ViewPubsliher
public class CloudStreamManager : IWorker
{
public class StreamPubUnit
{
public string name;
public string stream_expression;
public ViewStream stream;
public bool persist;
public ViewPublisher view_publisher;
public StreamPubUnit(string name_, string stream_expression_, ViewStream stream_, bool persist_, ViewPublisher view_publisher_)
{
name = name_;
stream_expression = stream_expression_;
stream = stream_;
persist = persist_;
view_publisher = view_publisher_;
}
}
static ViewStream build_stream(string stream_expression)
{
try
{
var exp = DataStreamExpressionsInterpreter.Evaluate(stream_expression);
var rv = exp.getView(new Dictionary<string, StatementExpression>(0));
return rv;
}
catch (Exception ex)
{
bts.Log.assert(false, $"Could not build stream: {stream_expression} ex: {ex}");
return null;
}
}
private IDictionary<string, StreamPubUnit>
_stream_pub_map = new Dictionary<string, StreamPubUnit>();
private ViewStream _stream = new TableStream("cloud_streams");
private PubTableBroker _broker = new PubTableBroker();
public CloudStreamManager()
{
_stream.onChange += _on_str;
}
private void _on_str(object obj)
{
DataPacket dp = obj as DataPacket;
foreach (IBlueRow r in dp.newRows)
{
string name = r.get<string>("name");
bool persist = r.get<bool>("persist");
string stream_exp = r.get<string>("stream_exp");
if (!_stream_pub_map.ContainsKey(name))
{
_assign(name, stream_exp, persist);
}
}
}
private void _assign(string name, string stream_expression, bool persist)
{
bts.Log.Gen.info($"CloudStreamManager.assign name: {name} stream_expression: {stream_expression}");
ViewStream stream = build_stream(stream_expression);
_expose_to_ws(name, stream);
if (persist)
{
stream = new PersistorStream(stream, name, "C:\\Temp\\", 1000000); // 10MBs
}
ViewPublisher view_pub = new ViewPublisher(name, _broker, stream);
StreamPubUnit u = new StreamPubUnit(name, stream_expression, stream, persist, view_pub);
_stream_pub_map.Add(name, u);
}
private void _expose_to_ws(string name, ViewStream stream)
{
// TODO: john
}
public void doWork()
{
}
}
}
@@ -0,0 +1,59 @@
using BCG;
using System.Linq;
namespace BCG
{
public class StreamOffloadRequestor
{
public class OffloadOp
{
string name;
string stream_exp;
}
private IBlueTableSchema _schema;
private IBlueRowCollection _rows;
private PubTableBroker _broker = new PubTableBroker();
ViewStream _existing_offloads_vs = new TableStream("cloud_streams");
public StreamOffloadRequestor()
{
_schema = new BlueTableSchema("cloud_streams",
new ColumnInfo("id", 0, typeof(int)),
new ColumnInfo("name", 1, typeof(string)),
new ColumnInfo("persist", 2, typeof(bool)),
new ColumnInfo("stream_exp", 3, typeof(string)));
_existing_offloads_vs.onChange += _on_str;
}
private void _on_str(object obj)
{
DataPacket dp = obj as DataPacket;
_rows = dp.newRows;
// this is needed so the broker knows the state of the table
_broker.createTable(_rows);
}
public void add_to_cloud(string name, string stream_exp, bool persist)
{
// check if it exists
if (_rows == null)
{
BlueTable table = new BlueTable(_schema);
IBlueRow nr = new BlueRow(_schema, 0, name, persist, stream_exp);
table.addRow(nr);
_broker.createTable(table);
// create table
}
else
{
if (exists(name))
return;
IBlueRow nr = new BlueRow(_schema, _rows.Count, name, persist, stream_exp);
_broker.addRow(nr);
}
}
bool exists(string name)
{
return _rows.to_ienum().Where(r => name == r.get<string>("name")).Count() > 0;
}
}
}
@@ -1,40 +0,0 @@
// using System;
// using System.Collections.Generic;
// using System.Linq;
// using System.Text;
// using System.IO;
// namespace BCG
// {
// public class CaptureSnapshotStream : ViewStream
// {
// public CaptureSnapshotStream(string basePath,ViewStream sourceStream)
// {
// myBasePath = basePath;
// mySource = sourceStream;
// Directory.CreateDirectory(myBasePath);
// }
// protected override void myOnFirstSubscriber()
// {
// mySource.onChange += new ChangeDelegate(mySource_onChange);
// }
// protected override void myOnLastSubscriber()
// {
// mySource.onChange -= mySource_onChange;
// }
// void mySource_onChange(object newValue)
// {
// DateTime now = DateTime.Now;
// new ViewStreamWaiter(new SaverStream(new BlueRowCollectionStaticStream(((DataPacket)newValue).newRows),
// Path.Combine(myBasePath, String.Format("{0}_{1}.ds", now.ToString("yyyyMMdd_HHmmss"),
// now.Millisecond)))).waitUntilArrived();
// myFireEvent(newValue);
// }
// private string myBasePath;
// private ViewStream mySource;
// }
// }
@@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Google.Protobuf;
using System.Globalization;
namespace BCG {
// Writes all the udpates to a stream in a file.
// File naming:
// token_epoch_yyyyMMdd_HHmmss
// File location: directory(passed)\token\
// directory passed on, it creates a folder with the token passed
// data:
// epochtime, size, serialized data
[DataStreamUserRespresentation("pers")]
public class PersistorStream : ViewStream {
private ViewStream _source_stream;
private string _token;
private FileStream _out_fs;
private IBlueDataSerializer _serializer;
private string _file_name = String.Empty;
private long _rollover_size;
private readonly string _directory_path;
private int _n_updates_in_current_file = 0;
public PersistorStream(ViewStream src, string token, string directory, int rollover_size) {
_source_stream = src;
_token = token;
_directory_path = directory + $@"\{token}\";
_open_new_file();
_rollover_size = rollover_size;
}
protected override void myOnFirstSubscriber() {
_source_stream.onChange += _on_change;
}
protected override void myOnLastSubscriber() {
_source_stream.onChange -= _on_change;
_out_fs.Close();
}
public static DateTime parse_datetime_from_filename(string s) {
// allbooks_1697054438_2023-10-11_16-00-38
string[] toks = s.Split("_");
bts.Log.assert(toks.Length == 4);
string dt = $"{toks[2]}_{toks[3]}";
return parse_datetime(dt);
}
// this is used to parse the string passed the datetime texts passed to cons of the stream
public static DateTime parse_datetime(string s) {
// for whatever reason "yyyy-MM-dd_HH-mm-ss" is not parsable using DateTime.ParseExact (it only gets
// the Date not the time), "yyyy-MM-dd_HH:mm:ss" is parsable
// however a file name can not have : in its name, therefore we need to parse "yyyy-MM-dd_HH-mm-ss"
DateTime rv = DateTime.ParseExact(s, PersistorStream.DateTime_format, CultureInfo.InvariantCulture);
string[] toks = s.Split("_");
string time_str = toks[1];
string[] time_toks = time_str.Split("-");
bts.Log.assert(time_toks.Length == 3);
int hh = Int32.Parse(time_toks[0]);
int mm = Int32.Parse(time_toks[1]);
int ss = Int32.Parse(time_toks[2]);
rv = rv.Date;
rv = rv.AddHours(hh);
rv = rv.AddMinutes(mm);
rv = rv.AddSeconds(ss);
return rv;
}
public static string DateTime_format {
get {
return "yyyy-MM-dd_HH-mm-ss";
}
}
public static long dt_to_epoch(DateTime dt) {
DateTimeOffset dtos = new DateTimeOffset(dt, TimeSpan.Zero);
return dtos.ToUnixTimeSeconds();
}
public static long epoch_now() {
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
void _on_change(object new_value) {
DataPacket dp = new_value as DataPacket;
byte[] serialized_update = null;
bool _write_create = _serializer == null || _n_updates_in_current_file == 0;
_serializer = _serializer ?? new UniversalSerializer(dp.schema);
if (_write_create) {
// new files always starts with create
_serializer.serialize(StreamOpCode.create, new IBlueRowCollection[] { dp.newRows }, out serialized_update);
} else
_serializer.serialize(StreamOpCode.multipleRemoveAdd, new IBlueRowCollection[] { dp.deletedRows, dp.addedRows }, out serialized_update);
BinaryWriter bw = new BinaryWriter(_out_fs);
long utc_epoch = epoch_now();
//time, length of data, data
bw.Write(utc_epoch);
bw.Write(serialized_update.Length);
bw.Write(serialized_update);
_out_fs.Flush();
myFireEvent(dp);
_n_updates_in_current_file++;
if (_out_fs.Length > _rollover_size) {
_close_current_and_open_new();
}
}
void _close_current_and_open_new() {
_out_fs.Close();
_open_new_file();
}
void _open_new_file() {
var epoch = epoch_now();
_n_updates_in_current_file = 0;
// Check if the directory was successfully created
if (!Directory.Exists(_directory_path)) {
Directory.CreateDirectory(_directory_path);
}
_file_name = $"{_directory_path}{_token}_{epoch}_{DateTime.Now.ToString(DateTime_format)}";
_out_fs = new FileStream(_file_name, FileMode.OpenOrCreate);
}
}
}
@@ -5,111 +5,184 @@ using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using BCG.Utilities.General;
using BCG.Utilities;
using bts.collections;
using System.Reflection.Metadata;
namespace BCG
{
public delegate void PlaybackStreamProgress(long readFar, long totalBytesRead);
public class PlaybackStream : ViewStream, IWorker
{
public PlaybackStream(string fileName) : this(fileName, 1.0) { }
namespace BCG {
private string myFileName;
private FileStream myFileReader;
private double myPlaybackSpeed;
private DateTime myPlaybackStart;
private DateTime myNextPacketTime;
private IClientDeserializer myDeserializer;
private ITableAccumulator myAccumulator;
public class PlaybackStream : ViewStream, IWorker {
private readonly PlaybackType _type;
private BlueTable _current_table;
private IClientDeserializer _deserilializer = new ClientUniversalDeserializer();
// these are the packets already downloaded from the current file
private List<PlaybackPacket> _packets = new List<PlaybackPacket>();
//private IEnumerable<FileStream> _file_streams = new List<FileStream>();
private IEnumerable<string> _file_names;
private Tuple<int, FileStream> _current_fs = new Tuple<int, FileStream>(-1, null);
private DateTime _playback_t0, _playback_t1;
private bool _all_files_read = false;
SnapshotData _snapshot_data = null; // only initialized when in snapshot mode
private BlueTable myLastTableVersion;
public PlaybackStream(string fileName, double playbackSpeed)
{
myFileName = fileName;
myPlaybackSpeed = playbackSpeed;
public PlaybackStream(string datetime_start, string datetime_end, string directory_name, string token) {
_type = PlaybackType.Streaming;
_playback_t0 = PersistorStream.parse_datetime(datetime_start);
_playback_t1 = PersistorStream.parse_datetime(datetime_end);
string token_directory_name = $"{directory_name}\\{token}";
bts.Log.Gen.info($"PlaybackStream t0: {_playback_t0} t1: {_playback_t1} dir: {token_directory_name}");
List<string> files_in_range = new List<string>();
if (Directory.Exists(token_directory_name)) {
_file_names =
Directory.GetFiles(token_directory_name).Where(f => {
DateTime file_time = PersistorStream.parse_datetime_from_filename(f);
return file_time > _playback_t0 && file_time < _playback_t1;
});
}
}
protected override void myOnFirstSubscriber()
{ myPlaybackStart = DateTime.Now;
myNextPacketTime = DateTime.MinValue;
myFileReader = new FileStream(myFileName, FileMode.Open, FileAccess.Read, FileShare.Read);
myReadNextPacketTime();
ViewStreamDatabase.instance.addWorker(this);
protected override void myOnFirstSubscriber() {
FileStream fs = new FileStream(_snapshot_data.snapshot_file, FileMode.Open, FileAccess.Read);
_snapshot_data.packets = StreamPersistorUtils.load_packets_from_file(fs);
PlaybackPacket snapshot_packet = StreamPersistorUtils.find_packet_at_time(_snapshot_data.packets, _snapshot_data.snapshot_time);
if (snapshot_packet != null) {
foreach (PlaybackPacket p in _snapshot_data.packets) {
byte[] ops;
Array row_array;
_deserilializer.deserialize(new Stream[] { new MemoryStream(p.data) }, out ops, out row_array);
for (int i = 0; i < ops.Length; i++) {
IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[];
byte op = ops[i];
if (op == StreamOpCode.create) {
IBlueRowCollection full_table = rows_args[0];
_current_table = new BlueTable(full_table);
} else if (op == StreamOpCode.multipleRemoveAdd) {
//IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[];
IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection;
IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection;
BlueDataUtility.absorbChanges(_current_table, dels, adds);
} else {
bts.Log.assert(false, $"Oprator: {op} is not expected");
}
if (p.idx == snapshot_packet.idx) {
myFireEvent(new DataPacket(_current_table, _current_table, new BlueTable(_current_table.schema)));
break;
}
}
}
}
}
protected override void myOnLastSubscriber()
{
if (myFileReader != null)
myFileReader.Close();
private void _load_packets_from_current_file() {
int curr_idx = _current_fs.Item1;
FileStream curr_fs = _current_fs.Item2;
_packets = new List<PlaybackPacket>();
_packets.AddRange(StreamPersistorUtils.load_packets_from_file(curr_fs));
}
private bool current_file_all_replayed {
get {
bool rv = true;
_packets.ForEach(p => rv = rv && p.replayed);
return rv;
}
}
protected override void myOnLastSubscriber() {
var fs = _current_fs.Item2;
if (fs != null) {
fs.Close();
}
ViewStreamDatabase.instance.removeWorker(this);
}
protected void myReadNextPacketTime()
{
if (myFileReader.Position == myFileReader.Length)
{
myNextPacketTime = DateTime.MaxValue;
myFileReader.Dispose();
if (onFileExhausted != null)
onFileExhausted();
}
else
{
double secondsElapsed = new BinaryReader(myFileReader).ReadDouble();
myNextPacketTime = myPlaybackStart + new TimeSpan(0, 0, 0, 0, (int)(1000 * secondsElapsed / myPlaybackSpeed));
if (onProgress != null)
onProgress(myFileReader.Position, myFileReader.Length);
// public event PlaybackStreamProgress onProgress;
// public event Action onFileExhausted;
private PlaybackPacket _locate_packet_to_replay() {
foreach (var p in _packets) {
// returns the first non replayed packet
if (!p.replayed)
return p;
}
return null;
}
public event PlaybackStreamProgress onProgress;
public event Action onFileExhausted;
private PlaybackPacket _get_previous_packet(PlaybackPacket p) {
if (p.idx == 0)
return null;
return _packets[p.idx - 1];
}
#region IWorker Members
public void doWork()
{
if (myNextPacketTime <= DateTime.Now)
{
if (myDeserializer == null)
{
myDeserializer = new ClientUniversalDeserializer();
myAccumulator = new TableAccumulator(myFileName, null);
}
BinaryReader reader = new BinaryReader(myFileReader);
int numBytes = reader.ReadInt32();
byte[] thisData = reader.ReadBytes(numBytes);
byte[] ops;
Array resultRowCollections;
myDeserializer.deserialize(new Stream[] { new MemoryStream(thisData) }, out ops, out resultRowCollections);
//there should only be one op in there becuae we just read a single update.
// BlueEventLog.logAssert(ops.Length == 1,"Playback stream got " +ops.Length.ToString() + " op codes in one update, from stream file "+myFileName);
//there shoudl only be one set of collections becaue there was just a single op code
//(those two arrays are parallel)
// BlueEventLog.logAssert(resultRowCollections.Length == 1, "StreamOpCode was create, serializer should return exactly 1 set of rows");
if (ops[0] == (byte)StreamOpCode.create)
{
myLastTableVersion = new BlueTable((resultRowCollections.GetValue(0) as IBlueRowCollection[])[0]);
myFireEvent(new DataPacket(myLastTableVersion, new BlueTable(myLastTableVersion.schema), new BlueTable(myLastTableVersion.schema)));
}
else
{
// BlueEventLog.logAssert(ops[0] == (byte)StreamOpCode.multipleRemoveAdd, "Playback stream got unexpected open code " + ops[0].ToString() + " from file " + myFileName);
// BlueEventLog.logAssert(myLastTableVersion != null, "Playback stream for file "+myFileName + "got a non-create before a create");
IBlueRowCollection[] deletedAndAdded = resultRowCollections.GetValue(0) as IBlueRowCollection[];
BlueDataUtility.absorbChanges(myLastTableVersion, deletedAndAdded[0], deletedAndAdded[1]);
myFireEvent(new DataPacket(myLastTableVersion, deletedAndAdded[1], deletedAndAdded[0]));
}
myReadNextPacketTime();
public void doWork() {
if (_all_files_read)
return;
if (current_file_all_replayed) {
_load_next_file();
}
PlaybackPacket curr_packet = _locate_packet_to_replay();
if (curr_packet.idx == 0) { // first packet in the file, fire it rightaway
byte[] ops;
Array row_array;
// what a stupid interface!
_deserilializer.deserialize(new Stream[] { new MemoryStream(curr_packet.data) }, out ops, out row_array);
_fire_packet(ops, row_array);
curr_packet.replay_timestamp = PersistorStream.epoch_now();
} else {
PlaybackPacket prev_packet = _get_previous_packet(curr_packet);
// this is the time we need to fire (replay) this packet
long time_to_fire = prev_packet.replay_timestamp + curr_packet.offset_from_previous;
long now_epoch = PersistorStream.epoch_now();
// fire when we are past the
if (now_epoch >= time_to_fire) {
byte[] ops;
Array row_array;
_deserilializer.deserialize(new Stream[] { new MemoryStream(curr_packet.data) }, out ops, out row_array);
_fire_packet(ops, row_array);
curr_packet.replay_timestamp = PersistorStream.epoch_now();
}
}
}
private void _fire_packet(byte[] ops, Array row_array) {
for (int i = 0; i < ops.Length; i++) {
IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[];
byte op = ops[i];
if (op == StreamOpCode.create) {
IBlueRowCollection full_table = rows_args[0];
_current_table = new BlueTable(full_table);
//_current_table.addRows(full_table);
myFireEvent(new DataPacket(full_table, full_table, myLastValue == null ? new BlueTable(full_table.schema) :
(myLastValue as DataPacket).newRows));
} else if (op == StreamOpCode.multipleRemoveAdd) {
//IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[];
IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection;
IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection;
BlueDataUtility.absorbChanges(_current_table, dels, adds);
myFireEvent(new DataPacket(_current_table, adds, dels));
} else {
bts.Log.assert(false, $"Oprator: {op} is not expected");
}
}
}
private void _load_next_file() {
var new_idx = _current_fs.Item1 + 1;
if (new_idx >= _file_names.Count()) {
_all_files_read = true;
bts.Log.Gen.info("All files read");
return;
}
var prev_fs = _current_fs.Item2;
if (prev_fs != null)
prev_fs.Close();
var new_filename = _file_names.ElementAt(new_idx);
bts.Log.Gen.info("PlaybackStream_load_next_file new_filename=: {new_filename}");
var new_fs = new FileStream(new_filename, FileMode.Open, FileAccess.Read);
_current_fs = new Tuple<int, FileStream>(new_idx, new_fs);
_load_packets_from_current_file();
}
#endregion
@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using BCG.Utilities.General;
using bts.collections;
using System.Reflection.Metadata;
namespace BCG {
public class SnapshotStream : ViewStream {
private BlueTable _current_table;
private IClientDeserializer _deserilializer = new ClientUniversalDeserializer();
public DateTime _snapshot_time;
public string _snapshot_file;
public IEnumerable<PlaybackPacket> _packets;
public SnapshotStream(string snapshot_dt, string directory_name, string token) {
_snapshot_time = PersistorStream.parse_datetime(snapshot_dt);
string token_directory_name = $"{directory_name}\\{token}";
_snapshot_file = StreamPersistorUtils.find_snapshot_file(token_directory_name, _snapshot_time);
}
protected override void myOnFirstSubscriber() {
FileStream fs = new FileStream(_snapshot_file, FileMode.Open, FileAccess.Read);
_packets = StreamPersistorUtils.load_packets_from_file(fs);
PlaybackPacket snapshot_packet = StreamPersistorUtils.find_packet_at_time(_packets, _snapshot_time);
if (snapshot_packet != null) {
foreach (PlaybackPacket p in _packets) {
byte[] ops;
Array row_array;
_deserilializer.deserialize(new Stream[] { new MemoryStream(p.data) }, out ops, out row_array);
for (int i = 0; i < ops.Length; i++) {
IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[];
byte op = ops[i];
if (op == StreamOpCode.create) {
IBlueRowCollection full_table = rows_args[0];
_current_table = new BlueTable(full_table);
} else if (op == StreamOpCode.multipleRemoveAdd) {
//IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[];
IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection;
IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection;
BlueDataUtility.absorbChanges(_current_table, dels, adds);
} else {
bts.Log.assert(false, $"Oprator: {op} is not expected");
}
if (p.idx == snapshot_packet.idx) {
myFireEvent(new DataPacket(_current_table, _current_table, new BlueTable(_current_table.schema)));
break;
}
}
}
}
}
private void _absorb_packet(byte[] ops, Array row_array) {
for (int i = 0; i < ops.Length; i++) {
IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[];
byte op = ops[i];
if (op == StreamOpCode.create) {
IBlueRowCollection full_table = rows_args[0];
_current_table = new BlueTable(full_table);
} else if (op == StreamOpCode.multipleRemoveAdd) {
//IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[];
IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection;
IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection;
BlueDataUtility.absorbChanges(_current_table, dels, adds);
} else {
bts.Log.assert(false, $"Operator: {op} is not expected");
}
}
}
protected override void myOnLastSubscriber() {
}
// public event SnapshotStream.Progress onProgress;
// public event Action onFileExhausted;
private PlaybackPacket _locate_packet_to_replay() {
foreach (var p in _packets) {
// returns the first non replayed packet
if (!p.replayed)
return p;
}
return null;
}
private void _fire_packet(byte[] ops, Array row_array) {
for (int i = 0; i < ops.Length; i++) {
IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[];
byte op = ops[i];
if (op == StreamOpCode.create) {
IBlueRowCollection full_table = rows_args[0];
_current_table = new BlueTable(full_table);
//_current_table.addRows(full_table);
myFireEvent(new DataPacket(full_table, full_table, myLastValue == null ? new BlueTable(full_table.schema) :
(myLastValue as DataPacket).newRows));
} else if (op == StreamOpCode.multipleRemoveAdd) {
//IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[];
IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection;
IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection;
BlueDataUtility.absorbChanges(_current_table, dels, adds);
myFireEvent(new DataPacket(_current_table, adds, dels));
} else {
bts.Log.assert(false, $"Oprator: {op} is not expected");
}
}
}
}
}
@@ -0,0 +1,145 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.IO;
namespace BCG {
// each stream op in the replay file is reprsented by a packet here
public class PlaybackPacket {
public readonly int idx;
public readonly long timestamp;
public readonly byte[] data;
public long replay_timestamp = 0; // non zero it has been replayed
public long offset_from_previous = 0;
public PlaybackPacket(int the_idx, long the_timestamp, byte[] the_data) {
this.idx = the_idx;
this.timestamp = the_timestamp;
this.data = the_data;
}
public bool replayed {
get { return replay_timestamp != 0; }
}
}
public enum PlaybackType {
Streaming = 0,
Snapshot
}
public class SnapshotData {
public DateTime snapshot_time;
public string snapshot_file;
public SnapshotData(DateTime snapshot_time_arg, string snapshot_file_arg) {
snapshot_time = snapshot_time_arg;
snapshot_file = snapshot_file_arg;
}
public IEnumerable<PlaybackPacket> packets = new List<PlaybackPacket>();
}
public static class StreamPersistorUtils {
public static string find_snapshot_file(string directory_name, DateTime snapshot_time) {
string[] file_names = Directory.GetFiles(directory_name);
for (int i = 0; i < file_names.Count() - 1; i++) {
string fn = file_names[i];
string next_fn = file_names[i + 1];
DateTime f_dt = PersistorStream.parse_datetime_from_filename(fn);
DateTime next_f_dt = PersistorStream.parse_datetime_from_filename(next_fn);
if (snapshot_time >= f_dt && snapshot_time <= next_f_dt) {
return fn;
}
}
return String.Empty;
}
public static DateTime parse_datetime_from_filename(string s) {
// allbooks_1697054438_2023-10-11_16-00-38
string[] toks = s.Split("_");
bts.Log.assert(toks.Length == 4);
string dt = $"{toks[2]}_{toks[3]}";
return parse_datetime(dt);
}
// this is used to parse the string passed the datetime texts passed to cons of the stream
public static DateTime parse_datetime(string s) {
// for whatever reason "yyyy-MM-dd_HH-mm-ss" is not parsable using DateTime.ParseExact (it only gets
// the Date not the time), "yyyy-MM-dd_HH:mm:ss" is parsable
// however a file name can not have : in its name, therefore we need to parse "yyyy-MM-dd_HH-mm-ss"
DateTime rv = DateTime.ParseExact(s, PersistorStream.DateTime_format, CultureInfo.InvariantCulture);
string[] toks = s.Split("_");
string time_str = toks[1];
string[] time_toks = time_str.Split("-");
bts.Log.assert(time_toks.Length == 3);
int hh = Int32.Parse(time_toks[0]);
int mm = Int32.Parse(time_toks[1]);
int ss = Int32.Parse(time_toks[2]);
rv = rv.Date;
rv = rv.AddHours(hh);
rv = rv.AddMinutes(mm);
rv = rv.AddSeconds(ss);
return rv;
}
public static string DateTime_format {
get {
return "yyyy-MM-dd_HH-mm-ss";
}
}
public static long dt_to_epoch(DateTime dt) {
DateTimeOffset dtos = new DateTimeOffset(dt, TimeSpan.Zero);
return dtos.ToUnixTimeSeconds();
}
public static long epoch_now() {
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
public static DateTime epoch_to_dt(long epoch_seconds) {
return DateTimeOffset.FromUnixTimeSeconds(epoch_seconds).DateTime;
}
public static PlaybackPacket find_packet_at_time(IEnumerable<PlaybackPacket> packets, DateTime snapshot_time) {
log_file_ts(packets, snapshot_time);
long snapshot_time_epoch = PersistorStream.dt_to_epoch(snapshot_time);
for (int i = 0; i < packets.Count() - 1; i++) {
PlaybackPacket curr_p = packets.ElementAt(i);
PlaybackPacket next_p = packets.ElementAt(i + 1);
if (curr_p.timestamp <= snapshot_time_epoch && next_p.timestamp >= snapshot_time_epoch) {
return curr_p;
}
}
// if for some reason it cant find it, send the last packet
return packets.Last();
}
private static void log_file_ts(IEnumerable<PlaybackPacket> packets, DateTime snapshot_time) {
string big_log_msg = String.Empty;
foreach (var p in packets) {
big_log_msg += $"packet idx: {p.idx} epoch_ts: {p.timestamp} ts: {epoch_to_dt(p.timestamp)} snapshot_time: {snapshot_time}";
big_log_msg += "\n";
}
bts.Log.Gen.info($"Packets: {big_log_msg}");
}
public static IEnumerable<PlaybackPacket> load_packets_from_file(FileStream fs) {
BinaryReader br = new BinaryReader(fs);
List<PlaybackPacket> rv = new List<PlaybackPacket>();
while (fs.Position < fs.Length) {
try {
long ts = br.ReadInt64();
int sz = br.ReadInt32();
byte[] data = br.ReadBytes(sz);
var pb = new PlaybackPacket(rv.Count, ts, data);
rv.Add(pb);
} catch (Exception ex) {
bts.Log.Gen.error($"ex: {ex}");
break;
}
}
// setting offset field
for (int i = 0; i < rv.Count; i++) {
if (i == 0)
continue;
rv[i].offset_from_previous = rv[i].timestamp - rv[i - 1].timestamp;
}
return rv;
}
}
}
@@ -8,6 +8,7 @@ using mbts.spark;
namespace BCG
{
[DataStreamUserRespresentation("fastJoin")]
public class NonIncJoinStream : ViewStream, BCG.Utilities.General.IWorker
{
private readonly NonIncJoinSpec[] _join_specs;
@@ -23,7 +24,7 @@ namespace BCG
public NonIncJoinStream(ViewStream left, string left_join_cols, string left_proj,
ViewStream right, string right_join_cols, string right_proj)
: this(new Triplet<ViewStream, string, string>[]
: this(new Triplet<ViewStream, string, string>[]
{
new Triplet<ViewStream, string, string> (left, left_join_cols, left_proj),
new Triplet<ViewStream, string, string> (right, right_join_cols, right_proj)
@@ -31,7 +32,7 @@ namespace BCG
{ }
public NonIncJoinStream(params Triplet<ViewStream, string, string>[] join_specs)
: this (NonIncJoinSpec.from_triplet (join_specs), null, 0)
: this(NonIncJoinSpec.from_triplet(join_specs), null, 0)
{ }
public NonIncJoinStream(ViewStreamDatabase vsd, INonIncJoinInlineMapper output_mapper, int throttles_ms,
@@ -102,8 +103,8 @@ namespace BCG
{
List<ColumnInfo> cis = new List<ColumnInfo>(new ColumnInfo[] { new ColumnInfo("id", 0, typeof(int)) });
foreach (NonIncJoinBookkeeper d in _book_keeping_data)
d.constribute_cols_to_schema (cis);
_output_schema = new BlueTableSchema ("NonIncJoinStream", cis.ToArray());
d.constribute_cols_to_schema(cis);
_output_schema = new BlueTableSchema("NonIncJoinStream", cis.ToArray());
}
}
@@ -0,0 +1,48 @@
using System;
namespace BCG {
// Keeps adding changing rows to the stream, hence preserving the history
// and creating a time series, for example this can be used to make bbo updates
// into a time series of prices/qty
public class DebugStream : ViewStream {
private ViewStream _stream;
private IBlueRowCollection _last_recv_rows = null;
public DebugStream(ViewStream stream) {
_stream = stream;
}
protected override void myOnFirstSubscriber() {
_stream.onChange += new ChangeDelegate(_onstream_change);
}
protected override void myOnLastSubscriber() {
_stream.onChange -= new ChangeDelegate(_onstream_change);
}
private void _onstream_change(object o) {
DataPacket dp = o as DataPacket;
BlueDataUtility.validate_table_schema(dp.newRows);
BlueDataUtility.validate_table_schema(dp.addedRows);
if (_last_recv_rows == null) {
_last_recv_rows = dp.newRows;
} else {
//schema
bts.Log.assert(BlueDataUtility.compareSchemas(_last_recv_rows.schema, dp.newRows.schema));
bts.Log.assert(BlueDataUtility.compareSchemas(_last_recv_rows.schema, dp.addedRows.schema));
bts.Log.assert(BlueDataUtility.compareSchemas(_last_recv_rows.schema, dp.deletedRows.schema));
foreach (IBlueRow r in dp.deletedRows) {
bts.Log.assert(_last_recv_rows.containsID(r.get<int>("id")));
}
foreach (IBlueRow r in dp.addedRows) {
bts.Log.assert(dp.newRows.containsID(r.get<int>("id")));
}
_last_recv_rows = dp.newRows;
}
myFireEvent(o);
}
}
}
@@ -0,0 +1,169 @@
using Google.Protobuf.WellKnownTypes;
using System;
using BCG.Utilities.General;
namespace BCG
{
// Keeps adding changing rows to the stream, hence preserving the history
// and creating a time series, for example this can be used to make bbo updates
// into a time series of prices/qty
public class TimeSeriesStream : ViewStream
{
private BlueTable _table;
private ViewStream _stream;
private int _id = 0;
public TimeSeriesStream(ViewStream stream)
{
_stream = stream;
}
protected override void myOnFirstSubscriber()
{
_stream.onChange += new ChangeDelegate(_onstream_change);
}
protected override void myOnLastSubscriber()
{
_stream.onChange -= new ChangeDelegate(_onstream_change);
}
private void _onstream_change(object o)
{
DataPacket dp = o as DataPacket;
DateTime now = DateTime.Now;
if (_table == null)
{
IBlueTableSchema schema = new BlueTableSchema(dp.newRows.schema.columnInfo, dp.newRows.schema.tableName);
schema = schema.add_columns(Tuple.Create(typeof(DateTime), "timestamp"));
_table = new BlueTable(schema);
}
BlueTable added_rows = new BlueTable(_table.schema);
foreach (IBlueRow r in dp.addedRows)
{
MutableBlueRow ar = new MutableBlueRow(_table.schema, r);
ar.setValue("timestamp", now);
ar.setValue("id", _id++);
added_rows.addRow(ar);
}
_table.addRows(added_rows);
myFireEvent(new DataPacket(_table, added_rows, new BlueTable(_table.schema)));
}
}
public class TimeBucketStream : ViewStream, IStreamMapper
{
private ViewStream _src;
private readonly string _time_stamp_col;
private IBlueTableSchema _schema;
private int _bucket_size_seconds;
public TimeBucketStream(ViewStream input, string time_stamp_col, int bucket_size_seconds)
{
_time_stamp_col = time_stamp_col;
_bucket_size_seconds = bucket_size_seconds;
var vs = new MapStream(input, this);
mySetRealSource(vs);
}
#region IStreamMapper Members
public IBlueTableSchema getOutputSchema(IBlueTableSchema input_schema)
{
IBlueTableSchema rv = input_schema;
//rv = BlueDataUtility.remove_columns(rv, _time_stamp_col);
rv = BlueDataUtility.add_column(rv, "bucket_number", typeof(int));
return rv;
}
#endregion
#region IDynamicStreamMapper Members
public IBlueRow map(IBlueRow row)
{
DateTime ts = row.get<DateTime>(_time_stamp_col);
TimeSpan time_of_day = (ts - ts.Date);
int seconds = Convert.ToInt32(time_of_day.TotalSeconds);
double buckets = seconds / _bucket_size_seconds;
int bucket_number = Convert.ToInt32(Math.Floor(buckets));
MutableBlueRow rv = new MutableBlueRow(getOutputSchema(row.schema), row);
rv.setValue("bucket_number", bucket_number);
return rv;
}
#endregion
}
// public class ThrottleStream : ViewStream, IWorker
// {
// private ViewStreamDatabase _vsd;
// private ViewStream _stream;
// private int _throttle_ms;
// private TimeSpan _min_fire_period;
// private DateTime _last_Fire_time = DateTime.MinValue;
// private DataPacket _unfired_dp;
// public ThrottleStream(ViewStreamDatabase vsd, ViewStream base_stream, int throttle_ms)
// {
// _vsd = vsd;
// _stream = base_stream;
// _throttle_ms = throttle_ms;
// _min_fire_period = TimeSpan.FromMilliSeconds(throttle_ms);
// }
// protected override void myOnFirstSubscriber()
// {
// _vsd.addWorker(this);
// _stream.onChange += new ChangeDelegate(_onstream_change);
// }
// protected override void myOnLastSubscriber()
// {
// _vsd.removeWorker(this);
// _stream.onChange -= new ChangeDelegate(_onstream_change);
// }
// private void _onstream_change(object obj)
// {
// DataPacket dp = obj as DataPacket;
// if (DateTime.Now - _last_Fire_time >= _min_fire_period)
// {
// // ok to fire here
// }
// else
// {
// _last_cached_state = dp.newRows;
// }
// _possibly_fire(dp.newRows);
// }
// public void doWork()
// {
// if (_unfired_dp != null)
// {
// }
// }
// private void _possibly_fire()
// {
// if (_unfired_dp != null)
// {
// if (DateTime.Now - _last_fire_time > _min_fire_period)
// {
// DataPacket dp = BlueDataUtility.build_dp_inc(_unfired_dp.newRows, myLastValue);
// _unfired_dp = null;
// _last_Fire_time = DateTime.Now;
// myFireEvent(dp);
// }
// }
// }
// }
}
@@ -6,7 +6,7 @@ using BCG.Utilities;
namespace BCG
{
[DataStreamUserRespresentation("csvSaver")]
[DataStreamUserRespresentation("CSVSaver")]
public class CSVSaverStream : ViewStream, ISideEffectStream
{
private IBlueTableSchema myResultSchema = new BlueTableSchema("CSVResult", new ColumnInfo("id", 0, typeof(int)),
@@ -0,0 +1,143 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BCG
{
/// <summary>
/// If one adds annother value to this enum, be sure to update _date_conversion_to_type_map below as well
/// </summary>
public enum DateConversion
{
ConvertDoubleToDateTime = 0,
ChopTime,
UTCToCurrent,
ConvertStringToDateTime,
ConvertDateTimeToMilliseconds,
SecondsOfDay
}
[DataStreamUserRespresentation("dateStandardize")]
public class DateStandardizationStream : ViewStream, IStreamMapper
{
private IBlueTableSchema mySchema;
private DateConversion myConversion;
private string myConversionColName;
private readonly Dictionary<DateConversion, Type> _date_conversion_to_type_map = new Dictionary<DateConversion, Type>()
{
{DateConversion.ConvertDoubleToDateTime , typeof(DateTime)},
{DateConversion.ChopTime , typeof(DateTime)},
{DateConversion.UTCToCurrent , typeof(DateTime)},
{DateConversion.ConvertStringToDateTime , typeof(DateTime)},
{DateConversion.ConvertDateTimeToMilliseconds, typeof(Double)},
{DateConversion.SecondsOfDay , typeof(Double)}
};
private static DateConversion _parse(string s)
{
DateConversion rv = DateConversion.ChopTime;
Enum.TryParse<DateConversion>(s, false, out rv);
return rv;
}
/// <summary>
/// for DSQA
/// </summary>
public DateStandardizationStream(ViewStream vs, string colName, string conversion)
: this(vs, colName, _parse(conversion))
{ }
public DateStandardizationStream(ViewStream vs, string colName, DateConversion conversion)
{
myConversionColName = colName;
myConversion = conversion;
mySetRealSource(new MapStream(vs, this));
}
#region IStreamMapper Members
public IBlueTableSchema getOutputSchema(IBlueTableSchema inputSchema)
{
if (mySchema == null)
{
List<ColumnInfo> cis = new List<ColumnInfo>();
foreach (ColumnInfo c in inputSchema.columnInfo)
{
if (c.colName == myConversionColName)
{
Type convType;
if (!_date_conversion_to_type_map.TryGetValue(myConversion, out convType))
{
//BCG.Utilities.BlueEventLog.logEvent("Please update the _date_conversion_to_type_map in DateStandardizationStream.cs.", BCG.Utilities.BlueEventLevel.Error);
convType = typeof(DateTime);
}
cis.Add(new ColumnInfo(c.colName, c.colNo, convType));
}
else
cis.Add(new ColumnInfo(c.colName, c.colNo, c.colType));
}
mySchema = new BlueTableSchema(inputSchema.tableName, cis.ToArray());
}
return mySchema;
}
#endregion
#region IDynamicStreamMapper Members
public IBlueRow map(IBlueRow row)
{
return BlueDataUtility.getNewReplacedRow(row, mapDateTime(row[myConversionColName], myConversion), myConversionColName);
}
#endregion
public static object mapDateTime(object objIn, DateConversion conv)
{
if (objIn == DBNull.Value || objIn == null)
{
return DBNull.Value;
}
else
{
if (conv == DateConversion.ChopTime)
{
DateTime dtIn = (DateTime)objIn;
return dtIn.Date;
}
else if (conv == DateConversion.ConvertDoubleToDateTime)
{
double dtIn = (double)objIn;
return DateTime.FromOADate(dtIn);
}
else if (conv == DateConversion.UTCToCurrent)
{
DateTime dtIn = (DateTime)objIn;
return dtIn.ToLocalTime();
}
else if (conv == DateConversion.ConvertStringToDateTime)
{
return DateTime.Parse((string)objIn);
}
else if (conv == DateConversion.ConvertDateTimeToMilliseconds)
{
DateTime dtIn = (DateTime)objIn;
return dtIn.TimeOfDay.TotalMilliseconds;
}
else if (conv == DateConversion.SecondsOfDay)
{
DateTime dtIn = (DateTime)objIn;
DateTime start_of_day = dtIn.Date;
TimeSpan day_period = dtIn - start_of_day;
return day_period.TotalSeconds;
}
else
{
bts.Log.Gen.info("incorrect type");
return null;
}
}
}
}
}
Whitespace-only changes.
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
namespace BCG
{
[DataStreamUserRepresentation("timeBucket")]
public class TimeBucketStream : ViewStream, IStreamMapper
{
private ViewStream _src;
private readonly string _time_stamp_col;
private IBlueTableSchema _schema;
private uint _bucket_size_seconds;
public TimeBucketStream(ViewStream input, string time_stamp_col, uint bucket_size_seconds)
{
_time_stamp_col = time_stamp_col;
_bucket_size_seconds = bucket_size_seconds;
}
#region IStreamMapper Members
public IBlueTableSchema getOutputSchema(IBlueTableSchema input_schema)
{
IBlueTableSchema rv = input_schema;
//rv = BlueDataUtility.remove_columns(rv, _time_stamp_col);
rv = BlueDataUtility.add_column(rv, "bucket_number", typeof(int));
return rv;
}
#endregion
#region IDynamicStreamMapper Members
public IBlueRow map(IBlueRow row)
{
DateTime ts = row.get<DateTime>(_time_stamp_col);
TimeSpan time_of_day = (ts - ts.Date)
int seconds = Convert.ToInt32(time_of_day.TotalSeconds);
int buckets = seconds / _bucket_size_seconds;
int bucket_number = Math.Floor(buckets);
MutableBlueRow rv = new MutableBlueRow(row, getOutputSchema(row.schema))
rv.setValue("bucket_number", bucket_number);
}
#endregion
}
}
@@ -1,10 +1,9 @@
using System;
using BCG.Utilities.General;
namespace BCG
{
public abstract class TimeUnitStream : ViewStream, IWorker
{
namespace BCG {
public abstract class TimeUnitStream : ViewStream, IWorker {
protected TimeSpan myOffset;
protected DateTime myConstructionTime;
protected int mySizeOfStream;
@@ -13,87 +12,80 @@ namespace BCG
protected ViewStreamDatabase myDb;
protected int myId = 0;
public TimeUnitStream (DateTime zeroTime, TimeSpan offSet, int sizeOfStream, ViewStreamDatabase db)
{
public TimeUnitStream(DateTime zeroTime, TimeSpan offSet, int sizeOfStream, ViewStreamDatabase db) {
myConstructionTime = DateTime.Now;
myZeroTime = zeroTime;
myOffset = offSet;
mySizeOfStream = sizeOfStream;
myDb = db;
myCollection = new CircularRowCollection (
new BlueTableSchema ("Time",
new ColumnInfo ("id", 0, typeof(Int32)), new ColumnInfo ("time", 1, typeof(DateTime))),
myCollection = new CircularRowCollection(
new BlueTableSchema("Time",
new ColumnInfo("id", 0, typeof(Int32)), new ColumnInfo("time", 1, typeof(DateTime))),
mySizeOfStream);
}
}
#region ViewStream overriden methods
protected override void myOnFirstSubscriber()
{
myDb.addWorker (this);
myInit ();
protected override void myOnFirstSubscriber() {
myDb.addWorker(this);
myInit();
}
protected override void myOnLastSubscriber()
{
myDb.removeWorker (this);
protected override void myOnLastSubscriber() {
myDb.removeWorker(this);
}
#endregion
protected virtual void myInit ()
{
protected virtual void myInit() {
int periods = (int)
(DateTime.Now - myConstructionTime).TotalMilliseconds / (int) myOffset.TotalMilliseconds;
(DateTime.Now - myConstructionTime).TotalMilliseconds / (int)myOffset.TotalMilliseconds;
DateTime dt = myGetLatestRow() == null ? myRoundTime(myZeroTime) :
myRoundTime (myZeroTime + new TimeSpan(myOffset.Ticks * periods));
DateTime dt = myGetLatestRow() == null ? myRoundTime(myZeroTime) :
myRoundTime(myZeroTime + new TimeSpan(myOffset.Ticks * periods));
if (myGetLatestRow() == null ||
!myGetLatestRow()["time"].Equals(dt))
{
IBlueRow ar = new BlueRow (myCollection.schema,
!myGetLatestRow()["time"].Equals(dt)) {
IBlueRow ar = new BlueRow(myCollection.schema,
myId++, dt);
IBlueRow dr = myCollection.addRowWithReturn (ar);
myFireEvent (new DataPacket (myCollection,
myConvertToCollection (ar),
myConvertToCollection (dr)));
IBlueRow dr = myCollection.addRowWithReturn(ar);
if (n_updates <= 3000)
myFireEvent(new DataPacket(myCollection,
myConvertToCollection(ar),
myConvertToCollection(dr)));
}
}
#region IWorker methods
public void doWork ()
{
myInit ();
public void doWork() {
myInit();
}
#endregion
protected abstract DateTime myRoundTime (DateTime dt);
protected abstract DateTime myRoundTime(DateTime dt);
#region Private Helper methods
private IBlueRow myGetLatestRow ()
{
private IBlueRow myGetLatestRow() {
return myCollection.Count == 0 ?
null :
BlueDataUtility.extractRow (myCollection, myCollection.Count - 1);
BlueDataUtility.extractRow(myCollection, myCollection.Count - 1);
}
private IBlueRowCollection myConvertToCollection (IBlueRow r)
{
BlueTable retVal = new BlueTable (myCollection.schema);
private IBlueRowCollection myConvertToCollection(IBlueRow r) {
BlueTable retVal = new BlueTable(myCollection.schema);
if (r != null)
retVal.addRow (r);
retVal.addRow(r);
return retVal;
}
#endregion
}
}
}
@@ -1,72 +1,75 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Xml.Serialization;
using BCG.Utilities;
namespace BCG
{
namespace BCG {
/// <summary>
/// This class will be used by the clients to publish data to the pubsub
/// This class will be used by the clients to publish tabular data to the pubsub
/// </summary>
public class PubTableBroker
{
protected PublisherCore myPublisherCore;
protected IDictionary myPublisherMap = new Hashtable ();
protected IDictionary mySchemaMap = new Hashtable ();
public class PubTableBroker {
protected PublisherCore _publisher_core;
protected IDictionary<string, IPubTablePublisher> _publisher_map = new Dictionary<string, IPubTablePublisher>();
protected Dictionary<string, IBlueTableSchema> _schema_map = new Dictionary<string, IBlueTableSchema>();
protected bool myWaitingForFirstOp = false;
public PubTableBroker ()
: this (new PublisherCore())
{}
public PubTableBroker()
: this(new PublisherCore()) { }
public PubTableBroker (PublisherCore publisher)
{myPublisherCore = publisher;}
public PubTableBroker(PublisherCore publisher) { _publisher_core = publisher; }
public PubTableBroker (IBlueRowCollection[] tablesToPublish)
: this (new PublisherCore(), tablesToPublish)
{}
public PubTableBroker(IBlueRowCollection[] tablesToPublish)
: this(new PublisherCore(), tablesToPublish) { }
public PubTableBroker (PublisherCore publisher, IBlueRowCollection[] tablesToPublish)
{
myPublisherCore = publisher;
public PubTableBroker(PublisherCore publisher, IBlueRowCollection[] tablesToPublish) {
_publisher_core = publisher;
myPublisherCore.beginTransaction ();
_publisher_core.beginTransaction();
foreach (IBlueRowCollection table in tablesToPublish)
createTable (table);
myPublisherCore.commitTransaction ();
createTable(table);
_publisher_core.commitTransaction();
}
public void beginTransaction ()
{
public void beginTransaction() {
myWaitingForFirstOp = true;
}
public void commitTransaction ()
{
public void commitTransaction() {
bts.Log.Gen.info("PubTableBroker.commitTransaction");
if (myWaitingForFirstOp)
myWaitingForFirstOp = false;
else
myPublisherCore.commitTransaction ();
_publisher_core.commitTransaction();
}
public void rollbackTransaction ()
{
public void rollbackTransaction() {
bts.Log.Gen.info("PubTableBroker.rollbackTransaction");
if (myWaitingForFirstOp)
myWaitingForFirstOp = false;
else
myPublisherCore.abortTransaction ();
_publisher_core.abortTransaction();
}
public virtual void createTable (IBlueRowCollection newTable)
{
myCheckTransaction();
if (myPublisherMap [newTable.schema.tableName.ToLower()] == null)
{
myPublisherMap [newTable.schema.tableName.ToLower()] = myGetIPubTablePublisher ();
mySchemaMap [newTable.schema.tableName.ToLower()] = newTable.schema;
public virtual void createTable(IBlueRowCollection newTable) {
string log_msg = $"PubTableBroker.createTable table: {newTable.schema.tableName}\n";
foreach (IBlueRow r in newTable) {
log_msg += $"id: {r["id"]}";
}
(myPublisherMap[newTable.schema.tableName.ToLower()] as IPubTablePublisher).createTable (newTable);
bts.Log.Gen.info(log_msg);
_check_schema_consistency(newTable.schema);
myCheckTransaction();
IPubTablePublisher table_publisher = null;
var name_key = newTable.schema.tableName.ToLower();
if (!_publisher_map.TryGetValue(name_key, out table_publisher)) {
table_publisher = _create_pubtable_publisher(name_key);
_publisher_map.Add(name_key, table_publisher);
_schema_map.Add(name_key, newTable.schema);
}
table_publisher.createTable(newTable);
}
/// <summary>
@@ -74,13 +77,17 @@ namespace BCG
/// will be thrown
/// </summary>
/// <param name="r"></param>
public virtual void addRow (IBlueRow r)
{
public virtual void addRow(IBlueRow r) {
string log_msg = $"PubTableBroker.addRow table: {r.schema.tableName} id: {r["id"]}";
bts.Log.Gen.info(log_msg);
_check_schema_consistency(r.schema);
myCheckTransaction();
if (myPublisherMap[r.schema.tableName.ToLower()] == null)
throw new ApplicationException ("Row can not be added, as the table that has not been created yet");
IPubTablePublisher table_publisher = null;
var name_key = r.schema.tableName.ToLower();
if (!_publisher_map.TryGetValue(name_key, out table_publisher))
throw new ApplicationException("Row can not be added, as the table that has not been created yet");
else
(myPublisherMap [r.schema.tableName.ToLower()] as IPubTablePublisher).addRow (r);
table_publisher.addRow(r);
}
/// <summary>
@@ -88,13 +95,17 @@ namespace BCG
/// will be thrown
/// </summary>
/// <param name="r"></param>
public virtual void deleteRow (IBlueRow r)
{
public virtual void deleteRow(IBlueRow r) {
string log_msg = $"PubTableBroker.deleteRow table: {r.schema.tableName} id: {r["id"]}";
bts.Log.Gen.info(log_msg);
_check_schema_consistency(r.schema);
myCheckTransaction();
if (myPublisherMap[r.schema.tableName.ToLower()] == null)
throw new ApplicationException ("Row can not be removed, as the table has not been created yet");
IPubTablePublisher table_publisher = null;
var name_key = r.schema.tableName.ToLower();
if (!_publisher_map.TryGetValue(name_key, out table_publisher))
throw new ApplicationException("Row can not be removed, as the table has not been created yet");
else
(myPublisherMap [r.schema.tableName.ToLower()] as IPubTablePublisher).deleteRow (r);
table_publisher.deleteRow(r);
}
/// <summary>
@@ -102,13 +113,17 @@ namespace BCG
/// will be thrown
/// </summary>
/// <param name="r"></param>
public virtual void changeRow (IBlueRow r)
{
public virtual void changeRow(IBlueRow r) {
string log_msg = $"PubTableBroker.changeRow table: {r.schema.tableName} id: {r["id"]}";
bts.Log.Gen.info(log_msg);
_check_schema_consistency(r.schema);
myCheckTransaction();
if (myPublisherMap[r.schema.tableName.ToLower()] == null)
throw new ApplicationException ("Row can not be changed, as the table has not been created yet");
IPubTablePublisher table_publisher = null;
var name_key = r.schema.tableName.ToLower();
if (!_publisher_map.TryGetValue(name_key, out table_publisher))
throw new ApplicationException("Row can not be changed, as the table has not been created yet");
else
(myPublisherMap [r.schema.tableName.ToLower()] as IPubTablePublisher).changeRow (r);
table_publisher.changeRow(r);
}
/// <summary>
@@ -116,40 +131,54 @@ namespace BCG
/// will be thrown
/// </summary>
/// <param name="r"></param>
public virtual void makeBatchChanges (IBlueRowCollection newRows,
IBlueRowCollection deletedRows,
IBlueRowCollection addedRows)
{
myCheckTransaction();
if (myPublisherMap[newRows.schema.tableName.ToLower()] == null)
throw new ApplicationException ("Batch changes can not be made, as the table has not been created yet");
public virtual void makeBatchChanges(IBlueRowCollection newRows,
IBlueRowCollection deletedRows,
IBlueRowCollection addedRows) {
string log_msg = $"PubTableBroker.makeBatchChanges {deletedRows.Count} {addedRows.Count} table: {newRows.schema.tableName} deleted_rows: ";
foreach (IBlueRow r in deletedRows)
log_msg += $"id: {r["id"]} ";
log_msg += "addedRows: ";
foreach (IBlueRow r in addedRows)
log_msg += $"id: {r["id"]}";
bts.Log.Gen.info(log_msg);
_check_schema_consistency(newRows.schema);
_check_schema_consistency(deletedRows.schema);
_check_schema_consistency(addedRows.schema);
IPubTablePublisher table_publisher = null;
var name_key = newRows.schema.tableName.ToLower();
if (!_publisher_map.TryGetValue(name_key, out table_publisher))
throw new ApplicationException("Batch changes can not be made, as the table has not been created yet");
else
(myPublisherMap [newRows.schema.tableName.ToLower()] as IPubTablePublisher).batchRemoveAdd (deletedRows, addedRows);
table_publisher.batchRemoveAdd(deletedRows, addedRows);
}
public virtual void deleteTableRows (string tableName)
{
public virtual void deleteTableRows(string tableName) {
myCheckTransaction();
(myPublisherMap [tableName.ToLower()] as IPubTablePublisher).createTable (
new BlueTable (mySchemaMap[tableName.ToLower()] as IBlueTableSchema));
(_publisher_map[tableName.ToLower()] as IPubTablePublisher).createTable(
new BlueTable(_schema_map[tableName.ToLower()] as IBlueTableSchema));
}
public int getNumberOfWaitingMessages() { return myPublisherCore.getNumberOfWaitingMessages(); }
public void clearTable(string tableName)
{myPublisherCore.clearState(PubStreamPrefixer.prefix(tableName));}
public int getNumberOfWaitingMessages() { return _publisher_core.getNumberOfWaitingMessages(); }
protected void myCheckTransaction()
{
public void clearTable(string tableName) { _publisher_core.clearState(PubStreamPrefixer.prefix(tableName)); }
protected void myCheckTransaction() {
if (myWaitingForFirstOp)
myPublisherCore.beginTransaction ();
_publisher_core.beginTransaction();
myWaitingForFirstOp = false;
}
protected virtual IPubTablePublisher myGetIPubTablePublisher ()
{
return new PubTablePublisher (myPublisherCore);
protected virtual IPubTablePublisher _create_pubtable_publisher(string tag) {
bts.Log.Gen.info($"PubTableBroker._create_pubtable_publisher tag: {tag}");
return new PubTablePublisher(tag, _publisher_core);
}
private void _check_schema_consistency(IBlueTableSchema schema_arg) {
IBlueTableSchema schema;
if (_schema_map.TryGetValue(schema_arg.tableName, out schema)) {
bts.Log.assert(BlueDataUtility.compareSchemas(schema, schema_arg));
}
}
}
}
}
@@ -4,62 +4,51 @@ using System.Data;
using BCG.Utilities;
namespace BCG
{
public class ViewPublisher : IDisposable
{
protected ViewPublisher () {}
namespace BCG {
public class ViewPublisher : IDisposable {
protected ViewPublisher() { }
/// If an name IsNullOrEmpty then it uses the name
/// in the schema (be careful with that because this
/// could lead to double publishes if the schema name
/// is not uniquely chosen)
public ViewPublisher(string name, PubTableBroker br, ViewStream vs)
{
public ViewPublisher(string name, PubTableBroker br, ViewStream vs) {
myName = name;
myView = new TableStream(name); // TODOds String.IsNullOrEmpty(name) ? vs : new ProjectStream(vs, "!", myName);
myView = String.IsNullOrEmpty(name) ? vs : new ChangeTableNameStream(vs, name);
myBroker = br;
myFirstTime = true;
myView.onChange += new DataStream.ChangeDelegate(myChangeHandler);
}
public void Dispose()
{
public void Dispose() {
myView.onChange -= new DataStream.ChangeDelegate(myChangeHandler);
if (!String.IsNullOrEmpty(myName))
myBroker.clearTable(myName);
}
private void myChangeHandler(object o)
{
DataPacket dp = (DataPacket) o;
if (myFirstTime)
{
private void myChangeHandler(object o) {
DataPacket dp = (DataPacket)o;
if (myFirstTime) {
myName = String.IsNullOrEmpty(myName) ? dp.schema.tableName : myName;
myLastRowCount = dp.newRows.Count;
myBroker.createTable(dp.newRows);
myFirstTime = false;
}
else
{
if (((dp.addedRows.Count + dp.deletedRows.Count) != 0))
{
myLastRowCount = dp.newRows.Count;
myBroker.makeBatchChanges(dp.newRows,dp.deletedRows, dp.addedRows);
} else {
if (((dp.addedRows.Count + dp.deletedRows.Count) != 0)) {
myLastRowCount = dp.newRows.Count;
myBroker.makeBatchChanges(dp.newRows, dp.deletedRows, dp.addedRows);
}
}
}
public int getLastRowPublishedCount()
{return myLastRowCount;}
public int getLastRowPublishedCount() { return myLastRowCount; }
public bool hasPublished()
{ return !myFirstTime; }
public bool hasPublished() { return !myFirstTime; }
private int myLastRowCount = -1;
private string myName;
private PubTableBroker myBroker;
protected ViewStream myView;
private bool myFirstTime;
}
}
}
@@ -12,6 +12,7 @@ using BCG.Utilities.General;
using System.Linq.Expressions;
//using mbts.spark;
using mbts;
using BCG.Extensions;
namespace BCG
{
@@ -42,6 +43,20 @@ namespace BCG
{
return get_row_value(r, col_no, err_value);
}
public static IEnumerable<T> get_covalues<T>(this IBlueRowCollection rows, string col)
{
List<T> rv = new List<T>();
foreach (IBlueRow r in rows)
rv.Add(r.get<T>(col));
return rv;
}
public static IEnumerable<T> get_covalues<T>(IEnumerable<IBlueRow> rows, string col)
{
List<T> rv = new List<T>();
foreach (IBlueRow r in rows)
rv.Add(r.get<T>(col));
return rv;
}
public static IBlueRowCollection where(this IBlueRowCollection rows, Func<IBlueRow, bool> where_func)
{
@@ -85,6 +100,30 @@ namespace BCG
}
}
public static DataPacket build_dp(IBlueRowCollection new_rows, DataPacket last_fired_dp)
{
IBlueRowCollection added_rows = new_rows;
IBlueRowCollection deleted_rows = last_fired_dp == null ? new BlueTable(new_rows.schema) : last_fired_dp.newRows;
return new DataPacket(new_rows, added_rows, deleted_rows);
}
public static DataPacket build_dp_inc(IBlueRowCollection new_rows, DataPacket last_fired_dp)
{
if (last_fired_dp == null)
{
IBlueRowCollection added_rows = new_rows;
IBlueRowCollection deleted_rows = new BlueTable(new_rows.schema);
return new DataPacket(new_rows, added_rows, deleted_rows);
}
else
{
IBlueRowCollection added_rows = null;
IBlueRowCollection deleted_rows = null;
compute_differences_id_based(new_rows, last_fired_dp.newRows, out deleted_rows, out added_rows);
return new DataPacket(new_rows, added_rows, deleted_rows);
}
}
public static IBlueRowCollection adapt_for_sql_storage(this IBlueRowCollection rows,
bool handle_datetime_min = false,
bool handle_double_nan = false)
@@ -112,6 +151,41 @@ namespace BCG
#endregion
public static void print_table(this IBlueRowCollection table, Func<string, int> get_col_width)
{
var rv = get_printed_rows(table, get_col_width);
Console.WriteLine(rv);
}
public static string get_printed_rows(this IBlueRowCollection table, Func<string, int> get_col_width)
{
// Print column headers
string rv = String.Empty;// = $"{table.schema.tableName}______________________________________";
foreach (var col_name in table.schema.columnNames)
{
int col_width = get_col_width(col_name);
rv += $"{col_name.PadRight(col_width)} ";
}
rv += "\n";
//rv += "______________________________________";
// Print table data
foreach (IBlueRow row in table)
{
foreach (string col_name in table.schema.columnNames)
{
int col_width = get_col_width(col_name);
object row_val = row[col_name];
string row_val_str = row_val.ToString();
if (row_val != null)
{
rv += $"{row_val_str.PadRight(col_width)} ";
}
}
rv += "\n";
}
return rv;
}
private static IReadOnlyDictionary<TypeCode, Type> _typecode_to_type = new Dictionary<TypeCode, Type>
{
{ TypeCode.Boolean, typeof(bool) },
@@ -891,16 +965,23 @@ namespace BCG
compute_differences_fast(new_rows, old_rows, col_indices, out out_d_rows, out out_a_rows);
}
public static void compute_differences_id_based(IBlueRowCollection new_rows, IBlueRowCollection old_rows,
out IBlueRowCollection out_d_rows, out IBlueRowCollection out_a_rows)
{
int[] col_indices = new int[] { new_rows.schema["id"].colNo };
compute_differences_fast(new_rows, old_rows, col_indices, out out_d_rows, out out_a_rows);
}
public static void compute_differences_fast(IBlueRowCollection new_rows, IBlueRowCollection old_rows, int[] col_indices,
out IBlueRowCollection out_d_rows, out IBlueRowCollection out_a_rows)
{
Func<IBlueRow, IBlueRow, bool> rows_equal = (r1, r2) =>
{
foreach (int col_no in col_indices)
if (!(r1[col_no] ?? DBNull.Value).Equals(r2[col_no] ?? DBNull.Value))
return false;
return true;
};
{
foreach (int col_no in col_indices)
if (!(r1[col_no] ?? DBNull.Value).Equals(r2[col_no] ?? DBNull.Value))
return false;
return true;
};
BlueTable del_rows = new BlueTable(new_rows.schema), add_rows = new BlueTable(new_rows.schema);
// adds + changes
@@ -1266,7 +1347,7 @@ namespace BCG
foreach (ColumnInfo ci1 in s1.columnInfo)
{
ColumnInfo ci2 = s2[ci1.colNo];
if (ci1.colName != ci2.colName || ci1.colType != ci2.colType)
if (ci1.colName != ci2.colName || ci1.colType != ci2.colType || ci1.colNo != ci2.colNo)
{
result = false;
break;
@@ -1280,6 +1361,25 @@ namespace BCG
return result;
}
public static void validate_row_schema(IBlueRow r)
{
foreach (var ci in r.schema.columnInfo)
{
object rval = r[ci.colName];
if (rval == null)
continue;
bts.Log.assert(rval.isDBNull() || rval.GetType().Equals(ci.colType));
}
}
public static void validate_table_schema(IBlueRowCollection rows)
{
foreach (IBlueRow r in rows)
{
validate_row_schema(r);
}
}
public static IBlueRowCollection removeRows(BlueTable table, string[] cols, object[] vals)
{
IBlueRowCollection dels = findMatchingRows(table, cols, vals);
@@ -5,14 +5,12 @@ using System.Data;
//using BCG.Utilities;
using System.Linq;
namespace BCG
{
namespace BCG {
/// <summary>
/// Anologue of the dotNet DataTable.
/// </summary>
[Serializable]
public class BlueTable : IBlueRowCollection
{
public class BlueTable : IBlueRowCollection {
/// <summary>
/// Hashtable indexed on "id" to speed up removes
/// </summary>
@@ -29,22 +27,19 @@ namespace BCG
/// all the data over
/// </summary>
/// <param name="table"></param>
public BlueTable(DataTable table)
{
public BlueTable(DataTable table) {
ColumnInfo[] cis = new ColumnInfo[table.Columns.Count];
int i = 0;
foreach (DataColumn col in table.Columns)
cis[i] = new ColumnInfo(col.ColumnName, i++, col.DataType);
mySchema = new BlueTableSchema(cis, table.TableName);
foreach (DataRow row in table.Rows)
{
foreach (DataRow row in table.Rows) {
IBlueRow newRow = new BlueRow(mySchema, row.ItemArray);
myIdIndex[newRow["id"]] = newRow;
}
}
public BlueTable(IBlueRowCollection table)
{
public BlueTable(IBlueRowCollection table) {
mySchema = table.schema;
foreach (IBlueRow row in table)
addRow(row);
@@ -52,12 +47,10 @@ namespace BCG
public BlueTable(string tableName,
IEnumerable objects,
params CMap[] columnMappers)
{
params CMap[] columnMappers) {
// extract schema from mappers
ColumnInfo[] cols = new ColumnInfo[columnMappers.Length];
for (int i = 0; i < columnMappers.Length; i++)
{
for (int i = 0; i < columnMappers.Length; i++) {
cols[i] = new ColumnInfo(
columnMappers[i].getColumnName(), i,
columnMappers[i].getColumnType());
@@ -66,8 +59,7 @@ namespace BCG
// load rows
int rowNumber = 0;
foreach (object rowObject in objects)
{
foreach (object rowObject in objects) {
object[] values = new object[columnMappers.Length];
for (int cn = 0; cn < columnMappers.Length; cn++)
values[cn] = columnMappers[cn].getColumnValue(rowNumber, rowObject);
@@ -87,10 +79,8 @@ namespace BCG
/// <summary>
/// Returns the row by the index, interface property
/// </summary>
public virtual IBlueRow this[int id]
{
get
{
public virtual IBlueRow this[int id] {
get {
object row = myIdIndex[id];
if (row == null)
throw new BlueDataException("ID " + id.ToString() + " does not exist in table " + mySchema.tableName);
@@ -105,8 +95,7 @@ namespace BCG
public virtual bool containsID(int id) { return myIdIndex[id] != null; }
public virtual bool tryGetValue(int id, out IBlueRow row)
{
public virtual bool tryGetValue(int id, out IBlueRow row) {
row = (IBlueRow)myIdIndex[id];
return (row != null);
}
@@ -114,8 +103,7 @@ namespace BCG
#endregion
#region BlueTable members
public virtual void clear()
{
public virtual void clear() {
myIdIndex.Clear();
}
@@ -123,8 +111,7 @@ namespace BCG
/// If a row with the same id exists, it replaces it
/// </summary>
/// <param name="r"></param>
public virtual void forceAddRow(IBlueRow r)
{
public virtual void forceAddRow(IBlueRow r) {
myIdIndex[r["id"]] = r;
}
@@ -132,44 +119,41 @@ namespace BCG
/// Adds a new row to the table.
/// </summary>
/// <param name="row"></param>
public virtual void addRow(IBlueRow row)
{
object val = row["id"];
public virtual void addRow(IBlueRow row) {
object id = row["id"];
if (val == null || val == DBNull.Value)
if (id == null || id == DBNull.Value)
throw new BlueDataException("The ID of the row being added is null/DNBull");
try
{
myIdIndex.Add(val, row);
}
catch (ArgumentException)
{
throw new BlueDataException("ID already exists in the table " + mySchema.tableName +
" , duplication of field ID not allowed");
try {
myIdIndex.Add(id, row);
} catch (ArgumentException) {
throw new BlueDataException($"ID: {id} already exists in the table: {mySchema.tableName}");
}
}
public virtual void addRow(DataRow row)
{
public virtual void addRow(DataRow row) {
object val = row["id"];
if (val == null || val == DBNull.Value)
throw new BlueDataException("The ID of the row being added is null/DNBull");
if (myIdIndex[val] != null)
throw new BlueDataException("ID already exists in the table, duplication of field ID not allowed");
if (myIdIndex[val] != null) {
string err_msg = $"ID: {val} already exists in the table: {mySchema.tableName} duplication of field ID not allowed";
// temp TODOds remove it
bts.Log.assert(false, err_msg);
throw new BlueDataException(err_msg);
}
IBlueRow newRow = new BlueRow(mySchema, row);
myIdIndex[val] = newRow;
}
public virtual void addRows(IBlueRowCollection rows)
{
public virtual void addRows(IBlueRowCollection rows) {
foreach (IBlueRow nr in rows)
addRow(nr);
}
public virtual void addRows(IEnumerable rows)
{
public virtual void addRows(IEnumerable rows) {
foreach (IBlueRow nr in rows)
addRow(nr);
}
@@ -186,37 +170,32 @@ namespace BCG
/// Removes a row specified by the id. The index helps in making this operation O(1)
/// </summary>
/// <param name="id"></param>
public virtual bool deleteRow(int id)
{
public virtual bool deleteRow(int id) {
if (myIdIndex[id] == null)
return false;
myIdIndex.Remove(id);
return true;
}
public virtual bool deleteRows(IBlueRowCollection rows)
{
public virtual bool deleteRows(IBlueRowCollection rows) {
bool retVal = true;
foreach (IBlueRow r in rows)
retVal &= deleteRow(r);
return retVal;
}
public virtual bool deleteRows(IEnumerable rows)
{
public virtual bool deleteRows(IEnumerable rows) {
bool retVal = true;
foreach (IBlueRow r in rows)
retVal &= deleteRow(r);
return retVal;
}
public virtual void changeRow(IBlueRow r)
{
public virtual void changeRow(IBlueRow r) {
myIdIndex[r["id"]] = r;
}
public virtual void changeRows(IBlueRowCollection rows)
{
public virtual void changeRows(IBlueRowCollection rows) {
foreach (IBlueRow r in rows)
changeRow(r);
}
@@ -1,5 +1,4 @@
namespace BCG
{
namespace BCG {
using Bts.DataStream;
using bts;
@@ -10,28 +9,26 @@ namespace BCG
using System.Reflection;
using System.IO;
public class PrimitiveManager
{
public class PrimitiveManager {
private IDictionary myTypeLookupTable = new Hashtable();
private static PrimitiveManager mySelf;
private ArrayList myAssemblyNames = new ArrayList();
private PrimitiveManager()
{
private PrimitiveManager() {
myLoadAllTypes();
}
private void myLoadAllTypes()
{
private void myLoadAllTypes() {
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(myAssemblyResolver);
loadAssembly(this.GetType().Assembly.FullName);
foreach (string assemblyName in Configuration.get<DataStreamConfig>().Assemblies)
{
var assemblies = new string[] { "datastream.dll", "sharedstreams.dll" };
var config_assemblies = Configuration.get<DataStreamConfig>().Assemblies;
bts.Log.Gen.info($"PrimitiveManager.myLoadAllTypes config_assemblies: {config_assemblies}");
foreach (string assemblyName in assemblies/*config_assemblies*/) {
bts.Log.Gen.info($"PrimitiveManager.myLoadAllTypes assemblyName: {assemblyName}");
string resolvedAssemblyPath = assemblyName;
if (!System.IO.Path.IsPathRooted(assemblyName))
{
if (!System.IO.Path.IsPathRooted(assemblyName)) {
string appPath = Path.GetDirectoryName(
Assembly.GetAssembly(typeof(PrimitiveManager)).CodeBase.Substring("file:///".Length));
resolvedAssemblyPath = System.IO.Path.GetFullPath(System.IO.Path.Combine(appPath, assemblyName));
@@ -40,8 +37,7 @@ namespace BCG
}
}
private static Assembly myAssemblyResolver(object sender, ResolveEventArgs args)
{
private static Assembly myAssemblyResolver(object sender, ResolveEventArgs args) {
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
if (args.Name.Equals(a.FullName))
return a;
@@ -52,8 +48,8 @@ namespace BCG
/// Loads all the Stream types associated with the assembly
/// </summary>
/// <param name="assemblyName"></param>
public void loadAssembly(string assemblyName)
{
public void loadAssembly(string assemblyName) {
bts.Log.Gen.info($"PrimitiveManager.loadAssembly assemblyName: {assemblyName}");
if (myAssemblyNames.Contains(assemblyName))
return;
myAssemblyNames.Add(assemblyName);
@@ -65,13 +61,11 @@ namespace BCG
if (!type.IsInterface
&& !type.IsAbstract
&& type.IsSubclassOf(typeof(ViewStream))
&& type.IsPublic)
{
&& type.IsPublic) {
bool isVisible = true;
string userRep = createDefaultName(type.Name);
foreach (Attribute att in type.GetCustomAttributes(false))
if (att is DataStreamUserRespresentation)
{
if (att is DataStreamUserRespresentation) {
DataStreamUserRespresentation dsatt = att as DataStreamUserRespresentation;
isVisible = dsatt.isVisible;
userRep = isVisible ?
@@ -79,16 +73,14 @@ namespace BCG
: null;
break;
}
if (isVisible)
{
if (isVisible) {
Log.assert(myTypeLookupTable[userRep] == null);
myTypeLookupTable[userRep] = type;
}
}
}
public static string createDefaultName(string typeName)
{
public static string createDefaultName(string typeName) {
if (!typeName.EndsWith("Stream"))
return typeName;
string retVal = typeName.Remove(typeName.Length - "Stream".Length, "Stream".Length);
@@ -100,8 +92,7 @@ namespace BCG
public static PrimitiveManager instance
{
public static PrimitiveManager instance {
get { return mySelf = mySelf == null ? new PrimitiveManager() : mySelf; }
}
@@ -110,8 +101,7 @@ namespace BCG
/// </summary>
/// <param name="friendlyName"></param>
/// <returns></returns>
public string find(string friendlyName)
{
public string find(string friendlyName) {
if (myTypeLookupTable[friendlyName] == null)
throw new ApplicationException(friendlyName + " is not the friendly name of any of the loaded types");
return (myTypeLookupTable[friendlyName] as Type).Name;
@@ -124,11 +114,9 @@ namespace BCG
/// <param name="args">args can be null or an empty ICollection if the paramterless constructor
/// is the desired one</param>
/// <returns></returns>
public ViewStream build(string friendlyName, ICollection args)
{
public ViewStream build(string friendlyName, ICollection args) {
object[] constructorArgs = null;
if (args != null && args.Count > 0)
{
if (args != null && args.Count > 0) {
constructorArgs = new object[args.Count];
args.CopyTo(constructorArgs, 0);
}
@@ -144,8 +132,7 @@ namespace BCG
/// Returns the name of all the primitives
/// </summary>
/// <returns></returns>
public string[] getPrimitiveNames()
{
public string[] getPrimitiveNames() {
string[] retVal = new string[myTypeLookupTable.Count];
myTypeLookupTable.Keys.CopyTo(retVal, 0);
return retVal;
@@ -155,20 +142,17 @@ namespace BCG
/// Return the types of all the streams
/// </summary>
/// <returns></returns>
public Type[] getStreamTypes()
{
public Type[] getStreamTypes() {
Type[] retVal = new Type[myTypeLookupTable.Count];
myTypeLookupTable.Values.CopyTo(retVal, 0);
return retVal;
}
public ICollection getConstructorSigns(string primitiveName)
{
public ICollection getConstructorSigns(string primitiveName) {
ArrayList retVal = new ArrayList();
Log.assert(myTypeLookupTable[primitiveName] != null);
Type t = myTypeLookupTable[primitiveName] as Type;
foreach (ConstructorInfo ci in t.GetConstructors())
{
foreach (ConstructorInfo ci in t.GetConstructors()) {
string sign = "";
sign = t.Name + " (";
foreach (ParameterInfo pi in ci.GetParameters())
@@ -181,8 +165,7 @@ namespace BCG
return retVal;
}
public string getAssemblyName(string primitiveName)
{
public string getAssemblyName(string primitiveName) {
Log.assert(myTypeLookupTable[primitiveName] != null);
return (myTypeLookupTable[primitiveName] as Type).Assembly.GetName().Name;
}
@@ -42,7 +42,7 @@ namespace BCG
Delegate.Combine (myOnUpdateDelegate, value) as TableUpdateDelegate;
if (myStateTable != null)
value (myStateTable, myStateTable, new BlueTable (myStateTable.schema));
}
}
remove
{
// BlueEventLog.logEvent ("TableSubscriber being Unsubscribed for tag :" + myTag, BlueEventLevel.Information);
@@ -64,6 +64,7 @@ namespace BCG
public void update(Stream[] streams)
{
bts.Log.Gen.info($"TableAccumulator.update tag: {myTag} n_streams: {streams.Length} stream[0].len: {streams[0].Length - streams[0].Position}");
//checking the condition as a subscriber might unsubscribe in a callback and there might be more than one
//data element for that tag in the ViewStreamDatabase
if (myOnUpdateDelegate != null)
@@ -3,16 +3,15 @@ using System.IO;
using System.Collections;
using BCG.Utilities;
namespace BCG
{
namespace BCG {
/// <summary>
/// Controls (ie creates dynamically) an IClientDeserializer and then passes data to it.
/// </summary>
public class ClientDeserializationController : IClientDeserializer
{
public class ClientDeserializationController : IClientDeserializer {
private IClientDeserializer myDeserializer;
public ClientDeserializationController () {}
private int _n_desers = 0;
public ClientDeserializationController() { }
#region IClientDeserializer Members
@@ -23,42 +22,41 @@ namespace BCG
/// <param name="streams"></param>
/// <param name="theOps"></param>
/// <param name="theRows"></param>
public void deserialize (Stream[] streams, out byte[] theOps, out Array theRows)
{
if (myDeserializer != null)
{
myDeserializer.deserialize (streams, out theOps, out theRows);
}
else
{
Stream totalStream = UtilityMethods.getAggregatedStream (streams);
public void deserialize(Stream[] streams, out byte[] theOps, out Array theRows) {
bts.Log.Gen.info($"ClientDeserializationController.deserialize len: {streams[0].Length - streams[0].Position}");
if (myDeserializer != null) {
myDeserializer.deserialize(streams, out theOps, out theRows);
} else {
Stream totalStream = UtilityMethods.getAggregatedStream(streams);
long initialPos = totalStream.Position;
BinaryReader br = new BinaryReader (totalStream);
BinaryReader br = new BinaryReader(totalStream);
byte op;
try
{
op = br.ReadByte ();
}
catch (EndOfStreamException)
{
try {
op = br.ReadByte();
} catch (EndOfStreamException) {
op = Byte.MaxValue;
}
if (op == StreamOpCode.create)
{
br.ReadString (); //pubsubclientdeserializer
string deserName = br.ReadString ();
myDeserializer = Activator.CreateInstance (Type.GetType (deserName))
if (op == StreamOpCode.create) {
br.ReadString(); //pubsubclientdeserializer
string deserName = br.ReadString();
myDeserializer = Activator.CreateInstance(Type.GetType(deserName))
as IClientDeserializer;
totalStream.Position = initialPos;
myDeserializer.deserialize (new Stream[] {totalStream}, out theOps, out theRows);
}
else
{
myDeserializer.deserialize(new Stream[] { totalStream }, out theOps, out theRows);
} else {
// BlueEventLog.logEvent ("Received a non create before a create", BlueEventLevel.Warning);
theOps = new byte[]{};
theRows = new object[]{};
theOps = new byte[] { };
theRows = new object[] { };
}
}
var msgs = StreamIOMessage.assemble_msgs(theOps, theRows);
int i = 0;
foreach (var m in msgs) {
bts.Log.Gen.info($"ClientDeserializationController n_desers: {_n_desers} msg no: {i++}: {m}");
}
_n_desers++;
// log it here
}
@@ -5,61 +5,61 @@ using System.IO;
using BCG.Utilities;
//using BCG.Utilities.BlueConfiguration;
namespace BCG
{
namespace BCG {
/// <summary>
/// Helps the ClientUniversalDeserializer in deserilizing by dealing with the deserialization process
/// of one row. This leaves the ClientUniversalDeserializer to deserializer headers (indicating operations)
/// </summary>
internal class ClientUniversalRowDeserializer : IClientRowDeserializer
{
internal class ClientUniversalRowDeserializer : IClientRowDeserializer {
private IBlueTableSchema mySchema;
private int myNullMapLength = 0;
private PrimitiveDeserializationHelper myDeserializationHelper;
private BitArray myNullMap;
private int[] mySerIndexToSchemaIndexMap;
public ClientUniversalRowDeserializer (IBlueTableSchema schema)
{
myDeserializationHelper = new PrimitiveDeserializationHelper (mySchema = schema);
myNullMapLength = Convert.ToInt32((Math.Ceiling(Convert.ToDouble(mySchema.columnNames.Length)/8)));
myInitReorderSchema ();
public ClientUniversalRowDeserializer(IBlueTableSchema schema) {
myDeserializationHelper = new PrimitiveDeserializationHelper(mySchema = schema);
myNullMapLength = Convert.ToInt32((Math.Ceiling(Convert.ToDouble(mySchema.columnNames.Length) / 8)));
myInitReorderSchema();
}
#region Schema Reordering initialization
private void myInitReorderSchema ()
{
int idColIndex = mySchema["id"].colNo;
int[] temp = new int [mySchema.columnInfo.Length];
foreach (ColumnInfo ci in mySchema.columnInfo)
{
temp[ci.colNo] =
ci.colNo == idColIndex ? 0 :
ci.colNo < idColIndex ? ci.colNo + 1 : ci.colNo;
private void myInitReorderSchema() {
try {
int idColIndex = mySchema["id"].colNo;
int[] temp = new int[mySchema.columnInfo.Length];
foreach (ColumnInfo ci in mySchema.columnInfo) {
temp[ci.colNo] =
ci.colNo == idColIndex ? 0 :
ci.colNo < idColIndex ? ci.colNo + 1 : ci.colNo;
}
mySerIndexToSchemaIndexMap = new int[temp.Length];
for (int i = 0; i < temp.Length; i++)
mySerIndexToSchemaIndexMap[temp[i]] = i;
} catch (Exception ex) {
string schema_name = mySchema == null ? "NULL" : mySchema.tableName;
string err_msg = $"ClientUniversalRowDeserializer.myInitReorderSchema table: {schema_name} ex: {ex}";
bts.Log.Gen.error(err_msg);
throw new ApplicationException(err_msg);
}
mySerIndexToSchemaIndexMap = new int[temp.Length];
for (int i = 0; i < temp.Length; i ++)
mySerIndexToSchemaIndexMap [temp[i]] = i;
}
#endregion
#region IClientRowDeserializer Members
public void deserializeRow (IBlueRowCollection currentState, BinaryReader br, byte op, out IBlueRow r)
{
br.ReadInt32 (); //length information for the row not needed
myNullMap = new BitArray(br.ReadBytes (myNullMapLength));
object[] values = new object [mySchema.columnNames.Length];
for (int i = 0; i < values.Length; i++)
{
public void deserializeRow(IBlueRowCollection currentState, BinaryReader br, byte op, out IBlueRow r) {
br.ReadInt32(); //length information for the row not needed
myNullMap = new BitArray(br.ReadBytes(myNullMapLength));
object[] values = new object[mySchema.columnNames.Length];
for (int i = 0; i < values.Length; i++) {
int colNo = mySerIndexToSchemaIndexMap[i];
values[mySerIndexToSchemaIndexMap[i]] = myNullMap[colNo] ? DBNull.Value : myDeserializationHelper.deserializeColumn (colNo, br);
values[mySerIndexToSchemaIndexMap[i]] = myNullMap[colNo] ? DBNull.Value : myDeserializationHelper.deserializeColumn(colNo, br);
}
r = new BlueRow(mySchema, values);
r = new BlueRow(mySchema, values);
}
@@ -1,22 +1,149 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace BCG {
public class StreamIOMessage {
public enum StreamOp {
Create = 0,
Add = 1, //adds a single row
Remove = 2, //removes a single row
Change = 3, //changes a single row
MultipleRemoveAdd = 4,//removes and adds multiple rows
MultipleChange = 5 //changes multiples rows
}
public class CreateMessage {
public IBlueRowCollection rows;
public override string ToString() {
string rv = "Create message ";
if (rows == null) {
rv += " rows: null";
return rv;
}
foreach (IBlueRow r in rows) {
rv += $"id: {r["id"]} ";
}
return rv;
}
}
public class AddMessage {
public IBlueRow added_row;
}
public class RemoveMessage {
public IBlueRow removed_row;
}
public class ChangeMessage {
public IBlueRow changed_row;
}
public class MultipleRemoveAddMessage {
public IBlueRowCollection removed;
public IBlueRowCollection added;
public override string ToString() {
string rv = "MultipleRemoveAdd removed: ";
foreach (IBlueRow r in removed) {
rv += $"id: {r["id"]} ";
}
rv += "added: ";
foreach (IBlueRow r in added) {
rv += $"id: {r["id"]} ";
}
return rv;
}
}
public class MultipleChangeMessage {
public IBlueRowCollection changed;
}
public StreamOp op;
public CreateMessage create_message = null;
public AddMessage add_message = null;
public RemoveMessage remove_message = null;
public ChangeMessage change_message = null;
public MultipleRemoveAddMessage multiple_remove_add_message = null;
public MultipleChangeMessage multiple_change_message = null;
public StreamIOMessage(byte op_, object data) {
op = (StreamIOMessage.StreamOp)(op_);
switch (op) {
case StreamIOMessage.StreamOp.Create:
IBlueRowCollection state = null;
// TODO, not sure why it can be an array and by itself
if (data is IBlueRowCollection) state = data as IBlueRowCollection;
else if (data is IBlueRowCollection[]) state = (data as IBlueRowCollection[]).ElementAt(0);
create_message = new CreateMessage() { rows = state };
break;
case StreamIOMessage.StreamOp.Add:
bts.Log.assert(false);
break;
case StreamIOMessage.StreamOp.Remove:
bts.Log.assert(false);
break;
case StreamIOMessage.StreamOp.Change:
bts.Log.assert(false);
break;
case StreamIOMessage.StreamOp.MultipleRemoveAdd:
IBlueRowCollection[] row_args = data as IBlueRowCollection[];
multiple_remove_add_message = new MultipleRemoveAddMessage() { removed = row_args[0], added = row_args[1] };
break;
case StreamIOMessage.StreamOp.MultipleChange:
//IBlueRowCollection[] row_args = data as IBlueRowCollection[];
multiple_change_message = new MultipleChangeMessage() { changed = (data as IBlueRowCollection[])[0] };
break;
}
}
public override string ToString() {
switch (op) {
case StreamIOMessage.StreamOp.Create:
return create_message.ToString();
break;
case StreamIOMessage.StreamOp.Add:
bts.Log.assert(false);
return String.Empty;
break;
case StreamIOMessage.StreamOp.Remove:
bts.Log.assert(false);
return String.Empty;
break;
case StreamIOMessage.StreamOp.Change:
bts.Log.assert(false);
return String.Empty;
break;
case StreamIOMessage.StreamOp.MultipleRemoveAdd:
return multiple_remove_add_message.ToString();
break;
case StreamIOMessage.StreamOp.MultipleChange:
return multiple_change_message.ToString();
break;
}
bts.Log.assert(false);
return String.Empty;
}
public static IEnumerable<StreamIOMessage> assemble_msgs(byte[] ops, Array op_data) {
int i = 0;
List<StreamIOMessage> rv = new List<StreamIOMessage>();
foreach (byte op in ops) {
object data = op_data.GetValue(i++);
rv.Add(new StreamIOMessage(op, data));
}
return rv;
}
}
namespace BCG
{
/// <summary>
/// Performs deserialization inside the client app. The client gets either the complete data set or the
/// increments from PubSub and this interface makes sense out of them from a tabular/datastream stand point.
/// </summary>
public interface IClientDeserializer
{
public interface IClientDeserializer {
/// <summary>
/// deserializes the data received by the client from the pubsub
/// </summary>
/// <param name="serializedData">the data in byte format received from pubsub</param>
/// <param name="theOps">the operations that the data maps onto</param>
/// <param name="theRows">the data corresponding to the operations, is an array of IblueRowCollection[]</param>
void deserialize (Stream[] streams, out byte[] theOps, out Array theRows);
void deserialize(Stream[] streams, out byte[] theOps, out Array theRows);
}
}
@@ -2,13 +2,11 @@ using System;
using System.IO;
using System.Collections;
namespace BCG
{
namespace BCG {
/// <summary>
/// Deserializes one row. the current state is also provided as some deserialization schemes might use it.
/// </summary>
public interface IClientRowDeserializer
{
void deserializeRow (IBlueRowCollection currentState, BinaryReader br, byte op, out IBlueRow r);
public interface IClientRowDeserializer {
void deserializeRow(IBlueRowCollection currentState, BinaryReader br, byte op, out IBlueRow r);
}
}
@@ -2,171 +2,158 @@ using System;
using System.Collections;
using System.IO;
namespace BCG
{
/// <summary>
/// The only instance of IPubTableBroker. It handles the publishing of one tag, and holds a specialized serializer
/// that it initializes according to the table, to optimize serialiazation, hence bw and performance
/// This class is held (as an interface) by the PubTableBroker, which guarantees the sanity of calls,
/// ie the first call will always be create.
/// </summary>
public class PubTablePublisher : IPubTablePublisher
{
namespace BCG {
/// <summary>
/// The only instance of IPubTableBroker. It handles the publishing of one tag, and holds a specialized serializer
/// that it initializes according to the table, to optimize serialiazation, hence bw and performance
/// This class is held (as an interface) by the PubTableBroker, which guarantees the sanity of calls,
/// ie the first call will always be create.
/// </summary>
public class PubTablePublisher : IPubTablePublisher {
private readonly string _tag;
protected IBlueDataSerializer mySerializer;
protected PublisherCore myPubCore;
public PubTablePublisher (PublisherCore publisherCore)
{
public PubTablePublisher(string tag, PublisherCore publisherCore) {
_tag = tag;
bts.Log.Gen.info($"PubTablePublisher.cons created for tag: {tag}");
myPubCore = publisherCore;
mySerializer = new BlueDataSerializationController ();
mySerializer = new BlueDataSerializationController();
}
#region IPubTablePublisher Members
public virtual void addRow (IBlueRow row)
{
public virtual void addRow(IBlueRow row) {
byte[] data;
mySerializer.serialize (StreamOpCode.add,
myGetRowCollectionArray (row),
mySerializer.serialize(StreamOpCode.add,
myGetRowCollectionArray(row),
out data);
myPublish (data, row.schema.tableName);
myPublish(data, row.schema.tableName);
}
public virtual void deleteRow (IBlueRow row)
{
public virtual void deleteRow(IBlueRow row) {
byte[] data;
mySerializer.serialize (StreamOpCode.remove,
myGetRowCollectionArray (row),
mySerializer.serialize(StreamOpCode.remove,
myGetRowCollectionArray(row),
out data);
myPublish (data, row.schema.tableName);
myPublish(data, row.schema.tableName);
}
public virtual void changeRow(IBlueRow row)
{
public virtual void changeRow(IBlueRow row) {
byte[] data;
mySerializer.serialize (StreamOpCode.change,
myGetRowCollectionArray (row),
mySerializer.serialize(StreamOpCode.change,
myGetRowCollectionArray(row),
out data);
myPublish (data, row.schema.tableName);
myPublish(data, row.schema.tableName);
}
public virtual void createTable (IBlueRowCollection rows)
{
public virtual void createTable(IBlueRowCollection rows) {
byte[] data;
mySerializer.serialize (StreamOpCode.create,
new IBlueRowCollection [] {rows},
mySerializer.serialize(StreamOpCode.create,
new IBlueRowCollection[] { rows },
out data);
myPublish (data, rows.schema.tableName);
bts.Log.Gen.info($"PubTablePublisher.createTable tag: {_tag} rows: {rows.Count} data: {data.Length}");
myPublish(data, rows.schema.tableName);
// byte[] ops;
// Array rows_ds;
// _test_deserializer.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows_ds);
}
public virtual void batchRemoveAdd (IBlueRowCollection delRows, IBlueRowCollection addRows)
{
byte[] data;
if (myIsRealChange (delRows, addRows))
batchChange (addRows);
else
{
mySerializer.serialize (StreamOpCode.multipleRemoveAdd,
new IBlueRowCollection []{delRows, addRows},
//private ClientDeserializationController _test_deserializer = new ClientDeserializationController();
public virtual void batchRemoveAdd(IBlueRowCollection delRows, IBlueRowCollection addRows) {
byte[] data = null;
if (myIsRealChange(delRows, addRows))
batchChange(addRows);
else {
mySerializer.serialize(StreamOpCode.multipleRemoveAdd,
new IBlueRowCollection[] { delRows, addRows },
out data);
myPublish (data, delRows.schema.tableName);
myPublish(data, delRows.schema.tableName);
}
// byte[] ops;
// Array rows_ds;
// _test_deserializer.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows_ds);
}
public virtual void batchChange (IBlueRowCollection rows)
{
public virtual void batchChange(IBlueRowCollection rows) {
byte[] data;
mySerializer.serialize (StreamOpCode.multipleChange,
new IBlueRowCollection [] {rows},
mySerializer.serialize(StreamOpCode.multipleChange,
new IBlueRowCollection[] { rows },
out data);
myPublish (data, rows.schema.tableName);
myPublish(data, rows.schema.tableName);
}
#endregion
#region private methods
private void myPublish (byte[] data, string tableName)
{
private void myPublish(byte[] data, string tableName) {
bts.Log.Gen.info($"PubTablePublisher.myPublish table: {tableName} data: {data.Length}");
if (data.Length > 0)
myPubCore.publish ("DataStreamTag",
PubStreamPrefixer.prefix (tableName),
new MemoryStream (data, 0, data.Length, false, true));
myPubCore.publish("DataStreamTag",
PubStreamPrefixer.prefix(tableName),
new MemoryStream(data, 0, data.Length, false, true));
}
private IBlueRowCollection[] myGetRowCollectionArray (IBlueRow r)
{
return new IBlueRowCollection []{
private IBlueRowCollection[] myGetRowCollectionArray(IBlueRow r) {
return new IBlueRowCollection[]{
BlueDataUtility.toBlueRowCollection (new IBlueRow[] {r})
};
}
private bool myIsRealChange (IBlueRowCollection delRows, IBlueRowCollection addRows)
{
if (delRows.Count == addRows.Count)
{
private bool myIsRealChange(IBlueRowCollection delRows, IBlueRowCollection addRows) {
if (delRows.Count == addRows.Count) {
foreach (IBlueRow dRow in delRows)
if (!addRows.containsID ((int)dRow["id"]))
if (!addRows.containsID((int)dRow["id"]))
return false;
return true;
}
else
} else
return false;
}
#endregion
}
public class IndependentTablePublisher : PubTablePublisher
{
public class IndependentTablePublisher : PubTablePublisher {
bool myIsCreated = false;
public IndependentTablePublisher (PublisherCore pubCore) : base (pubCore)
{}
public IndependentTablePublisher(string tag, PublisherCore pubCore) : base(tag, pubCore) { }
public override void addRow (IBlueRow row)
{
myCheckCreate (row.schema);
base.addRow (row);
public override void addRow(IBlueRow row) {
myCheckCreate(row.schema);
base.addRow(row);
}
public override void batchChange (IBlueRowCollection rows)
{
myCheckCreate (rows.schema);
base.batchChange (rows);
public override void batchChange(IBlueRowCollection rows) {
myCheckCreate(rows.schema);
base.batchChange(rows);
}
public override void batchRemoveAdd (IBlueRowCollection delRows, IBlueRowCollection addRows)
{
myCheckCreate (delRows.schema);
base.batchRemoveAdd (delRows, addRows);
public override void batchRemoveAdd(IBlueRowCollection delRows, IBlueRowCollection addRows) {
myCheckCreate(delRows.schema);
base.batchRemoveAdd(delRows, addRows);
}
public override void changeRow (IBlueRow row)
{
myCheckCreate (row.schema);
base.changeRow (row);
public override void changeRow(IBlueRow row) {
myCheckCreate(row.schema);
base.changeRow(row);
}
public override void deleteRow (IBlueRow row)
{
myCheckCreate (row.schema);
base.deleteRow (row);
public override void deleteRow(IBlueRow row) {
myCheckCreate(row.schema);
base.deleteRow(row);
}
public override void createTable(IBlueRowCollection rows)
{
public override void createTable(IBlueRowCollection rows) {
myIsCreated = true;
base.createTable (rows);
base.createTable(rows);
}
private void myCheckCreate (IBlueTableSchema schema)
{
if (!myIsCreated)
{
private void myCheckCreate(IBlueTableSchema schema) {
if (!myIsCreated) {
//so that the initiazliation work is done on the serializer
byte[] placeHolder;
mySerializer.serialize (StreamOpCode.create, new IBlueRowCollection [] {new BlueTable (schema)}, out placeHolder);
mySerializer.serialize(StreamOpCode.create, new IBlueRowCollection[] { new BlueTable(schema) }, out placeHolder);
myIsCreated = true;
}
}
@@ -1,18 +1,16 @@
using System;
namespace BCG
{
/// <summary>
/// Deals with the publication of one tag. Gets the specific implementaion of IBlueDataSerializer according to
/// the table name, from the config, and wraps around it. The external code that will deal with user calls for
/// row operations (PubTablePublisher) will only deal with this class, hence will be agnostic of the specalized
/// serialization.
/// </summary>
public class BlueDataSerializationController : IBlueDataSerializer
{
namespace BCG {
/// <summary>
/// Deals with the publication of one tag. Gets the specific implementaion of IBlueDataSerializer according to
/// the table name, from the config, and wraps around it. The external code that will deal with user calls for
/// row operations (PubTablePublisher) will only deal with this class, hence will be agnostic of the specalized
/// serialization.
/// </summary>
public class BlueDataSerializationController : IBlueDataSerializer {
private IBlueDataSerializer mySerializer;
public BlueDataSerializationController () {}
public BlueDataSerializationController() { }
#region IBlueDataSerializer Members
@@ -23,43 +21,37 @@ namespace BCG
/// <param name="op"></param>
/// <param name="rows"></param>
/// <param name="serializedData"></param>
public void serialize (byte op, IBlueRowCollection[] rows, out byte[] serializedData)
{
if (op == StreamOpCode.create)
{
public void serialize(byte op, IBlueRowCollection[] rows, out byte[] serializedData) {
if (op == StreamOpCode.create) {
if (mySerializer == null)
mySerializer = myGetSerializerForTable(rows[0].schema);
mySerializer.serialize (op, rows, out serializedData);
}
else
{
if (mySerializer != null)
{
mySerializer.serialize (op, rows, out serializedData);
}
else
{
serializedData = new byte[] {};
mySerializer.serialize(op, rows, out serializedData);
} else {
if (mySerializer != null) {
mySerializer.serialize(op, rows, out serializedData);
} else {
serializedData = new byte[] { };
}
}
}
#endregion
private IBlueDataSerializer myGetSerializerForTable(IBlueTableSchema theSchema)
{
private IBlueDataSerializer myGetSerializerForTable(IBlueTableSchema theSchema) {
// TODOds
return new UniversalSerializer(theSchema);
string serializerName = DataStreamGatewaySettings.instance.getSerializer(theSchema.tableName);
object[] serializerArgs = DataStreamGatewaySettings.instance.getSerializerArgs(theSchema.tableName);
if(serializerArgs != null)
if (serializerArgs != null)
return Activator.CreateInstance(Type.GetType(serializerName), theSchema, serializerArgs) as IBlueDataSerializer;
else
return Activator.CreateInstance(Type.GetType(serializerName), theSchema) as IBlueDataSerializer;
}
}
}
@@ -8,7 +8,7 @@ namespace BCG
public class UniversalSerializer : BlueDataSerializer
{
public UniversalSerializer (IBlueTableSchema schema)
: base ("BCG.PubsubUniversalDeserializer, DataStreamGateway", "BCG.ClientUniversalDeserializer")
: base ("BCG.PubsubUniversalDeserializer, DataStreamCore", "BCG.ClientUniversalDeserializer")
{
myRowSerializer = new UniversalRowSerializer (schema);
}
@@ -7,10 +7,11 @@ using System.Text;
namespace BCG
{
/// <summary>
/// Base class for all deserializers.
/// Base class for all pubsubs deserializers.
/// </summary>
public abstract class PubsubDeserializer : IPubsubDeserializer
{
// this is where the stream state is stored in pubsub?
protected IDictionary myState = new Hashtable ();
protected IBlueTableSchema mySchema;
protected string myClientDeserializerName; //for the getState method
@@ -35,6 +36,7 @@ namespace BCG
}
catch (EndOfStreamException)
{
// TODO, logically break loop
break;
}
if (op == StreamOpCode.create)
@@ -2,24 +2,22 @@ using System;
using System.Collections;
using System.IO;
namespace BCG
{
public class PubsubUniversalDeserializer : PubsubDeserializer
{
public PubsubUniversalDeserializer() {}
namespace BCG {
public class PubsubUniversalDeserializer : PubsubDeserializer {
public PubsubUniversalDeserializer() {
bts.Log.Gen.info("PubsubUniversalDeserializer.cons");
}
protected override IDictionary myGetRows (BinaryReader br, byte op, int noOfRows)
{
myDeserializer = myDeserializer == null ? new PubsubUniversalRowDeserializer (mySchema) : myDeserializer;
Hashtable retVal = new Hashtable ();
for (int i = 0; i < noOfRows; i++)
{
protected override IDictionary myGetRows(BinaryReader br, byte op, int noOfRows) {
myDeserializer = myDeserializer == null ? new PubsubUniversalRowDeserializer(mySchema) : myDeserializer;
Hashtable retVal = new Hashtable();
for (int i = 0; i < noOfRows; i++) {
int id; object row;
myDeserializer.deserializeRow (myState, br, op, out id, out row);
retVal.Add (id, row);
myDeserializer.deserializeRow(myState, br, op, out id, out row);
retVal.Add(id, row);
}
return retVal;
}
}
}
}
@@ -1,54 +1,46 @@
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using BCG.Utilities;
namespace BCG
{
namespace BCG {
/// <summary>
/// Keeps a collection of TagStateBanks to hold the state of each tag
/// </summary>
public class PubsubServerTagHandler : IPubSubServerTagHandler
{
private IDictionary myTagStates = new Hashtable ();
public class PubsubServerTagHandler : IPubSubServerTagHandler {
private IDictionary<string, TagStateBank> _tag_state_map = new Dictionary<string, TagStateBank>();
private bool myPublishStatistics = //DataStreamGatewaySettings.instance.enablePubsubStats;
false;
public PubsubServerTagHandler() {}
#region IPubSubServerTagHandler Members
public byte[] getContent (string tag)
{
TagStateBank stateBank = myTagStates[tag] as TagStateBank;
if (stateBank != null)
{
return stateBank.getConent ();
}
else
{
// BlueEventLog.logEvent (String.Format ("Information requested for tag {0} which does not exist now", tag), BlueEventLevel.Warning);
return new byte[] {};
public byte[] getContent(string tag) {
TagStateBank tag_state_bank;
if (_tag_state_map.TryGetValue(tag, out tag_state_bank)) {
return tag_state_bank.getConent();
} else {
bts.Log.Gen.warn("Information requested for tag: {tag}, it does not exist now");
return new byte[] { };
}
}
public void update (string tag, Stream[] messageBodies)
{
if (myPublishStatistics)
{
public void update(string tag, Stream[] messageBodies) {
bts.Log.Gen.info($"PubsubServerTagHandler.update tag: {tag} streams: {messageBodies.Length}");
if (myPublishStatistics) {
StatisticsLogger.instance.log(tag, messageBodies);
}
if (!myTagStates.Contains (tag))
{
// BlueEventLog.logEvent (String.Format ("Tag {0} received for the first time and its state created", tag), BlueEventLevel.Information);
myTagStates.Add (tag, new TagStateBank ());
TagStateBank tag_state_bank;
if (!_tag_state_map.TryGetValue(tag, out tag_state_bank)) {
bts.Log.Gen.info("tag: {tag} received for the first time creating TagStateBank for it now");
tag_state_bank = new TagStateBank();
_tag_state_map.Add(tag, tag_state_bank);
}
(myTagStates[tag] as TagStateBank).update (messageBodies);
tag_state_bank.update(messageBodies);
}
public void doWork() {}
public void doWork() { }
public string[] supportedTagTypes {get {return new string [] {"DataStreamTag"};}}
public string[] supportedTagTypes { get { return new string[] { "DataStreamTag" }; } }
public void register(InternalPublishDelegate callback) { }
@@ -1,26 +1,26 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
namespace BCG
{
public class TagStateBank
{
//private IDictionary myState = new Hashtable ();
private PubsubDeserializationController myDeserializationController = new PubsubDeserializationController ();
public TagStateBank () {}
namespace BCG {
public class TagStateBank {
private PubsubDeserializationController myDeserializationController = new PubsubDeserializationController();
public byte[] getConent ()
{
return myDeserializationController.getState ();
public TagStateBank() { }
public TagStateBank(string tag) {
bts.Log.Gen.info("TagStateBank created for tag: {tag}");
}
public void update (Stream[] streams)
{
public byte[] getConent() {
return myDeserializationController.getState();
}
public void update(Stream[] streams) {
bts.Log.Gen.info($"TagStateBank.update streams: {streams.Length}");
byte[] ops;
Array rowCollection;
myDeserializationController.deserialize (streams, out ops, out rowCollection);
myDeserializationController.deserialize(streams, out ops, out rowCollection);
}
}
}
@@ -9,7 +9,7 @@ namespace BCG
public class CompressionSerializer : IBlueDataSerializer
{
private IBlueRowSerializer myRowSerializer;
private string myPubsubDeserializerName = "BCG.CompressionPubsubDeserializer, DataStreamGateway", myClientDeserializerName = "BCG.CompressionClientDeserializer";
private string myPubsubDeserializerName = "BCG.CompressionPubsubDeserializer, DataStreamCore", myClientDeserializerName = "BCG.CompressionClientDeserializer";
public CompressionSerializer (IBlueTableSchema schema)
{
@@ -0,0 +1,236 @@
// using System;
// using System.IO;
// using NUnit.Framework;
// namespace BCG
// {
// /// <summary>
// /// Tests the deserialization happening within the pubsub.
// /// </summary>
// [TestGroup]
// public class CompressionSerializationTest
// {
// protected IBlueTableSchema mySchema;
// protected BlueTable myTable;
// protected IBlueDataSerializer mySer;
// protected IPubsubDeserializer myPubsubDeser;
// protected IClientDeserializer myClientDeser;
// [Test]
// public static void test_compression()
// {
// int n_len = 10000000;
// for (int t = 0; t < 10; t++)
// {
// Random rnd = new Random(DateTime.Now.Millisecond);
// byte[] data = new byte[n_len];
// rnd.NextBytes(data);
// BCG.Utilities.General.HighPerformanceTimer timer = new Utilities.General.HighPerformanceTimer();
// timer.start();
// byte[] compr = UtilityMethods.compress(new MemoryStream(data));
// timer.stop();
// Console.WriteLine("Time to compress {0} bytes {1} msecs ratio {2}", n_len, timer.lastIntervalTime, (1.0 * data.Length)/(1.0 * compr.Length));
// timer.start();
// Stream decompr_str = UtilityMethods.decompress(compr);
// timer.stop();
// Console.WriteLine("Time to de-compress {0} bytes {1} msecs", n_len, timer.lastIntervalTime);
// decompr_str.Position = 0;
// Assert.AreEqual(data.Length, (int)decompr_str.Length);
// for (int i = 0; i < data.Length; i++)
// Assert.AreEqual(data[i], decompr_str.ReadByte());
// }
// }
// public CompressionSerializationTest()
// {
// mySchema = new BlueTableSchema(myGetTableName(),
// new ColumnInfo("id", 0, typeof(int)),
// new ColumnInfo("i1", 1, typeof(int)),
// new ColumnInfo("d1", 2, typeof(double)),
// new ColumnInfo("dt", 3, typeof(DateTime)),
// new ColumnInfo("x", 4, typeof(byte))
// );
// mySer = new CompressionSerializer(mySchema);
// myClientDeser = new ClientDeserializationController();
// myPubsubDeser = new PubsubDeserializationController();
// }
// protected virtual string myGetTableName()
// {
// return "testUniversal";
// }
// /// <summary>
// /// Tests the entire cycle. This is done by 'publishing' data to the serializationController (ie a series of
// /// adds, deletions, changes etc) and getting the bytes and feeding it into a pubsubDeseriazlier and a clientDeserializer.
// /// At every step the data is tested for consistency. At the end the getState is used to get all the data, and its passed
// /// through the clientDeserializer to get all the rows.
// /// </summary>
// [Test]
// public void testEntireProcess()
// {
// myTable = new BlueTable(mySchema);
// byte[] data;
// int id;
// //create
// for (id = 0; id < 100; id++)
// myTable.addRow(myGetRow(id));
// byte[] ops;
// Array rows;
// IBlueRowCollection del, add;
// IBlueRowCollection[] receivedData;
// IBlueRow r;
// //create
// mySer.serialize(StreamOpCode.create, new IBlueRowCollection[] { myTable }, out data);
// myWrite(StreamOpCode.create, data);
// myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// Assert.AreEqual(1, ops.Length);
// Assert.AreEqual(StreamOpCode.create, ops[0]);
// Assert.AreEqual(1, rows.Length);
// receivedData = rows.GetValue(0) as IBlueRowCollection[];
// Assert.AreEqual(1, receivedData.Length);
// BlueDataUtility.computeDifferences(receivedData[0], myTable, out del, out add);
// Assert.AreEqual(0, del.Count);
// Assert.AreEqual(0, add.Count);
// //single add
// r = myGetRow(id);
// BlueTable temp = new BlueTable(mySchema);
// myTable.addRow(r);
// temp.addRow(r);
// mySer.serialize(StreamOpCode.add, new IBlueRowCollection[] { temp }, out data);
// myWrite(StreamOpCode.add, data);
// myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// Assert.AreEqual(1, ops.Length);
// Assert.AreEqual(StreamOpCode.add, ops[0]);
// Assert.AreEqual(1, rows.Length);
// receivedData = rows.GetValue(0) as IBlueRowCollection[];
// Assert.AreEqual(1, receivedData.Length);
// BlueDataUtility.computeDifferences(receivedData[0], temp, out del, out add);
// Assert.AreEqual(0, del.Count);
// Assert.AreEqual(0, add.Count);
// //single delete
// r = myTable[0]; //delete row with id 0
// temp = new BlueTable(mySchema);
// myTable.deleteRow(0);
// temp.addRow(r);
// mySer.serialize(StreamOpCode.remove, new IBlueRowCollection[] { temp }, out data);
// myWrite(StreamOpCode.remove, data);
// myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// Assert.AreEqual(1, ops.Length);
// Assert.AreEqual(StreamOpCode.remove, ops[0]);
// Assert.AreEqual(1, rows.Length);
// receivedData = rows.GetValue(0) as IBlueRowCollection[];
// Assert.AreEqual(1, receivedData.Length);
// BlueDataUtility.computeDifferences(receivedData[0], temp, out del, out add);
// Assert.AreEqual(0, del.Count);
// Assert.AreEqual(0, add.Count);
// //batch deletes and adds
// //0 was removed earlier, so lets delete from 1 to 24 first, and then add 101 to 124
// BlueTable delRows = new BlueTable(mySchema), addRows = new BlueTable(mySchema);
// for (int i = 1; i < 25; i++)
// {
// delRows.addRow(myTable[i]);
// myTable.deleteRow(i);
// }
// for (id = 101; id < 125; id++)
// {
// r = myGetRow(id);
// addRows.addRow(r);
// myTable.addRow(r);
// }
// for (int i = 25; i < 125; i++)
// Assert.AreEqual(true, myTable.containsID(i));
// Assert.AreEqual(100, myTable.Count);
// mySer.serialize(StreamOpCode.multipleRemoveAdd, new IBlueRowCollection[] { delRows, addRows }, out data);
// myWrite(StreamOpCode.multipleRemoveAdd, data);
// myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// Assert.AreEqual(1, ops.Length);
// Assert.AreEqual(StreamOpCode.multipleRemoveAdd, ops[0]);
// Assert.AreEqual(1, rows.Length);
// receivedData = rows.GetValue(0) as IBlueRowCollection[];
// Assert.AreEqual(2, receivedData.Length);
// BlueDataUtility.computeDifferences(receivedData[0], delRows, out del, out add);
// Assert.AreEqual(0, del.Count);
// Assert.AreEqual(0, add.Count);
// BlueDataUtility.computeDifferences(receivedData[1], addRows, out del, out add);
// Assert.AreEqual(0, del.Count);
// Assert.AreEqual(0, add.Count);
// //pure changes only
// //change the first 25, 25-49
// BlueTable changedRows = new BlueTable(mySchema);
// for (int i = 25; i < 50; i++)
// {
// MutableBlueRow mr = new MutableBlueRow(myTable[i]);
// mr.setValue(4, Byte.MaxValue);
// myTable.changeRow(mr);
// changedRows.addRow(mr);
// }
// mySer.serialize(StreamOpCode.multipleChange, new IBlueRowCollection[] { changedRows }, out data);
// myWrite(StreamOpCode.multipleChange, data);
// myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// Assert.AreEqual(1, ops.Length);
// Assert.AreEqual(StreamOpCode.multipleChange, ops[0]);
// Assert.AreEqual(1, rows.Length);
// receivedData = rows.GetValue(0) as IBlueRowCollection[];
// Assert.AreEqual(1, receivedData.Length);
// BlueDataUtility.computeDifferences(receivedData[0], changedRows, out del, out add);
// Assert.AreEqual(0, del.Count);
// Assert.AreEqual(0, add.Count);
// //final test
// data = myPubsubDeser.getState();
// new ClientDeserializationController().deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
// Assert.AreEqual(1, ops.Length);
// Assert.AreEqual(StreamOpCode.create, ops[0]);
// Assert.AreEqual(1, rows.Length);
// receivedData = rows.GetValue(0) as IBlueRowCollection[];
// Assert.AreEqual(1, receivedData.Length);
// BlueDataUtility.computeDifferences(receivedData[0], myTable, out del, out add);
// Assert.AreEqual(0, del.Count);
// Assert.AreEqual(0, add.Count);
// }
// private IBlueRow myGetRow(int id)
// {
// return new BlueRow(mySchema, // the day pp fixed this test.
// id, id + 10, id * 3.0, new DateTime(2008, 6, 4, 0, 0, 0, DateTimeKind.Unspecified), Convert.ToByte(id));
// }
// private void myWrite(byte op, byte[] data)
// {
// string s = "";
// if (op == StreamOpCode.add)
// s = "add one row";
// else if (op == StreamOpCode.change)
// s = "change one row";
// else if (op == StreamOpCode.create)
// s = "create";
// else if (op == StreamOpCode.multipleChange)
// s = "multiple change";
// else if (op == StreamOpCode.multipleRemoveAdd)
// s = "multiple add remove";
// else if (op == StreamOpCode.remove)
// s = "remove one row";
// Console.WriteLine("op = {0}, size = {1}", s, data.Length);
// }
// }
// }
@@ -0,0 +1,100 @@
// using System;
// using System.IO;
// using System.Collections;
// using NUnit.Framework;
// namespace BCG
// {
// [TestGroup]
// public class FixedChangingRowSerializationTest
// {
// private IBlueTableSchema mySchema = new BlueTableSchema ("Test",
// new ColumnInfo ("i", 0, typeof(int)),
// new ColumnInfo ("b", 1, typeof(bool)),
// new ColumnInfo ("d", 2, typeof(double)),
// new ColumnInfo ("id", 3, typeof(int)),
// new ColumnInfo ("dt", 4, typeof(DateTime)),
// new ColumnInfo ("bt", 5, typeof(byte)));
// private BlueTable myState;
// private Random myRnd = new Random (DateTime.Now.Millisecond);
// private IBlueRowSerializer mySerializer;
// private IClientRowDeserializer myRowDeserializer;
// public FixedChangingRowSerializationTest ()
// {
// myState = new BlueTable (mySchema);
// mySerializer = new FixedChangingRowSerializer (mySchema, "bt");
// myRowDeserializer = new ClientFixedChangingRowDeserializer (mySchema, new string[] {"bt"});
// }
// [Test]
// public void addTest ()
// {
// for (int i = 0; i < 1000; i++)
// {
// BinaryWriter bw = new BinaryWriter (new MemoryStream ());
// IBlueRow r = myCreateRow (i);
// mySerializer.serializeRow (r, StreamOpCode.add, bw);
// BinaryReader br = new BinaryReader (new MemoryStream ((bw.BaseStream as MemoryStream).ToArray ()));
// Assert.AreEqual (r["i"], br.ReadInt32());
// Assert.AreEqual (r["b"], br.ReadBoolean ());
// Assert.AreEqual (r["d"], br.ReadDouble ());
// Assert.AreEqual (r["id"], br.ReadInt32 ());
// Assert.AreEqual (((DateTime)r["dt"]).Ticks, br.ReadInt64());
// Assert.AreEqual (r["bt"], br.ReadByte ());
// }
// }
// [Test]
// public void removeTest ()
// {
// for (int i = 0; i < 1000; i++)
// {
// BinaryWriter bw = new BinaryWriter (new MemoryStream ());
// IBlueRow r = myCreateRow (i);
// mySerializer.serializeRow (r, StreamOpCode.remove, bw);
// BinaryReader br = new BinaryReader (new MemoryStream ((bw.BaseStream as MemoryStream).ToArray ()));
// Assert.AreEqual (r["id"], br.ReadInt32());
// }
// }
// [Test]
// public void changeTest ()
// {
// for (int i = 0; i < 1000; i++)
// {
// BinaryWriter bw = new BinaryWriter (new MemoryStream ());
// IBlueRow r = myCreateRow (i);
// mySerializer.serializeRow (r, StreamOpCode.change, bw);
// BinaryReader br = new BinaryReader (new MemoryStream ((bw.BaseStream as MemoryStream).ToArray ()));
// Assert.AreEqual (r["id"], br.ReadInt32());
// Assert.AreEqual (r["bt"], br.ReadByte());
// bool isEnd = false;
// try
// {
// br.ReadByte ();
// }
// catch (EndOfStreamException)
// {
// isEnd = true;
// }
// Assert.That (isEnd);
// }
// }
// private IBlueRow myCreateRow (int id)
// {
// return new BlueRow (mySchema,
// myRnd.Next (1000),
// myRnd.Next (1000) % 2 == 0,
// myRnd.NextDouble (),
// id,
// DateTime.Now,
// Convert.ToByte (10));
// }
// }
// }
@@ -0,0 +1,40 @@
// using System;
// namespace BCG
// {
// public class TestFixedChangingSerializer : FixedChangingSerializer
// {
// public TestFixedChangingSerializer (IBlueTableSchema schema)
// : base (schema,
// new string[] {"x"},
// "BCG.PubsubTestFixedChangingDeserializer",
// "BCG.ClientTestFixedChangingDeserializer"
// )
// {}
// }
// public class PubsubTestFixedChangingDeserializer : PubsubFixedChangingDeserializer
// {
// public PubsubTestFixedChangingDeserializer () : base (new string[] {"x"})
// {}
// }
// public class ClientTestFixedChangingDeserializer : ClientFixedChangingDeserializer
// {
// public ClientTestFixedChangingDeserializer () : base (new string[] {"x"})
// {}
// }
// public class FixedChangingSerializationTest : UniversalSerializationTest
// {
// public FixedChangingSerializationTest () {}
// protected override string myGetTableName()
// {
// return "testFixedChanging";
// }
// }
// }
@@ -0,0 +1,73 @@
// using System;
// using System.Collections;
// using System.IO;
// using NUnit.Framework;
// using BCG.Utilities.General;
// namespace BCG
// {
// [TestFixture]
// public class MarketOptionTheoSerializationTest
// {
// private IBlueTableSchema mySchema = new BlueTableSchema ("marketOptionTheo",
// new ColumnInfo ("arrayIndex", 0, typeof(byte)),
// new ColumnInfo ("cell", 1, typeof(byte)),
// new ColumnInfo ("expiration", 2, typeof(DateTime)),
// new ColumnInfo ("id", 3, typeof(int)),
// new ColumnInfo ("value", 4, typeof(double))
// );
// public MarketOptionTheoSerializationTest () {}
// [Test]
// public void serializationPerformanceTest ()
// {
// MarketOptionTheoSerializer ser = new MarketOptionTheoSerializer (mySchema);
// IClientDeserializer deser = new MarketOptionTheoClientDeserializer ();
// BlueTable bt = new BlueTable (mySchema);
// int count = 3000;
// byte[] ops;
// Array rows;
// HighPerformanceTimer timer = new HighPerformanceTimer ();
// byte[] serData = null;
// for (int i = 0; i < count; i++)
// bt.addRow (myGetRow (i));
// ///serialization
// //create
// ser.serialize (StreamOpCode.create, new IBlueRowCollection[] {bt}, out serData);
// deser.deserialize (new Stream [] {new MemoryStream (serData)}, out ops, out rows);
// ArrayList times = new ArrayList ();
// for (int i = 0; i < 25; i++)
// {
// timer.start ();
// ser.serialize (StreamOpCode.multipleRemoveAdd, new IBlueRowCollection[] {bt, bt}, out serData);
// timer.stop ();
// times.Add (timer.lastIntervalTime);
// Console.WriteLine (String.Format ("serialization of {0} rows, time = {1}, size = {2}", count, timer.lastIntervalTime, serData.Length));
// }
// times.Sort ();
// Console.WriteLine ("Median time = {0}", times[times.Count/2]);
// //deserialization
// times.Clear ();
// for (int i = 0; i < 25; i++)
// {
// timer.start ();
// deser.deserialize (new Stream [] {new MemoryStream (serData)}, out ops, out rows);
// timer.stop();
// times.Add (timer.lastIntervalTime);
// Console.WriteLine (String.Format ("deserialization of {0} rows, time = {1}", count, timer.lastIntervalTime));
// }
// times.Sort ();
// Console.WriteLine ("Median time = {0}", times[times.Count/2]);
// }
// private IBlueRow myGetRow (int id)
// {
// return new BlueRow (mySchema,
// Convert.ToByte (2), Convert.ToByte (4), DateTime.Now, id, 10.324555);
// }
// }
// }
@@ -0,0 +1,46 @@
// using System;
// using NUnit.Framework;
// using BCG.Utilities.General;
// namespace BCG
// {
// [TestFixture]
// public class Performance
// {
// public Performance()
// {
// }
// [Test]
// public void testContructionTime ()
// {
// double totalTime;
// string deserName = "BCG.ClientUniversalDeserializer";
// HighPerformanceTimer timer = new HighPerformanceTimer ();
// IClientDeserializer cd;
// for (int i = 0; i < 100; i++)
// {
// timer.start ();
// cd = Activator.CreateInstance (Type.GetType (deserName)) as IClientDeserializer;
// timer.stop ();
// //Console.Write (timer.lastIntervalTime.ToString() + " ");
// }
// Console.WriteLine ("average time = " + timer.totalMilliseconds / 100);
// totalTime = timer.totalMilliseconds;
// timer = new HighPerformanceTimer ();
// for (int i = 0; i < 100; i++)
// {
// timer.start ();
// cd = new ClientUniversalDeserializer ();
// timer.stop ();
// //Console.Write (timer.lastIntervalTime.ToString () + " ");
// }
// Console.WriteLine ("average time = " + timer.totalMilliseconds / 100);
// Console.WriteLine ("Ratio = " + totalTime/timer.totalMilliseconds);
// }
// }
// }
@@ -0,0 +1,275 @@
// using System;
// using System.IO;
// using NUnit.Framework;
// namespace BCG
// {
// [TestFixture]
// public class TableAccumulatorTest
// {
// private IBlueTableSchema mySchema = new BlueTableSchema ("test",
// new ColumnInfo ("id", 0, typeof(int)),
// new ColumnInfo ("x", 1, typeof(int)));
// private SubscriberCore mySubCore = new SubscriberCore ();
// private IBlueRowCollection myNr, myAr, myDr;
// public TableAccumulatorTest() {}
// [SetUp]
// public void tearDown ()
// {
// myNr = myAr = myDr = null;
// }
// #region create
// [Test]
// public void testCreate ()
// {
// TableAccumulator ta = new TableAccumulator ("test", mySubCore);
// IBlueDataSerializer ser = new BlueDataSerializationController ();
// byte[] data;
// BlueTable bt = new BlueTable (mySchema);
// for (int i = 0; i < 100; i++)
// bt.addRow (new BlueRow (mySchema, i, 2*i));
// ser.serialize (StreamOpCode.create, new IBlueRowCollection[] {bt}, out data);
// ta.onUpdate += new TableUpdateDelegate (myHandleUpdate);
// ta.update (new Stream[] {new MemoryStream (data)});
// //testing the data
// IBlueRowCollection dr, ar;
// //new rows
// BlueDataUtility.computeDifferences (bt, myNr, out dr, out ar);
// Assert.AreEqual (0, dr.Count);
// Assert.AreEqual (0, ar.Count);
// //added rows
// BlueDataUtility.computeDifferences (bt, myAr, out dr, out ar);
// Assert.AreEqual (0, dr.Count);
// Assert.AreEqual (0, ar.Count);
// //deleted rows;
// Assert.AreEqual (0, myDr.Count);
// ta.onUpdate -= new TableUpdateDelegate (myHandleUpdate);
// }
// #endregion
// #region single add, delete and change
// [Test]
// public void testAddRemoveChange ()
// {
// TableAccumulator ta = new TableAccumulator ("test", mySubCore);
// IBlueDataSerializer ser = new BlueDataSerializationController ();
// byte[] data;
// BlueTable bt = new BlueTable (mySchema);
// for (int i = 0; i < 100; i++)
// bt.addRow (new BlueRow (mySchema, i, 2*i));
// ser.serialize (StreamOpCode.create, new IBlueRowCollection[] {bt}, out data);
// ta.onUpdate += new TableUpdateDelegate (myHandleUpdate);
// ta.update (new Stream[] {new MemoryStream (data)});
// //add
// //add a row with id 100
// bt.clear ();
// bt.addRow (new BlueRow (mySchema, 100, 200));
// ser.serialize (StreamOpCode.add, new IBlueRowCollection[] {bt}, out data);
// ta.update (new Stream[] {new MemoryStream (data)});
// //testing the add data
// Assert.AreEqual (101, myNr.Count);
// for (int i = 0; i < 101; i++)
// myNr.containsID (i);
// Assert.AreEqual (0, myDr.Count);
// Assert.AreEqual (1, myAr.Count);
// Assert.That (myAr.containsID (100));
// //remove
// //remove the row with id 0
// bt.clear ();
// bt.addRow (new BlueRow (mySchema, 0, 0));
// ser.serialize (StreamOpCode.remove, new IBlueRowCollection[] {bt}, out data);
// ta.update (new Stream[] {new MemoryStream (data)});
// //testing remove data
// Assert.AreEqual (100, myNr.Count);
// for (int i = 0; i < 101; i++)
// {
// Assert.That ((i == 0 && !myNr.containsID (i)) || (i != 0 && myNr.containsID (i)));
// }
// Assert.AreEqual (0, myAr.Count);
// Assert.AreEqual (1, myDr.Count);
// Assert.That (myDr.containsID (0));
// //change
// bt.clear ();
// bt.addRow (new BlueRow (mySchema, 100, -100));
// ser.serialize (StreamOpCode.change, new IBlueRowCollection[] {bt}, out data);
// ta.update (new Stream[] {new MemoryStream (data)});
// //testing changed data
// Assert.AreEqual (100, myNr.Count);
// Assert.AreEqual (1, myAr.Count);
// Assert.AreEqual (100, BlueDataUtility.extractRow (myAr, 0)["id"]);
// Assert.AreEqual (-100, BlueDataUtility.extractRow (myAr, 0)["x"]);
// Assert.AreEqual (1, myDr.Count);
// Assert.AreEqual (100, BlueDataUtility.extractRow (myDr, 0)["id"]);
// Assert.AreEqual (200, BlueDataUtility.extractRow (myDr, 0)["x"]);
// ta.onUpdate -= new TableUpdateDelegate (myHandleUpdate);
// }
// #endregion
// #region multiple change
// public void testMultipleChange ()
// {
// TableAccumulator ta = new TableAccumulator ("test", mySubCore);
// IBlueDataSerializer ser = new BlueDataSerializationController ();
// byte[] data;
// BlueTable bt = new BlueTable (mySchema);
// for (int i = 0; i < 100; i++)
// bt.addRow (new BlueRow (mySchema, i, 2*i));
// ser.serialize (StreamOpCode.create, new IBlueRowCollection[] {bt}, out data);
// ta.onUpdate += new TableUpdateDelegate (myHandleUpdate);
// ta.update (new Stream[] {new MemoryStream (data)});
// //partial rows changed
// bt.clear ();
// for (int i = 0; i < 50; i++)
// bt.addRow (new BlueRow (mySchema, i, -2*i));
// ser.serialize (StreamOpCode.multipleChange, new IBlueRowCollection[] {bt}, out data);
// ta.update (new Stream[] {new MemoryStream (data)});
// //checking received data
// Assert.AreEqual (100, myNr.Count);
// foreach (IBlueRow r in myNr)
// {
// if ((int)r["id"] < 50)
// Assert.AreEqual ((int)r["id"] * -2, r["x"]);
// else
// Assert.AreEqual ((int)r["id"] * 2, r["x"]);
// }
// Assert.AreEqual (50, myAr.Count);
// foreach (IBlueRow r in myAr)
// Assert.AreEqual ((int)r["id"] * -2, r["x"]);
// Assert.AreEqual (50, myDr.Count);
// foreach (IBlueRow r in myDr)
// Assert.AreEqual ((int)r["id"] * 2, r["x"]);
// //full rows changed
// bt.clear ();
// for (int i = 0; i < 100; i++)
// bt.addRow (new BlueRow (mySchema, i, -2*i));
// ser.serialize (StreamOpCode.multipleChange, new IBlueRowCollection[] {bt}, out data);
// ta.update (new Stream[] {new MemoryStream (data)});
// //checking received data
// Assert.AreEqual (100, myNr.Count);
// foreach (IBlueRow r in myNr)
// {
// Assert.AreEqual ((int)r["id"] * -2, r["x"]);
// }
// Assert.AreEqual (100, myAr.Count);
// foreach (IBlueRow r in myAr)
// Assert.AreEqual ((int)r["id"] * -2, r["x"]);
// Assert.AreEqual (100, myDr.Count);
// foreach (IBlueRow r in myDr)
// {
// if ((int)r["id"] < 50)
// Assert.AreEqual ((int)r["id"] * -2, r["x"]);
// else
// Assert.AreEqual ((int)r["id"] * 2, r["x"]);
// }
// ta.onUpdate -= new TableUpdateDelegate (myHandleUpdate);
// }
// #endregion
// #region multiple deletes/adds
// public void testMultipleDeletesAdds ()
// {
// TableAccumulator ta = new TableAccumulator ("test", mySubCore);
// IBlueDataSerializer ser = new BlueDataSerializationController ();
// byte[] data;
// BlueTable bt = new BlueTable (mySchema);
// for (int i = 0; i < 100; i++)
// bt.addRow (new BlueRow (mySchema, i, 2*i));
// ser.serialize (StreamOpCode.create, new IBlueRowCollection[] {bt}, out data);
// ta.onUpdate += new TableUpdateDelegate (myHandleUpdate);
// ta.update (new Stream[] {new MemoryStream (data)});
// BlueTable at = new BlueTable (mySchema),
// dt = new BlueTable (mySchema);
// for (int i = 0; i < 50; i++)
// dt.addRow (new BlueRow (mySchema, i, 2*i));
// for (int i = 100; i < 150; i++)
// at.addRow (new BlueRow (mySchema, i, 2*i));
// ser.serialize (StreamOpCode.multipleRemoveAdd, new IBlueRowCollection[] {dt, at}, out data);
// ta.update (new Stream[] {new MemoryStream (data)});
// //checking state
// Assert.AreEqual (100, myNr.Count);
// for (int i = 50; i < 150; i++)
// Assert.That (myNr.containsID (i));
// Assert.AreEqual (50, myDr.Count);
// for (int i = 0; i < 50; i++)
// Assert.That (myDr.containsID (i));
// Assert.AreEqual (50, myAr.Count);
// for (int i = 100; i < 150; i++)
// Assert.That (myAr.containsID (i));
// ta.onUpdate -= new TableUpdateDelegate (myHandleUpdate);
// }
// #endregion
// #region multiple ops in one stream
// [Test]
// public void testMultipleOps ()
// {
// TableAccumulator ta = new TableAccumulator ("test", mySubCore);
// ta.onUpdate += new TableUpdateDelegate (myHandleUpdate);
// IBlueDataSerializer ser = new BlueDataSerializationController ();
// byte[] data;
// MemoryStream ms = new MemoryStream ();
// BlueTable bt = new BlueTable (mySchema);
// for (int i = 0; i < 100; i++)
// bt.addRow (new BlueRow (mySchema, i, 2*i));
// ser.serialize (StreamOpCode.create, new IBlueRowCollection[] {bt}, out data);
// ta.update (new Stream[] {new MemoryStream (data)});
// //ms.Write (data, 0, data.Length);
// //changing the first 5 rows
// bt.clear ();
// for (int i = 0; i < 5; i++)
// bt.addRow (new BlueRow (mySchema, i, 1000));
// ser.serialize (StreamOpCode.multipleChange, new IBlueRowCollection[] {bt}, out data);
// ms.Write (data, 0, data.Length);
// //delete id 5
// bt.clear ();
// bt.addRow (new BlueRow (mySchema, 5, 10));
// ser.serialize (StreamOpCode.remove, new IBlueRowCollection[] {bt}, out data);
// ms.Write (data, 0, data.Length);
// //add id 100
// bt.clear ();
// bt.addRow (new BlueRow (mySchema, 100, 200));
// ser.serialize (StreamOpCode.add, new IBlueRowCollection[] {bt}, out data);
// ms.Write (data, 0, data.Length);
// //delete 4 and add 5
// bt.clear ();
// BlueTable dels = new BlueTable (bt.schema);
// for (int i = 90; i < 94; i++)
// dels.addRow (new BlueRow (mySchema, i, i*2));
// for (int i = 101; i < 106; i++)
// bt.addRow (new BlueRow (mySchema, i, 2*i));
// ser.serialize (StreamOpCode.multipleRemoveAdd, new IBlueRowCollection[] {dels, bt}, out data);
// ms.Write (data, 0, data.Length);
// ms.Position = 0;
// ta.update (new Stream[] {ms});
// Assert.AreEqual (101, myNr.Count);
// Assert.AreEqual (10, myDr.Count);
// Assert.AreEqual (11, myAr.Count);
// ta.onUpdate -= new TableUpdateDelegate (myHandleUpdate);
// }
// #endregion
// private void myHandleUpdate (IBlueRowCollection nr, IBlueRowCollection ar, IBlueRowCollection dr)
// {
// myNr = nr;
// myAr = ar;
// myDr = dr;
// }
// }
// }
@@ -0,0 +1,58 @@
// using System;
// using System.IO;
// using NUnit.Framework;
// namespace BCG
// {
// [TestFixture]
// public class UniversalRowSerializerTest
// {
// private IBlueRowSerializer myRowSerializer;
// private IClientRowDeserializer myRowDeserializer;
// private Random myRnd = new Random (DateTime.Now.Millisecond);
// private IBlueTableSchema mySchema = new BlueTableSchema ("Test",
// new ColumnInfo ("id", 0, typeof(int)),
// new ColumnInfo ("int1", 1, typeof(int)),
// new ColumnInfo ("int2", 2, typeof(int)),
// new ColumnInfo ("double1", 3, typeof(double)),
// new ColumnInfo ("double2", 4, typeof(double)),
// new ColumnInfo ("byte1", 5, typeof(byte)),
// new ColumnInfo ("string1", 6, typeof(string)),
// new ColumnInfo ("string2", 7, typeof(string)));
// public UniversalRowSerializerTest () {}
// [Test]
// public void testSerialiazationCycle ()
// {
// myRowSerializer = new UniversalRowSerializer (mySchema);
// myRowDeserializer = new ClientUniversalRowDeserializer (mySchema);
// for (int i = 0; i < 10000; i++)
// {
// BinaryWriter bw = new BinaryWriter (new MemoryStream ());
// IBlueRow ir = myGetRandomRow ();
// myRowSerializer.serializeRow (ir, StreamOpCode.add, bw);
// IBlueRow or;
// (bw.BaseStream as MemoryStream).Position = 0;
// BinaryReader br = new BinaryReader (bw.BaseStream);
// myRowDeserializer.deserializeRow (null, br, StreamOpCode.add, out or);
// Assert.That (BlueDataUtility.computeRowEquality (ir, or));
// }
// }
// private IBlueRow myGetRandomRow ()
// {
// return new BlueRow (mySchema,
// myRnd.Next (1000),
// myRnd.Next (5)% 3 == 0 ? DBNull.Value as object : myRnd.Next (1000) as object,
// myRnd.Next (5)% 3 == 0 ? DBNull.Value as object: myRnd.Next (1000) as object,
// myRnd.Next (5)% 3 == 0 ? DBNull.Value as object : myRnd.NextDouble () as object,
// myRnd.Next (5)% 3 == 0 ? DBNull.Value as object : myRnd.NextDouble () as object,
// myRnd.Next (5)% 3 == 0 ? DBNull.Value as object : Convert.ToByte (76) as object,
// myRnd.Next (5)% 3 == 0 ? DBNull.Value as object : "abcdefgh" as object,
// myRnd.Next (5)% 3 == 0 ? DBNull.Value as object : "1234567890" as object
// );
// }
// }
// }
@@ -0,0 +1,13 @@
PubTableBroker allows publishing of streams through createTable, addRow, deleteRow, changeRow, makeBatchChanges ->
PubTablePublisher:IPubTablePublisher per tag (addRow, deleteRow, changeRow, createTable, batchRemoveAdd)
PubTablePublisher has BlueDataSerializationController:IBlueDataSerializer to serialize the rows to byte[]
BlueDataSerializationController uses a IBlueDataSerializer, which is specialized for the tag (using UniversalSerializer for now)
IBlueDataSerializer has just one function
void serialize (byte op, IBlueRowCollection[] rows, out byte[] serializedData);
the second arg is IBlueRowCollection[] because in case of op = StreamOpCode.multipleRemoveAdd, it has multiple IBlueRowCollection for rem and add
(BlueDataSerializer.serialize's comment has the serialization layout)
For each serializer we have 2 matching deserializers, IPubsubDeserializer (for PubSubservr) and IClientDeserializer (for clients subscribing to streams)
For UniversalSerializer, we have PubsubUniversalDeserializer and ClientUniversalDeserializer
@@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BCG
{
public delegate void PubSubTagURLChangeDelegate(List<string> tagsMoving, string newURL);
public interface IPubSubRouter
{
event PubSubTagURLChangeDelegate onSubURLTagRouteChange;
event PubSubTagURLChangeDelegate onPubURLTagRouteChange;
List<string> getAllPubSubSubURLs();
List<string> getAllPubSubPubURLs();
string getSubURLForTag(string tag);
string getPubURLForTag(string tag);
}
}
@@ -23,6 +23,7 @@
%token BOOLEAN_CONSTANT, INTEGER_CONSTANT, REAL_CONSTANT, DATE_TIME_CONSTANT, CS_STRING_CONSTANT, NULL_CONSTANT
%token PARENTHESIS_OPEN, PARENTHESIS_CLOSE, COMMA, IDENTIFIER, EQUALS, QUOTE_OPEN, QUOTE_CLOSE
%token LINE_COMMENT
%nonassoc EQUALS
@@ -49,6 +50,12 @@ Statement :
| IDENTIFIER EQUALS Statement {
$$ = new Assignment($1.Identifier, $3);
}
| LINE_COMMENT Statement {
$$ = $2;
}
| Statement LINE_COMMENT {
$$ = $1;
}
;
Arguments :
@@ -26,6 +26,9 @@ Comma ,
QuoteOpen \[
QuoteClose \]
/* Comments */
LineComment \/\/[^\n\r]*(\n|\r|\r\n)
%%
{Equals} {
@@ -92,4 +95,8 @@ QuoteClose \]
return (int)DataStreamExpressionToken.IDENTIFIER;
}
{LineComment} {
return (int)DataStreamExpressionToken.LINE_COMMENT;
}
%%
@@ -48,14 +48,26 @@ public class PrimitiveExpression : StatementExpression {
return PrimitiveManager.instance.build(myName, resolvedArgs);
}
string myPrintSingleArg(int atColumn, object? o, IList<string> activeBindings) {
/// Unwrap <see cref="Argument"/> to get its underlying value
while (o is Argument arg) {
o = arg.Obj;
// Safeguard against infinite loop
if (ReferenceEquals(o, arg)) {
throw new ArgumentException(
$"Detected circular reference in argument " +
$"('{nameof(arg)}.{nameof(arg.Obj)}' is '{nameof(arg)}' itself)");
}
}
string myPrintSingleArg(int atColumn, object o, IList<string> activeBindings) {
string result = new string(' ', atColumn);
if (o is null) {
return result;
}
if (o is StatementExpression)
return new string(' ', atColumn) +
((o as StatementExpression)?.print(atColumn, activeBindings) ?? string.Empty);
else {
string result = new string(' ', atColumn);
if (o is string)
result += makeCSString((string)o);
else if (o is DateTime)
@@ -3,6 +3,10 @@
<ItemGroup>
<ProjectReference Include="..\..\client\spark_api\spark_api.csproj" />
<ProjectReference Include="..\..\client\spark_core\spark_core.csproj" />
<ProjectReference Include="..\DataStreamCore\DataStreamCore.csproj" />
<ProjectReference Include="..\DataStream\DataStream.csproj" />
<ProjectReference Include="..\SharedStreams\SharedStreams.csproj" />
<ProjectReference Include="..\PubSub\PubSub.csproj" />
</ItemGroup>
<PropertyGroup>
@@ -1,16 +1,84 @@
using bts.utils;
using System;
using mbts.config;
using bts.utils;
using System.Threading.Tasks;
using Bts.DataStreamExpressions;
using System.Collections.Generic;
using System;
using bts;
using mbts;
using BCG;
BTSNativeMethods.provide_command_line(args, args.Length);
// Must initialize config before using log system
Console.WriteLine("Initializing config...");
Configuration.initialize();
for (int i = 0; i < 10; i++)
bts.Log.Gen.info($"Starting DSPublisher");
Console.WriteLine("Starting DSPublisher...");
static void init(string[] args)
{
bts.Log.Gen.info($"Starting DataStreamPublisher...log: {i}");
Console.WriteLine("Hit key to continue");
Console.ReadLine();
Func<string, string, Task> login = async (l, p) =>
{
var login = l;
var passwd = p;
var service_ctx = bts.api.core.ServiceContext.create();
await service_ctx.login(login, passwd);
};
BTSNativeMethods.provide_command_line(args, args.Length);
Configuration.initialize();
Task.Run(async () => await login("bts", String.Empty));
}
init(args);
_publish_streams();
static ViewStream build_stream(string stream_expression)
{
try
{
var exp = DataStreamExpressionsInterpreter.Evaluate(stream_expression);
var rv = exp.getView(new Dictionary<string, StatementExpression>(0));
return rv;
}
catch (Exception ex)
{
bts.Log.assert(false, $"Could not build stream: {stream_expression} ex: {ex}");
return null;
}
}
void _publish_streams()
{
PubTableBroker pb_broker = new PubTableBroker();
CloudStreamManager csm = new CloudStreamManager();
// get it from config
Dictionary<string, string> streams_to_publish = new Dictionary<string, string>() {
{"bbo","bbo()"},
{"instruments","instruments()"},
//{"timesales","timesales(10000)"},
{"books","books()"},
// {"seconds_1_10","second(1,10)"},
{"literal_420","literal(\"x\", \"420.0\")"},
// {"bbo_ts","timeSeries(bbo())"}
};
foreach (var kv in streams_to_publish)
{
var name = kv.Key;
var exp = kv.Value;
BCG.ViewStream vs = build_stream(exp);
ViewPublisher vpub = new ViewPublisher(name, pb_broker, vs);
vs.onChange += on_change;
}
while (true)
{
System.Threading.Thread.Sleep(TimeSpan.FromSeconds(1));
ViewStreamDatabase.instance.doWork();
csm.doWork();
}
}
void on_change(object obj)
{
bts.Log.Gen.info($"DSPublisher on_change dp: {obj}");
}
@@ -12,11 +12,13 @@
<ProjectReference Include="..\..\client\spark_core\spark_core.csproj" />
<ProjectReference Include="..\PubSub\PubSub.csproj" />
<ProjectReference Include="..\DataStream\DataStream.csproj" />
<ProjectReference Include="..\DataStreamCore\DataStreamCore.csproj" />
<ProjectReference Include="..\BlueRegistry\BlueRegistry.csproj" />
<ProjectReference Include="..\BaseUtilities\BaseUtilities.csproj" />
<ProjectReference Include="..\GuiUtilities\GuiUtilities.csproj" />
<ProjectReference Include="..\BooleanExpressions\BooleanExpressions.csproj" />
<ProjectReference Include="..\DataStreamExpressions\DataStreamExpressions.csproj" />
<ProjectReference Include="..\SharedStreams\SharedStreams.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+419 -369
View File
@@ -5,16 +5,16 @@
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose (bool disposing)
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose ();
components.Dispose();
}
}
base.Dispose (disposing);
base.Dispose(disposing);
}
#region Windows Form Designer generated code
@@ -22,500 +22,549 @@
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent ()
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
components = new System.ComponentModel.Container();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.myQueryTextBox = new System.Windows.Forms.RichTextBox();
this.myTabControl = new System.Windows.Forms.TabControl();
this.myViewTabPage = new System.Windows.Forms.TabPage();
this.myDataGrid = new BCG.HScrollGrid();
this.myCSharpTabPage = new System.Windows.Forms.TabPage();
this.myCSharpText = new System.Windows.Forms.RichTextBox();
this.myErrorTabPage = new System.Windows.Forms.TabPage();
this.myErrorTextBox = new System.Windows.Forms.RichTextBox();
this.myTableListTabPage = new System.Windows.Forms.TabPage();
this.myTableListBox = new BCG.Utilities.XPControls.ListBoxXP();
this.myTableListTopPanel = new System.Windows.Forms.Panel();
this.myTableFilterBox = new System.Windows.Forms.TextBox();
this.myTableFilterLabel = new System.Windows.Forms.Label();
this.myPrimitivesPage = new System.Windows.Forms.TabPage();
this.myTreeView = new System.Windows.Forms.TreeView();
this.myConsoleTabPage = new System.Windows.Forms.TabPage();
this.myConsoleRichTextBox = new System.Windows.Forms.RichTextBox();
this.myTimer = new System.Windows.Forms.Timer(this.components);
this.mySplitter = new System.Windows.Forms.Splitter();
this.myStatusStrip = new System.Windows.Forms.StatusStrip();
this.myToolStripStatusLabelTime = new System.Windows.Forms.ToolStripStatusLabel();
this.myToolStripStatusLabelRows = new System.Windows.Forms.ToolStripStatusLabel();
this.myMenuStrip = new System.Windows.Forms.MenuStrip();
this.myToolStripMenuItemFile = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemOpen = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemSave = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemSaveAs = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemExit = new System.Windows.Forms.ToolStripMenuItem();
this.testGridToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemQuery = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemExecute = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemExecSel = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemFreeze = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemStep = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemTools = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemLoadAss = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemTest = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemToolsSep = new System.Windows.Forms.ToolStripSeparator();
this.myToolStripMenuItemClearConsole = new System.Windows.Forms.ToolStripMenuItem();
this.myToolStripMenuItemSite = new System.Windows.Forms.ToolStripMenuItem();
this.libraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.myTabControl.SuspendLayout();
this.myViewTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.myDataGrid)).BeginInit();
this.myCSharpTabPage.SuspendLayout();
this.myErrorTabPage.SuspendLayout();
this.myTableListTabPage.SuspendLayout();
this.myTableListTopPanel.SuspendLayout();
this.myPrimitivesPage.SuspendLayout();
this.myConsoleTabPage.SuspendLayout();
this.myStatusStrip.SuspendLayout();
this.myMenuStrip.SuspendLayout();
this.SuspendLayout();
myQueryTextBox = new System.Windows.Forms.RichTextBox();
myTabControl = new System.Windows.Forms.TabControl();
myViewTabPage = new System.Windows.Forms.TabPage();
myDataGrid = new HScrollGrid();
myCSharpTabPage = new System.Windows.Forms.TabPage();
myCSharpText = new System.Windows.Forms.RichTextBox();
myErrorTabPage = new System.Windows.Forms.TabPage();
myErrorTextBox = new System.Windows.Forms.RichTextBox();
myTableListTabPage = new System.Windows.Forms.TabPage();
myTableListBox = new Utilities.XPControls.ListBoxXP();
myTableListTopPanel = new System.Windows.Forms.Panel();
myTableFilterBox = new System.Windows.Forms.TextBox();
myTableFilterLabel = new System.Windows.Forms.Label();
myPrimitivesPage = new System.Windows.Forms.TabPage();
myTreeView = new System.Windows.Forms.TreeView();
myConsoleTabPage = new System.Windows.Forms.TabPage();
myConsoleRichTextBox = new System.Windows.Forms.RichTextBox();
myTimer = new System.Windows.Forms.Timer(components);
mySplitter = new System.Windows.Forms.Splitter();
myStatusStrip = new System.Windows.Forms.StatusStrip();
myToolStripStatusLabelTime = new System.Windows.Forms.ToolStripStatusLabel();
myToolStripStatusLabelRows = new System.Windows.Forms.ToolStripStatusLabel();
toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
myMenuStrip = new System.Windows.Forms.MenuStrip();
myToolStripMenuItemFile = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemOpen = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemSave = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemSaveAs = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemExit = new System.Windows.Forms.ToolStripMenuItem();
testGridToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemQuery = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemExecute = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemExecSel = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemFreeze = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemStep = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemTools = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemLoadAss = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemTest = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemToolsSep = new System.Windows.Forms.ToolStripSeparator();
myToolStripMenuItemClearConsole = new System.Windows.Forms.ToolStripMenuItem();
myToolStripMenuItemSite = new System.Windows.Forms.ToolStripMenuItem();
libraryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
myTabControl.SuspendLayout();
myViewTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)myDataGrid).BeginInit();
myCSharpTabPage.SuspendLayout();
myErrorTabPage.SuspendLayout();
myTableListTabPage.SuspendLayout();
myTableListTopPanel.SuspendLayout();
myPrimitivesPage.SuspendLayout();
myConsoleTabPage.SuspendLayout();
myStatusStrip.SuspendLayout();
myMenuStrip.SuspendLayout();
SuspendLayout();
//
// myQueryTextBox
//
this.myQueryTextBox.AutoWordSelection = true;
this.myQueryTextBox.BackColor = System.Drawing.Color.White;
this.myQueryTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.myQueryTextBox.Dock = System.Windows.Forms.DockStyle.Top;
this.myQueryTextBox.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.myQueryTextBox.ForeColor = System.Drawing.Color.Black;
this.myQueryTextBox.Location = new System.Drawing.Point(0, 24);
this.myQueryTextBox.Name = "myQueryTextBox";
this.myQueryTextBox.Size = new System.Drawing.Size(904, 208);
this.myQueryTextBox.TabIndex = 0;
this.myQueryTextBox.Text = "";
myQueryTextBox.AutoWordSelection = true;
myQueryTextBox.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myQueryTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
myQueryTextBox.Dock = System.Windows.Forms.DockStyle.Top;
myQueryTextBox.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
myQueryTextBox.ForeColor = System.Drawing.Color.White;
myQueryTextBox.Location = new System.Drawing.Point(0, 24);
myQueryTextBox.Name = "myQueryTextBox";
myQueryTextBox.Size = new System.Drawing.Size(904, 208);
myQueryTextBox.TabIndex = 0;
myQueryTextBox.Text = "";
//
// myTabControl
//
this.myTabControl.Appearance = System.Windows.Forms.TabAppearance.FlatButtons;
this.myTabControl.Controls.Add(this.myViewTabPage);
this.myTabControl.Controls.Add(this.myCSharpTabPage);
this.myTabControl.Controls.Add(this.myErrorTabPage);
this.myTabControl.Controls.Add(this.myTableListTabPage);
this.myTabControl.Controls.Add(this.myPrimitivesPage);
this.myTabControl.Controls.Add(this.myConsoleTabPage);
this.myTabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.myTabControl.Location = new System.Drawing.Point(0, 232);
this.myTabControl.Multiline = true;
this.myTabControl.Name = "myTabControl";
this.myTabControl.SelectedIndex = 0;
this.myTabControl.Size = new System.Drawing.Size(904, 335);
this.myTabControl.TabIndex = 1;
myTabControl.Appearance = System.Windows.Forms.TabAppearance.FlatButtons;
myTabControl.Controls.Add(myViewTabPage);
myTabControl.Controls.Add(myCSharpTabPage);
myTabControl.Controls.Add(myErrorTabPage);
myTabControl.Controls.Add(myTableListTabPage);
myTabControl.Controls.Add(myPrimitivesPage);
myTabControl.Controls.Add(myConsoleTabPage);
myTabControl.Dock = System.Windows.Forms.DockStyle.Fill;
myTabControl.Location = new System.Drawing.Point(0, 232);
myTabControl.Multiline = true;
myTabControl.Name = "myTabControl";
myTabControl.SelectedIndex = 0;
myTabControl.Size = new System.Drawing.Size(904, 335);
myTabControl.TabIndex = 1;
//
// myViewTabPage
//
this.myViewTabPage.Controls.Add(this.myDataGrid);
this.myViewTabPage.Location = new System.Drawing.Point(4, 26);
this.myViewTabPage.Name = "myViewTabPage";
this.myViewTabPage.Size = new System.Drawing.Size(896, 305);
this.myViewTabPage.TabIndex = 0;
this.myViewTabPage.Text = "View";
myViewTabPage.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myViewTabPage.Controls.Add(myDataGrid);
myViewTabPage.ForeColor = System.Drawing.Color.White;
myViewTabPage.Location = new System.Drawing.Point(4, 26);
myViewTabPage.Name = "myViewTabPage";
myViewTabPage.Size = new System.Drawing.Size(896, 305);
myViewTabPage.TabIndex = 0;
myViewTabPage.Text = "View";
//
// myDataGrid
//
this.myDataGrid.BackgroundColor = System.Drawing.Color.Gainsboro;
this.myDataGrid.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
// this.myDataGrid.CaptionBackColor = System.Drawing.Color.Wheat;
// this.myDataGrid.CaptionFont = new System.Drawing.Font("Comic Sans MS", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
// this.myDataGrid.CaptionForeColor = System.Drawing.Color.Black;
this.myDataGrid.DataMember = "";
this.myDataGrid.Dock = System.Windows.Forms.DockStyle.Fill;
// this.myDataGrid.FlatMode = true;
// this.myDataGrid.GridLineColor = System.Drawing.Color.Gainsboro;
// this.myDataGrid.HeaderBackColor = System.Drawing.Color.Gainsboro;
// this.myDataGrid.HeaderFont = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
// this.myDataGrid.HeaderForeColor = System.Drawing.Color.Black;
this.myDataGrid.HorizScrollBarValue = 0;
this.myDataGrid.Location = new System.Drawing.Point(0, 0);
this.myDataGrid.Name = "myDataGrid";
// this.myDataGrid.PreferredRowHeight = 20;
this.myDataGrid.ReadOnly = true;
this.myDataGrid.RowHeadersVisible = false;
// this.myDataGrid.RowHeaderWidth = 0;
this.myDataGrid.Size = new System.Drawing.Size(896, 305);
this.myDataGrid.TabIndex = 0;
this.myDataGrid.MouseEnter += new System.EventHandler(this.myDataGrid_MouseEnter);
this.myDataGrid.MouseLeave += new System.EventHandler(this.myDataGrid_MouseLeave);
myDataGrid.BackgroundColor = System.Drawing.Color.FromArgb(36, 36, 49);
myDataGrid.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single;
myDataGrid.ColumnHeadersHeight = 32;
dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle1.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
dataGridViewCellStyle1.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
dataGridViewCellStyle1.ForeColor = System.Drawing.Color.White;
dataGridViewCellStyle1.SelectionBackColor = System.Drawing.Color.Green;
dataGridViewCellStyle1.SelectionForeColor = System.Drawing.Color.Yellow;
dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
myDataGrid.DefaultCellStyle = dataGridViewCellStyle1;
myDataGrid.Dock = System.Windows.Forms.DockStyle.Fill;
myDataGrid.GridColor = System.Drawing.Color.DarkGray;
myDataGrid.HorizScrollBarValue = 0;
myDataGrid.Location = new System.Drawing.Point(0, 0);
myDataGrid.Name = "myDataGrid";
myDataGrid.ReadOnly = true;
myDataGrid.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.None;
dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle2.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
dataGridViewCellStyle2.ForeColor = System.Drawing.Color.White;
dataGridViewCellStyle2.SelectionBackColor = System.Drawing.Color.Yellow;
dataGridViewCellStyle2.SelectionForeColor = System.Drawing.Color.DimGray;
dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
myDataGrid.RowHeadersDefaultCellStyle = dataGridViewCellStyle2;
myDataGrid.RowHeadersVisible = false;
myDataGrid.RowHeadersWidth = 82;
myDataGrid.Size = new System.Drawing.Size(896, 305);
myDataGrid.TabIndex = 0;
myDataGrid.MouseEnter += myDataGrid_MouseEnter;
myDataGrid.MouseLeave += myDataGrid_MouseLeave;
//
// myCSharpTabPage
//
this.myCSharpTabPage.Controls.Add(this.myCSharpText);
this.myCSharpTabPage.Location = new System.Drawing.Point(4, 25);
this.myCSharpTabPage.Name = "myCSharpTabPage";
this.myCSharpTabPage.Size = new System.Drawing.Size(896, 306);
this.myCSharpTabPage.TabIndex = 2;
this.myCSharpTabPage.Text = "C# Class";
myCSharpTabPage.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myCSharpTabPage.Controls.Add(myCSharpText);
myCSharpTabPage.ForeColor = System.Drawing.Color.White;
myCSharpTabPage.Location = new System.Drawing.Point(4, 27);
myCSharpTabPage.Name = "myCSharpTabPage";
myCSharpTabPage.Size = new System.Drawing.Size(896, 304);
myCSharpTabPage.TabIndex = 2;
myCSharpTabPage.Text = "C# Class";
//
// myCSharpText
//
this.myCSharpText.BackColor = System.Drawing.Color.White;
this.myCSharpText.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.myCSharpText.Dock = System.Windows.Forms.DockStyle.Fill;
this.myCSharpText.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.myCSharpText.Location = new System.Drawing.Point(0, 0);
this.myCSharpText.Name = "myCSharpText";
this.myCSharpText.ReadOnly = true;
this.myCSharpText.Size = new System.Drawing.Size(896, 306);
this.myCSharpText.TabIndex = 0;
this.myCSharpText.Text = "";
this.myCSharpText.MouseEnter += new System.EventHandler(this.myCSharpText_MouseEnter);
this.myCSharpText.MouseLeave += new System.EventHandler(this.myCSharpText_MouseLeave);
myCSharpText.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myCSharpText.BorderStyle = System.Windows.Forms.BorderStyle.None;
myCSharpText.Dock = System.Windows.Forms.DockStyle.Fill;
myCSharpText.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
myCSharpText.ForeColor = System.Drawing.Color.White;
myCSharpText.Location = new System.Drawing.Point(0, 0);
myCSharpText.Name = "myCSharpText";
myCSharpText.ReadOnly = true;
myCSharpText.Size = new System.Drawing.Size(896, 304);
myCSharpText.TabIndex = 0;
myCSharpText.Text = "";
myCSharpText.MouseEnter += myCSharpText_MouseEnter;
myCSharpText.MouseLeave += myCSharpText_MouseLeave;
//
// myErrorTabPage
//
this.myErrorTabPage.Controls.Add(this.myErrorTextBox);
this.myErrorTabPage.Location = new System.Drawing.Point(4, 25);
this.myErrorTabPage.Name = "myErrorTabPage";
this.myErrorTabPage.Size = new System.Drawing.Size(896, 306);
this.myErrorTabPage.TabIndex = 1;
this.myErrorTabPage.Text = "Error";
myErrorTabPage.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myErrorTabPage.Controls.Add(myErrorTextBox);
myErrorTabPage.ForeColor = System.Drawing.Color.White;
myErrorTabPage.Location = new System.Drawing.Point(4, 27);
myErrorTabPage.Name = "myErrorTabPage";
myErrorTabPage.Size = new System.Drawing.Size(896, 304);
myErrorTabPage.TabIndex = 1;
myErrorTabPage.Text = "Error";
//
// myErrorTextBox
//
this.myErrorTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.myErrorTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.myErrorTextBox.ForeColor = System.Drawing.Color.Red;
this.myErrorTextBox.Location = new System.Drawing.Point(0, 0);
this.myErrorTextBox.Name = "myErrorTextBox";
this.myErrorTextBox.ReadOnly = true;
this.myErrorTextBox.Size = new System.Drawing.Size(896, 306);
this.myErrorTextBox.TabIndex = 1;
this.myErrorTextBox.Text = "";
myErrorTextBox.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myErrorTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
myErrorTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
myErrorTextBox.ForeColor = System.Drawing.Color.Red;
myErrorTextBox.Location = new System.Drawing.Point(0, 0);
myErrorTextBox.Name = "myErrorTextBox";
myErrorTextBox.ReadOnly = true;
myErrorTextBox.Size = new System.Drawing.Size(896, 304);
myErrorTextBox.TabIndex = 1;
myErrorTextBox.Text = "";
//
// myTableListTabPage
//
this.myTableListTabPage.Controls.Add(this.myTableListBox);
this.myTableListTabPage.Controls.Add(this.myTableListTopPanel);
this.myTableListTabPage.Location = new System.Drawing.Point(4, 25);
this.myTableListTabPage.Name = "myTableListTabPage";
this.myTableListTabPage.Size = new System.Drawing.Size(896, 306);
this.myTableListTabPage.TabIndex = 3;
this.myTableListTabPage.Text = "Table list";
myTableListTabPage.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myTableListTabPage.Controls.Add(myTableListBox);
myTableListTabPage.Controls.Add(myTableListTopPanel);
myTableListTabPage.ForeColor = System.Drawing.Color.White;
myTableListTabPage.Location = new System.Drawing.Point(4, 27);
myTableListTabPage.Name = "myTableListTabPage";
myTableListTabPage.Size = new System.Drawing.Size(896, 304);
myTableListTabPage.TabIndex = 3;
myTableListTabPage.Text = "Table list";
//
// myTableListBox
//
this.myTableListBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.myTableListBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.myTableListBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.myTableListBox.ItemHeight = 14;
this.myTableListBox.Location = new System.Drawing.Point(0, 31);
this.myTableListBox.Name = "myTableListBox";
this.myTableListBox.Size = new System.Drawing.Size(896, 275);
this.myTableListBox.TabIndex = 1;
this.myTableListBox.DoubleClick += new System.EventHandler(this.myTableListBox_DoubleClick);
this.myTableListBox.MouseEnter += new System.EventHandler(this.myTableListBox_MouseEnter);
this.myTableListBox.MouseLeave += new System.EventHandler(this.myTableListBox_MouseLeave);
myTableListBox.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myTableListBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
myTableListBox.Dock = System.Windows.Forms.DockStyle.Fill;
myTableListBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
myTableListBox.ForeColor = System.Drawing.Color.White;
myTableListBox.ItemHeight = 14;
myTableListBox.Location = new System.Drawing.Point(0, 31);
myTableListBox.Name = "myTableListBox";
myTableListBox.Size = new System.Drawing.Size(896, 273);
myTableListBox.TabIndex = 1;
myTableListBox.DoubleClick += myTableListBox_DoubleClick;
myTableListBox.MouseEnter += myTableListBox_MouseEnter;
myTableListBox.MouseLeave += myTableListBox_MouseLeave;
//
// myTableListTopPanel
//
this.myTableListTopPanel.Controls.Add(this.myTableFilterBox);
this.myTableListTopPanel.Controls.Add(this.myTableFilterLabel);
this.myTableListTopPanel.Dock = System.Windows.Forms.DockStyle.Top;
this.myTableListTopPanel.Location = new System.Drawing.Point(0, 0);
this.myTableListTopPanel.Name = "myTableListTopPanel";
this.myTableListTopPanel.Size = new System.Drawing.Size(896, 31);
this.myTableListTopPanel.TabIndex = 4;
myTableListTopPanel.Controls.Add(myTableFilterBox);
myTableListTopPanel.Controls.Add(myTableFilterLabel);
myTableListTopPanel.Dock = System.Windows.Forms.DockStyle.Top;
myTableListTopPanel.Location = new System.Drawing.Point(0, 0);
myTableListTopPanel.Name = "myTableListTopPanel";
myTableListTopPanel.Size = new System.Drawing.Size(896, 31);
myTableListTopPanel.TabIndex = 4;
//
// myTableFilterBox
//
this.myTableFilterBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.myTableFilterBox.Location = new System.Drawing.Point(58, 3);
this.myTableFilterBox.Name = "myTableFilterBox";
this.myTableFilterBox.Size = new System.Drawing.Size(835, 20);
this.myTableFilterBox.TabIndex = 2;
this.myTableFilterBox.TextChanged += new System.EventHandler(this.myTableFilterBox_TextChanged);
myTableFilterBox.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right;
myTableFilterBox.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myTableFilterBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
myTableFilterBox.ForeColor = System.Drawing.Color.White;
myTableFilterBox.Location = new System.Drawing.Point(58, 3);
myTableFilterBox.Name = "myTableFilterBox";
myTableFilterBox.Size = new System.Drawing.Size(835, 20);
myTableFilterBox.TabIndex = 2;
myTableFilterBox.TextChanged += myTableFilterBox_TextChanged;
//
// myTableFilterLabel
//
this.myTableFilterLabel.AutoSize = true;
this.myTableFilterLabel.Location = new System.Drawing.Point(3, 3);
this.myTableFilterLabel.Name = "myTableFilterLabel";
this.myTableFilterLabel.Size = new System.Drawing.Size(49, 14);
this.myTableFilterLabel.TabIndex = 3;
this.myTableFilterLabel.Text = "Filter";
myTableFilterLabel.AutoSize = true;
myTableFilterLabel.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myTableFilterLabel.ForeColor = System.Drawing.Color.White;
myTableFilterLabel.Location = new System.Drawing.Point(3, 3);
myTableFilterLabel.Name = "myTableFilterLabel";
myTableFilterLabel.Size = new System.Drawing.Size(49, 14);
myTableFilterLabel.TabIndex = 3;
myTableFilterLabel.Text = "Filter";
myTableFilterLabel.Click += myTableFilterLabel_Click;
//
// myPrimitivesPage
//
this.myPrimitivesPage.Controls.Add(this.myTreeView);
this.myPrimitivesPage.Location = new System.Drawing.Point(4, 25);
this.myPrimitivesPage.Name = "myPrimitivesPage";
this.myPrimitivesPage.Size = new System.Drawing.Size(896, 306);
this.myPrimitivesPage.TabIndex = 4;
this.myPrimitivesPage.Text = "Language primitives";
myPrimitivesPage.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myPrimitivesPage.Controls.Add(myTreeView);
myPrimitivesPage.ForeColor = System.Drawing.Color.White;
myPrimitivesPage.Location = new System.Drawing.Point(4, 27);
myPrimitivesPage.Name = "myPrimitivesPage";
myPrimitivesPage.Size = new System.Drawing.Size(896, 304);
myPrimitivesPage.TabIndex = 4;
myPrimitivesPage.Text = "Language primitives";
//
// myTreeView
//
this.myTreeView.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.myTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
this.myTreeView.Location = new System.Drawing.Point(0, 0);
this.myTreeView.Name = "myTreeView";
this.myTreeView.Size = new System.Drawing.Size(896, 306);
this.myTreeView.TabIndex = 0;
myTreeView.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myTreeView.BorderStyle = System.Windows.Forms.BorderStyle.None;
myTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
myTreeView.ForeColor = System.Drawing.Color.White;
myTreeView.Location = new System.Drawing.Point(0, 0);
myTreeView.Name = "myTreeView";
myTreeView.Size = new System.Drawing.Size(896, 304);
myTreeView.TabIndex = 0;
//
// myConsoleTabPage
//
this.myConsoleTabPage.Controls.Add(this.myConsoleRichTextBox);
this.myConsoleTabPage.Location = new System.Drawing.Point(4, 25);
this.myConsoleTabPage.Name = "myConsoleTabPage";
this.myConsoleTabPage.Padding = new System.Windows.Forms.Padding(3);
this.myConsoleTabPage.Size = new System.Drawing.Size(896, 306);
this.myConsoleTabPage.TabIndex = 5;
this.myConsoleTabPage.Text = "Console";
this.myConsoleTabPage.UseVisualStyleBackColor = true;
myConsoleTabPage.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myConsoleTabPage.Controls.Add(myConsoleRichTextBox);
myConsoleTabPage.ForeColor = System.Drawing.Color.White;
myConsoleTabPage.Location = new System.Drawing.Point(4, 27);
myConsoleTabPage.Name = "myConsoleTabPage";
myConsoleTabPage.Padding = new System.Windows.Forms.Padding(3);
myConsoleTabPage.Size = new System.Drawing.Size(896, 304);
myConsoleTabPage.TabIndex = 5;
myConsoleTabPage.Text = "Console";
//
// myConsoleRichTextBox
//
this.myConsoleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.myConsoleRichTextBox.Location = new System.Drawing.Point(3, 3);
this.myConsoleRichTextBox.Name = "myConsoleRichTextBox";
this.myConsoleRichTextBox.Size = new System.Drawing.Size(890, 300);
this.myConsoleRichTextBox.TabIndex = 0;
this.myConsoleRichTextBox.Text = "";
myConsoleRichTextBox.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myConsoleRichTextBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
myConsoleRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
myConsoleRichTextBox.ForeColor = System.Drawing.Color.White;
myConsoleRichTextBox.Location = new System.Drawing.Point(3, 3);
myConsoleRichTextBox.Name = "myConsoleRichTextBox";
myConsoleRichTextBox.Size = new System.Drawing.Size(890, 298);
myConsoleRichTextBox.TabIndex = 0;
myConsoleRichTextBox.Text = "";
//
// myTimer
//
this.myTimer.Enabled = true;
this.myTimer.Interval = 150;
this.myTimer.Tick += new System.EventHandler(this.myTimer_Tick);
myTimer.Enabled = true;
myTimer.Interval = 150;
myTimer.Tick += myTimer_Tick;
//
// mySplitter
//
this.mySplitter.Dock = System.Windows.Forms.DockStyle.Top;
this.mySplitter.Location = new System.Drawing.Point(0, 232);
this.mySplitter.Name = "mySplitter";
this.mySplitter.Size = new System.Drawing.Size(904, 3);
this.mySplitter.TabIndex = 3;
this.mySplitter.TabStop = false;
mySplitter.Dock = System.Windows.Forms.DockStyle.Top;
mySplitter.Location = new System.Drawing.Point(0, 232);
mySplitter.Name = "mySplitter";
mySplitter.Size = new System.Drawing.Size(904, 4);
mySplitter.TabIndex = 3;
mySplitter.TabStop = false;
//
// myStatusStrip
//
this.myStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.myToolStripStatusLabelTime,
this.myToolStripStatusLabelRows});
this.myStatusStrip.Location = new System.Drawing.Point(0, 567);
this.myStatusStrip.Name = "myStatusStrip";
this.myStatusStrip.Size = new System.Drawing.Size(904, 22);
this.myStatusStrip.TabIndex = 4;
myStatusStrip.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myStatusStrip.ImageScalingSize = new System.Drawing.Size(32, 32);
myStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { myToolStripStatusLabelTime, myToolStripStatusLabelRows, toolStripStatusLabel1 });
myStatusStrip.Location = new System.Drawing.Point(0, 567);
myStatusStrip.Name = "myStatusStrip";
myStatusStrip.Size = new System.Drawing.Size(904, 22);
myStatusStrip.TabIndex = 4;
//
// myToolStripStatusLabelTime
//
this.myToolStripStatusLabelTime.Name = "myToolStripStatusLabelTime";
this.myToolStripStatusLabelTime.Padding = new System.Windows.Forms.Padding(0, 0, 8, 0);
this.myToolStripStatusLabelTime.Size = new System.Drawing.Size(8, 17);
myToolStripStatusLabelTime.Name = "myToolStripStatusLabelTime";
myToolStripStatusLabelTime.Padding = new System.Windows.Forms.Padding(0, 0, 8, 0);
myToolStripStatusLabelTime.Size = new System.Drawing.Size(8, 17);
//
// myToolStripStatusLabelRows
//
this.myToolStripStatusLabelRows.Name = "myToolStripStatusLabelRows";
this.myToolStripStatusLabelRows.Size = new System.Drawing.Size(0, 17);
myToolStripStatusLabelRows.Name = "myToolStripStatusLabelRows";
myToolStripStatusLabelRows.Size = new System.Drawing.Size(0, 17);
//
// toolStripStatusLabel1
//
toolStripStatusLabel1.ForeColor = System.Drawing.Color.White;
toolStripStatusLabel1.Name = "toolStripStatusLabel1";
toolStripStatusLabel1.Size = new System.Drawing.Size(0, 17);
//
// myMenuStrip
//
this.myMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.myToolStripMenuItemFile,
this.myToolStripMenuItemQuery,
this.myToolStripMenuItemTools,
this.myToolStripMenuItemSite,
this.libraryToolStripMenuItem});
this.myMenuStrip.Location = new System.Drawing.Point(0, 0);
this.myMenuStrip.Name = "myMenuStrip";
this.myMenuStrip.Size = new System.Drawing.Size(904, 24);
this.myMenuStrip.TabIndex = 5;
this.myMenuStrip.Text = "menuStrip1";
myMenuStrip.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myMenuStrip.ImageScalingSize = new System.Drawing.Size(32, 32);
myMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { myToolStripMenuItemFile, myToolStripMenuItemQuery, myToolStripMenuItemTools, myToolStripMenuItemSite, libraryToolStripMenuItem });
myMenuStrip.Location = new System.Drawing.Point(0, 0);
myMenuStrip.Name = "myMenuStrip";
myMenuStrip.Size = new System.Drawing.Size(904, 24);
myMenuStrip.TabIndex = 5;
myMenuStrip.Text = "menuStrip1";
//
// myToolStripMenuItemFile
//
this.myToolStripMenuItemFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.myToolStripMenuItemOpen,
this.myToolStripMenuItemSave,
this.myToolStripMenuItemSaveAs,
this.myToolStripMenuItemExit,
this.testGridToolStripMenuItem});
this.myToolStripMenuItemFile.Name = "myToolStripMenuItemFile";
this.myToolStripMenuItemFile.Size = new System.Drawing.Size(37, 20);
this.myToolStripMenuItemFile.Text = "&File";
myToolStripMenuItemFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { myToolStripMenuItemOpen, myToolStripMenuItemSave, myToolStripMenuItemSaveAs, myToolStripMenuItemExit, testGridToolStripMenuItem });
myToolStripMenuItemFile.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemFile.Name = "myToolStripMenuItemFile";
myToolStripMenuItemFile.Size = new System.Drawing.Size(37, 20);
myToolStripMenuItemFile.Text = "&File";
//
// myToolStripMenuItemOpen
//
this.myToolStripMenuItemOpen.Image = global::DataStreamQueryAnalyzer.Properties.Resources.File_Open_icon16;
this.myToolStripMenuItemOpen.Name = "myToolStripMenuItemOpen";
this.myToolStripMenuItemOpen.Size = new System.Drawing.Size(123, 22);
this.myToolStripMenuItemOpen.Text = "&Open...";
this.myToolStripMenuItemOpen.Click += new System.EventHandler(this.myMenuItemOpenClick);
myToolStripMenuItemOpen.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myToolStripMenuItemOpen.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemOpen.Image = DataStreamQueryAnalyzer.Properties.Resources.File_Open_icon16;
myToolStripMenuItemOpen.Name = "myToolStripMenuItemOpen";
myToolStripMenuItemOpen.Size = new System.Drawing.Size(139, 38);
myToolStripMenuItemOpen.Text = "&Open...";
myToolStripMenuItemOpen.Click += myMenuItemOpenClick;
//
// myToolStripMenuItemSave
//
this.myToolStripMenuItemSave.Image = global::DataStreamQueryAnalyzer.Properties.Resources.Save_icon16;
this.myToolStripMenuItemSave.Name = "myToolStripMenuItemSave";
this.myToolStripMenuItemSave.Size = new System.Drawing.Size(123, 22);
this.myToolStripMenuItemSave.Text = "Save...";
this.myToolStripMenuItemSave.Click += new System.EventHandler(this.myMenuItemSaveClick);
myToolStripMenuItemSave.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myToolStripMenuItemSave.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemSave.Image = DataStreamQueryAnalyzer.Properties.Resources.Save_icon16;
myToolStripMenuItemSave.Name = "myToolStripMenuItemSave";
myToolStripMenuItemSave.Size = new System.Drawing.Size(139, 38);
myToolStripMenuItemSave.Text = "Save...";
myToolStripMenuItemSave.Click += myMenuItemSaveClick;
//
// myToolStripMenuItemSaveAs
//
this.myToolStripMenuItemSaveAs.Name = "myToolStripMenuItemSaveAs";
this.myToolStripMenuItemSaveAs.Size = new System.Drawing.Size(123, 22);
this.myToolStripMenuItemSaveAs.Text = "Save As...";
this.myToolStripMenuItemSaveAs.Click += new System.EventHandler(this.myMenuItemSaveAsClick);
myToolStripMenuItemSaveAs.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myToolStripMenuItemSaveAs.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemSaveAs.Name = "myToolStripMenuItemSaveAs";
myToolStripMenuItemSaveAs.Size = new System.Drawing.Size(139, 38);
myToolStripMenuItemSaveAs.Text = "Save As...";
myToolStripMenuItemSaveAs.Click += myMenuItemSaveAsClick;
//
// myToolStripMenuItemExit
//
this.myToolStripMenuItemExit.Image = global::DataStreamQueryAnalyzer.Properties.Resources.Button_Turn_Off_icon16;
this.myToolStripMenuItemExit.Name = "myToolStripMenuItemExit";
this.myToolStripMenuItemExit.Size = new System.Drawing.Size(123, 22);
this.myToolStripMenuItemExit.Text = "Exit";
this.myToolStripMenuItemExit.Click += new System.EventHandler(this.myToolStripMenuItemExit_Click);
myToolStripMenuItemExit.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myToolStripMenuItemExit.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemExit.Image = DataStreamQueryAnalyzer.Properties.Resources.Button_Turn_Off_icon16;
myToolStripMenuItemExit.Name = "myToolStripMenuItemExit";
myToolStripMenuItemExit.Size = new System.Drawing.Size(139, 38);
myToolStripMenuItemExit.Text = "Exit";
myToolStripMenuItemExit.Click += myToolStripMenuItemExit_Click;
//
// testGridToolStripMenuItem
//
this.testGridToolStripMenuItem.Name = "testGridToolStripMenuItem";
this.testGridToolStripMenuItem.Size = new System.Drawing.Size(123, 22);
this.testGridToolStripMenuItem.Text = "Test Grid";
this.testGridToolStripMenuItem.Click += new System.EventHandler(this.testGridToolStripMenuItem_Click);
testGridToolStripMenuItem.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
testGridToolStripMenuItem.ForeColor = System.Drawing.Color.White;
testGridToolStripMenuItem.Name = "testGridToolStripMenuItem";
testGridToolStripMenuItem.Size = new System.Drawing.Size(139, 38);
testGridToolStripMenuItem.Text = "Test Grid";
testGridToolStripMenuItem.Click += testGridToolStripMenuItem_Click;
//
// myToolStripMenuItemQuery
//
this.myToolStripMenuItemQuery.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.myToolStripMenuItemExecute,
this.myToolStripMenuItemExecSel,
this.myToolStripMenuItemFreeze,
this.myToolStripMenuItemStep});
this.myToolStripMenuItemQuery.Name = "myToolStripMenuItemQuery";
this.myToolStripMenuItemQuery.Size = new System.Drawing.Size(51, 20);
this.myToolStripMenuItemQuery.Text = "&Query";
myToolStripMenuItemQuery.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { myToolStripMenuItemExecute, myToolStripMenuItemExecSel, myToolStripMenuItemFreeze, myToolStripMenuItemStep });
myToolStripMenuItemQuery.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemQuery.Name = "myToolStripMenuItemQuery";
myToolStripMenuItemQuery.Size = new System.Drawing.Size(51, 20);
myToolStripMenuItemQuery.Text = "&Query";
//
// myToolStripMenuItemExecute
//
this.myToolStripMenuItemExecute.Image = global::DataStreamQueryAnalyzer.Properties.Resources.Button_Play_icon16;
this.myToolStripMenuItemExecute.Name = "myToolStripMenuItemExecute";
this.myToolStripMenuItemExecute.ShortcutKeys = System.Windows.Forms.Keys.F11;
this.myToolStripMenuItemExecute.Size = new System.Drawing.Size(190, 22);
this.myToolStripMenuItemExecute.Text = "Execute";
this.myToolStripMenuItemExecute.Click += new System.EventHandler(this.myMenuItemExecuteQueryClick);
myToolStripMenuItemExecute.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myToolStripMenuItemExecute.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemExecute.Image = DataStreamQueryAnalyzer.Properties.Resources.Button_Play_icon16;
myToolStripMenuItemExecute.Name = "myToolStripMenuItemExecute";
myToolStripMenuItemExecute.ShortcutKeys = System.Windows.Forms.Keys.F11;
myToolStripMenuItemExecute.Size = new System.Drawing.Size(207, 38);
myToolStripMenuItemExecute.Text = "Execute";
myToolStripMenuItemExecute.Click += myMenuItemExecuteQueryClick;
//
// myToolStripMenuItemExecSel
//
this.myToolStripMenuItemExecSel.Image = global::DataStreamQueryAnalyzer.Properties.Resources.Button_Blank_Blue_icon16;
this.myToolStripMenuItemExecSel.Name = "myToolStripMenuItemExecSel";
this.myToolStripMenuItemExecSel.ShortcutKeys = System.Windows.Forms.Keys.F12;
this.myToolStripMenuItemExecSel.Size = new System.Drawing.Size(190, 22);
this.myToolStripMenuItemExecSel.Text = "Execute Selection";
this.myToolStripMenuItemExecSel.Click += new System.EventHandler(this.myToolStripMenuItemExecSel_Click);
myToolStripMenuItemExecSel.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myToolStripMenuItemExecSel.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemExecSel.Image = DataStreamQueryAnalyzer.Properties.Resources.Button_Blank_Blue_icon16;
myToolStripMenuItemExecSel.Name = "myToolStripMenuItemExecSel";
myToolStripMenuItemExecSel.ShortcutKeys = System.Windows.Forms.Keys.F12;
myToolStripMenuItemExecSel.Size = new System.Drawing.Size(207, 38);
myToolStripMenuItemExecSel.Text = "Execute Selection";
myToolStripMenuItemExecSel.Click += myToolStripMenuItemExecSel_Click;
//
// myToolStripMenuItemFreeze
//
this.myToolStripMenuItemFreeze.Image = global::DataStreamQueryAnalyzer.Properties.Resources.Button_Pause_icon16;
this.myToolStripMenuItemFreeze.Name = "myToolStripMenuItemFreeze";
this.myToolStripMenuItemFreeze.Size = new System.Drawing.Size(190, 22);
this.myToolStripMenuItemFreeze.Text = "Freeze";
this.myToolStripMenuItemFreeze.Click += new System.EventHandler(this.myToolStripMenuItemFreeze_Click);
myToolStripMenuItemFreeze.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myToolStripMenuItemFreeze.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemFreeze.Image = DataStreamQueryAnalyzer.Properties.Resources.Button_Pause_icon16;
myToolStripMenuItemFreeze.Name = "myToolStripMenuItemFreeze";
myToolStripMenuItemFreeze.Size = new System.Drawing.Size(207, 38);
myToolStripMenuItemFreeze.Text = "Freeze";
myToolStripMenuItemFreeze.Click += myToolStripMenuItemFreeze_Click;
//
// myToolStripMenuItemStep
//
this.myToolStripMenuItemStep.Image = global::DataStreamQueryAnalyzer.Properties.Resources.Button_Forward_icon16;
this.myToolStripMenuItemStep.Name = "myToolStripMenuItemStep";
this.myToolStripMenuItemStep.Size = new System.Drawing.Size(190, 22);
this.myToolStripMenuItemStep.Text = "Step";
this.myToolStripMenuItemStep.Click += new System.EventHandler(this.myToolStripMenuItemStep_Click);
myToolStripMenuItemStep.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myToolStripMenuItemStep.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemStep.Image = DataStreamQueryAnalyzer.Properties.Resources.Button_Forward_icon16;
myToolStripMenuItemStep.Name = "myToolStripMenuItemStep";
myToolStripMenuItemStep.Size = new System.Drawing.Size(207, 38);
myToolStripMenuItemStep.Text = "Step";
myToolStripMenuItemStep.Click += myToolStripMenuItemStep_Click;
//
// myToolStripMenuItemTools
//
this.myToolStripMenuItemTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.myToolStripMenuItemLoadAss,
this.myToolStripMenuItemTest,
this.myToolStripMenuItemToolsSep,
this.myToolStripMenuItemClearConsole});
this.myToolStripMenuItemTools.Name = "myToolStripMenuItemTools";
this.myToolStripMenuItemTools.Size = new System.Drawing.Size(48, 20);
this.myToolStripMenuItemTools.Text = "&Tools";
myToolStripMenuItemTools.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { myToolStripMenuItemLoadAss, myToolStripMenuItemTest, myToolStripMenuItemToolsSep, myToolStripMenuItemClearConsole });
myToolStripMenuItemTools.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemTools.Name = "myToolStripMenuItemTools";
myToolStripMenuItemTools.Size = new System.Drawing.Size(46, 20);
myToolStripMenuItemTools.Text = "&Tools";
//
// myToolStripMenuItemLoadAss
//
this.myToolStripMenuItemLoadAss.Image = global::DataStreamQueryAnalyzer.Properties.Resources.Button_Upload_icon16;
this.myToolStripMenuItemLoadAss.Name = "myToolStripMenuItemLoadAss";
this.myToolStripMenuItemLoadAss.Size = new System.Drawing.Size(154, 22);
this.myToolStripMenuItemLoadAss.Text = "Load Assembly";
this.myToolStripMenuItemLoadAss.Click += new System.EventHandler(this.myToolStripMenuItemLoadAss_Click);
myToolStripMenuItemLoadAss.Image = DataStreamQueryAnalyzer.Properties.Resources.Button_Upload_icon16;
myToolStripMenuItemLoadAss.Name = "myToolStripMenuItemLoadAss";
myToolStripMenuItemLoadAss.Size = new System.Drawing.Size(170, 38);
myToolStripMenuItemLoadAss.Text = "Load Assembly";
myToolStripMenuItemLoadAss.Click += myToolStripMenuItemLoadAss_Click;
//
// myToolStripMenuItemTest
//
this.myToolStripMenuItemTest.Image = global::DataStreamQueryAnalyzer.Properties.Resources.Button_Refresh_icon16;
this.myToolStripMenuItemTest.Name = "myToolStripMenuItemTest";
this.myToolStripMenuItemTest.ShortcutKeys = System.Windows.Forms.Keys.F4;
this.myToolStripMenuItemTest.Size = new System.Drawing.Size(154, 22);
this.myToolStripMenuItemTest.Text = "Test Resub";
this.myToolStripMenuItemTest.Click += new System.EventHandler(this.myToolStripMenuItemTest_Click);
myToolStripMenuItemTest.Image = DataStreamQueryAnalyzer.Properties.Resources.Button_Refresh_icon16;
myToolStripMenuItemTest.Name = "myToolStripMenuItemTest";
myToolStripMenuItemTest.ShortcutKeys = System.Windows.Forms.Keys.F4;
myToolStripMenuItemTest.Size = new System.Drawing.Size(170, 38);
myToolStripMenuItemTest.Text = "Test Resub";
myToolStripMenuItemTest.Click += myToolStripMenuItemTest_Click;
//
// myToolStripMenuItemToolsSep
//
this.myToolStripMenuItemToolsSep.Name = "myToolStripMenuItemToolsSep";
this.myToolStripMenuItemToolsSep.Size = new System.Drawing.Size(151, 6);
myToolStripMenuItemToolsSep.Name = "myToolStripMenuItemToolsSep";
myToolStripMenuItemToolsSep.Size = new System.Drawing.Size(167, 6);
//
// myToolStripMenuItemClearConsole
//
this.myToolStripMenuItemClearConsole.Name = "myToolStripMenuItemClearConsole";
this.myToolStripMenuItemClearConsole.Size = new System.Drawing.Size(154, 22);
this.myToolStripMenuItemClearConsole.Text = "Clear Console";
this.myToolStripMenuItemClearConsole.Click += new System.EventHandler(this.myToolStripMenuItemClearConsole_Click);
myToolStripMenuItemClearConsole.BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
myToolStripMenuItemClearConsole.ForeColor = System.Drawing.Color.White;
myToolStripMenuItemClearConsole.Name = "myToolStripMenuItemClearConsole";
myToolStripMenuItemClearConsole.Size = new System.Drawing.Size(170, 38);
myToolStripMenuItemClearConsole.Text = "Clear Console";
myToolStripMenuItemClearConsole.Click += myToolStripMenuItemClearConsole_Click;
//
// myToolStripMenuItemSite
//
this.myToolStripMenuItemSite.Name = "myToolStripMenuItemSite";
this.myToolStripMenuItemSite.Size = new System.Drawing.Size(38, 20);
this.myToolStripMenuItemSite.Text = "&Site";
myToolStripMenuItemSite.Name = "myToolStripMenuItemSite";
myToolStripMenuItemSite.Size = new System.Drawing.Size(38, 20);
myToolStripMenuItemSite.Text = "&Site";
//
// libraryToolStripMenuItem
//
this.libraryToolStripMenuItem.Name = "libraryToolStripMenuItem";
this.libraryToolStripMenuItem.Size = new System.Drawing.Size(55, 20);
this.libraryToolStripMenuItem.Text = "Library";
this.libraryToolStripMenuItem.Click += new System.EventHandler(this.libraryToolStripMenuItem_Click);
libraryToolStripMenuItem.Name = "libraryToolStripMenuItem";
libraryToolStripMenuItem.Size = new System.Drawing.Size(55, 20);
libraryToolStripMenuItem.Text = "Library";
libraryToolStripMenuItem.Click += libraryToolStripMenuItem_Click;
//
// MainForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(7, 13);
this.BackColor = System.Drawing.Color.Gainsboro;
this.ClientSize = new System.Drawing.Size(904, 589);
this.Controls.Add(this.mySplitter);
this.Controls.Add(this.myTabControl);
this.Controls.Add(this.myQueryTextBox);
this.Controls.Add(this.myMenuStrip);
this.Controls.Add(this.myStatusStrip);
this.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.ForeColor = System.Drawing.Color.Black;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MainMenuStrip = this.myMenuStrip;
this.Name = "MainForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "DataStream Query Analyzer";
this.Closed += new System.EventHandler(this.MainForm_Closed);
this.myTabControl.ResumeLayout(false);
this.myViewTabPage.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.myDataGrid)).EndInit();
this.myCSharpTabPage.ResumeLayout(false);
this.myErrorTabPage.ResumeLayout(false);
this.myTableListTabPage.ResumeLayout(false);
this.myTableListTopPanel.ResumeLayout(false);
this.myTableListTopPanel.PerformLayout();
this.myPrimitivesPage.ResumeLayout(false);
this.myConsoleTabPage.ResumeLayout(false);
this.myStatusStrip.ResumeLayout(false);
this.myStatusStrip.PerformLayout();
this.myMenuStrip.ResumeLayout(false);
this.myMenuStrip.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
AutoScaleBaseSize = new System.Drawing.Size(7, 13);
BackColor = System.Drawing.Color.FromArgb(36, 36, 49);
ClientSize = new System.Drawing.Size(904, 589);
Controls.Add(mySplitter);
Controls.Add(myTabControl);
Controls.Add(myQueryTextBox);
Controls.Add(myMenuStrip);
Controls.Add(myStatusStrip);
Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point);
ForeColor = System.Drawing.Color.White;
Icon = (System.Drawing.Icon)resources.GetObject("$this.Icon");
MainMenuStrip = myMenuStrip;
Name = "MainForm";
StartPosition = System.Windows.Forms.FormStartPosition.Manual;
Text = "BTS-cloud.io";
Closed += MainForm_Closed;
Load += MainForm_Load;
myTabControl.ResumeLayout(false);
myViewTabPage.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)myDataGrid).EndInit();
myCSharpTabPage.ResumeLayout(false);
myErrorTabPage.ResumeLayout(false);
myTableListTabPage.ResumeLayout(false);
myTableListTopPanel.ResumeLayout(false);
myTableListTopPanel.PerformLayout();
myPrimitivesPage.ResumeLayout(false);
myConsoleTabPage.ResumeLayout(false);
myStatusStrip.ResumeLayout(false);
myStatusStrip.PerformLayout();
myMenuStrip.ResumeLayout(false);
myMenuStrip.PerformLayout();
ResumeLayout(false);
PerformLayout();
}
#endregion
@@ -561,5 +610,6 @@
private System.Windows.Forms.Panel myTableListTopPanel;
private System.Windows.Forms.ToolStripMenuItem testGridToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem libraryToolStripMenuItem;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
}
}
@@ -21,55 +21,65 @@ using Spark.DataStream;
using Bts.DataStreamExpressions;
// using BCG.Evaluator.DataStreamExpression;
// using BCG.Utilities.Win32;
using System.Threading.Tasks;
namespace BCG
{
public partial class MainForm : System.Windows.Forms.Form
{
namespace BCG {
public partial class MainForm : System.Windows.Forms.Form {
// static async Task _run() {
// var login = "bts";
// var passwd = String.Empty;
// Console.WriteLine("Starting DSQA... ");
// // Log.notnull(login);
// // Log.notnull(passwd);
// var service_ctx = bts.api.core.ServiceContext.create();
// await service_ctx.login(login, passwd);
// }
private bool myChangeStyle = false;
private PubSubRoute[] myRoutes = PubSub3Config.instance.getSubRouting();
private PersistWindowState myWindowState;
private string myLastFileName;
private ViewStream myCurrentStream;
private List<ToolStripMenuItem> mySiteItems = new List<ToolStripMenuItem> ();
private List<ToolStripMenuItem> mySiteItems = new List<ToolStripMenuItem>();
// private string mySite = SitesCore.getMySiteName ();
private string mySite = "TODO";
private string myLastClassName = "MyView";
private ViewStream myAllTagsStream;
private PubSubConfigureForm myPubSubConForm = new PubSubConfigureForm ();
private ViewStream myAllTagsStream;
private PubSubConfigureForm myPubSubConForm = new PubSubConfigureForm();
private string myKQ;
private TextWriter myConsoleOutput;
public MainForm()
{
public MainForm() {
//Task.Run(async () => await _run());
InitializeComponent();
// myKQ = ConfigurationRequester.getApplicationQualifier();
myKQ = "TODO";
mySetText();
myWindowState = new PersistWindowState ();
myWindowState = new PersistWindowState();
myWindowState.parent = this;
myWindowState.saveState = false;
this.Load += new EventHandler (myLoad);
this.Closing += new CancelEventHandler (myClosing);
this.Load += new EventHandler(myLoad);
this.Closing += new CancelEventHandler(myClosing);
myQueryTextBox.TextChanged += (o, e) => {
myQueryTextBox.ForeColor = Color.White;
};
}
public string query_text
{
public string query_text {
get { return myQueryTextBox.Text; }
set { myQueryTextBox.Text = value; }
}
private ViewStream myGetAllTagsStream ()
{
private ViewStream myGetAllTagsStream() {
// TODO: Port PublishedTagsStream from edge (then we can uncomment impl below)
// return new FilterStream(new PublishedTagsStream(), String.Format("tag~='^{0}'", PubStreamPrefixer.prefix("")));
return new LiteralStream("tag/String", "DS_Comedians;DS_Baldies");
return new FilterStream(new PubSubServerStateStream(), "tag~='DS_'");
//return new LiteralStream("tag/String", "DS_Comedians;DS_Baldies");
}
private void mySetText ()
{
this.Text = "Data Stream Query Analyzer | Site: " + mySite + (string.IsNullOrEmpty (myKQ) ? string.Empty : " | Key Qualifier: " + myKQ);
private void mySetText() {
this.Text = "Data Stream Query Analyzer | Site: " + mySite + (string.IsNullOrEmpty(myKQ) ? string.Empty : " | Key Qualifier: " + myKQ);
myToolStripStatusLabelTime.Text = "Ready";
myToolStripStatusLabelRows.Text = string.Empty;
}
@@ -78,41 +88,36 @@ namespace BCG
/// Gets the data in the form of a multilevel IDictionary
/// </summary>
/// <returns></returns>
private IDictionary myGetLibraryData ()
{
private IDictionary myGetLibraryData() {
SortedList retVal = new SortedList();
string[] primitiveNames = PrimitiveManager.instance.getPrimitiveNames ();
foreach (string pName in primitiveNames)
{
string aName = PrimitiveManager.instance.getAssemblyName (pName);
ICollection cNames = PrimitiveManager.instance.getConstructorSigns (pName);
if (!retVal.Contains (aName))
retVal.Add (aName, new SortedList ());
(retVal[aName] as IDictionary)[pName] = new ArrayList (cNames);
string[] primitiveNames = PrimitiveManager.instance.getPrimitiveNames();
foreach (string pName in primitiveNames) {
string aName = PrimitiveManager.instance.getAssemblyName(pName);
ICollection cNames = PrimitiveManager.instance.getConstructorSigns(pName);
if (!retVal.Contains(aName))
retVal.Add(aName, new SortedList());
(retVal[aName] as IDictionary)[pName] = new ArrayList(cNames);
}
foreach (DictionaryEntry outerDe in retVal)
foreach (DictionaryEntry innerDe in (outerDe.Value as IDictionary))
(innerDe.Value as ArrayList).Sort ();
(innerDe.Value as ArrayList).Sort();
return retVal;
}
private void myLoadAssemblies ()
{
myTreeView.Nodes.Clear ();
IDictionary libraryData = myGetLibraryData ();
foreach (DictionaryEntry de in libraryData)
{
TreeNode assemblyNode = new TreeNode (de.Key as String);
foreach (DictionaryEntry innerDe in (de.Value as IDictionary))
{
TreeNode primitiveNode = new TreeNode (innerDe.Key as string);
private void myLoadAssemblies() {
myTreeView.Nodes.Clear();
IDictionary libraryData = myGetLibraryData();
foreach (DictionaryEntry de in libraryData) {
TreeNode assemblyNode = new TreeNode(de.Key as String);
foreach (DictionaryEntry innerDe in (de.Value as IDictionary)) {
TreeNode primitiveNode = new TreeNode(innerDe.Key as string);
foreach (string con in (innerDe.Value as ICollection))
primitiveNode.Nodes.Add (con);
assemblyNode.Nodes.Add (primitiveNode);
primitiveNode.Nodes.Add(con);
assemblyNode.Nodes.Add(primitiveNode);
}
myTreeView.Nodes.Add (assemblyNode);
myTreeView.Nodes.Add(assemblyNode);
}
/*
myPrimitivesTextBox.Clear ();
@@ -126,27 +131,23 @@ namespace BCG
}*/
}
private void myHandleTableListChange (object o)
{
private void myHandleTableListChange(object o) {
IBlueRowCollection rows = (o as DataPacket).newRows;
myUpdateTableList();
}
#region Persistence Keys
public int textBoxHeight
{
public int textBoxHeight {
get { return myQueryTextBox.Height; }
set { myQueryTextBox.Height = value; }
}
#endregion
private void myTryExpression (string expStr)
{
myFreezeView (false); // force unfreeze the view
private void myTryExpression(string expStr) {
myFreezeView(false); // force unfreeze the view
DataStreamExpression oldExp = myExp;
try
{
try {
var exp = DataStreamExpressionsInterpreter.Evaluate(expStr);
if (exp == null)
@@ -156,7 +157,7 @@ namespace BCG
myTabControl.SelectedIndex = 0;
myErrorTextBox.Text = "";
// myDataGrid.CaptionText = "";
if (myCurrentStream != null)
myCurrentStream.onChange -= new BCG.DataStream.ChangeDelegate(myCallback);
myCurrentStream = null;
@@ -164,7 +165,7 @@ namespace BCG
myExp = exp;
myCrono = new Crono();
myCrono.start();
(myCurrentStream = myExp.getView(new Dictionary<string, StatementExpression>(0))).onChange += new DataStream.ChangeDelegate(myCallback);
myChangeStyle = true;
//new SimpleBindableStream(myExp.getView(new Hashtable())).onChange += new DataStream.ChangeDelegate(myCallback);
@@ -173,66 +174,55 @@ namespace BCG
oldExp.getView(new Hashtable()).onChange -= new DataStream.ChangeDelegate(myCallback);
*/
//myQueryTextBox.Text = expStr;
}
catch (Exception exc)
{
} catch (Exception exc) {
Log.Ui.warn(exc.ToString());
myDataGrid.DataSource = null;
myTabControl.SelectedIndex = 2;
myExp = oldExp;
myExp = oldExp;
myErrorTextBox.Text = exc.Message + "\n";
if(exc.InnerException != null)
if (exc.InnerException != null)
myErrorTextBox.Text += "Inner Exception: " + exc.InnerException.Message + "\n";
myErrorTextBox.Text += "\n" + exc.StackTrace;
myCSharpText.Text = "";
}
}
private string myExtractFromClass (TextReader r)
{
private string myExtractFromClass(TextReader r) {
string line = r.ReadLine();
while (line != null && line.IndexOf("*Expression*") == -1)
while (line != null && line.IndexOf("*Expression*") == -1)
line = r.ReadLine();
if (line == null)
throw new Exception ("Unexpected EOF");
throw new Exception("Unexpected EOF");
r.ReadLine();
string result = "";
line = r.ReadLine();
while (line != null && line.IndexOf("----------------------------------------------------------------------") == -1)
{
while (line != null && line.IndexOf("----------------------------------------------------------------------") == -1) {
if (line != "")
result += line.Substring(" ".Length) + "\n";
line = r.ReadLine();
}
if (line == null)
throw new Exception ("Unexpected EOF");
throw new Exception("Unexpected EOF");
return result;
}
public void loadFile (string fileName)
{
try
{
public void loadFile(string fileName) {
try {
TextReader r = new StreamReader(fileName);
try
{
try {
myQueryTextBox.Text = myExtractFromClass(r);
}
finally
{
} finally {
r.Close();
}
myLastFileName = fileName;
this.Text = fileName;
}
catch (Exception exc)
{
} catch (Exception exc) {
Log.Ui.warn(exc.ToString());
myDataGrid.DataSource = null;
@@ -243,30 +233,28 @@ namespace BCG
}
private void myPrintCode(IBlueTableSchema schema, ICollection vars, string code)
{
private void myPrintCode(IBlueTableSchema schema, ICollection vars, string code) {
myCSharpText.Text = "using System;\n\nnamespace BCG\n{";
myCSharpText.Text +="\n/*";
myCSharpText.Text +="\n ----------------------------------------------------------------------";
myCSharpText.Text +="\n *Expression*";
myCSharpText.Text +="\n ----------------------------------------------------------------------";
myCSharpText.Text += "\n/*";
myCSharpText.Text += "\n ----------------------------------------------------------------------";
myCSharpText.Text += "\n *Expression*";
myCSharpText.Text += "\n ----------------------------------------------------------------------";
foreach (string line in myQueryTextBox.Text.Split('\n'))
myCSharpText.Text +="\n " + line;
myCSharpText.Text +="\n\n ----------------------------------------------------------------------";
myCSharpText.Text +="\n *Schema*";
myCSharpText.Text +="\n ----------------------------------------------------------------------";
foreach(ColumnInfo ci in schema.columnInfo)
myCSharpText.Text +="\n " + ci.colName + new string(' ', Math.Max(32 - ci.colName.Length,1) ) + ci.colType.ToString();
myCSharpText.Text +="\n*/\n";
myCSharpText.Text += "\n " + line;
myCSharpText.Text += "\n\n ----------------------------------------------------------------------";
myCSharpText.Text += "\n *Schema*";
myCSharpText.Text += "\n ----------------------------------------------------------------------";
foreach (ColumnInfo ci in schema.columnInfo)
myCSharpText.Text += "\n " + ci.colName + new string(' ', Math.Max(32 - ci.colName.Length, 1)) + ci.colType.ToString();
myCSharpText.Text += "\n*/\n";
string lastVar = null;
string variableDeclarations = "";
foreach (string var in vars)
{
variableDeclarations+= " ViewStream " + var + ";\n";
foreach (string var in vars) {
variableDeclarations += " ViewStream " + var + ";\n";
lastVar = var;
}
@@ -278,18 +266,18 @@ namespace BCG
else
myLastClassName = "MyView";
myCSharpText.Text +="\n\n public class " + myLastClassName + " : ViewStream \n {\n";
myCSharpText.Text += "\n\n public class " + myLastClassName + " : ViewStream \n {\n";
myCSharpText.Text += " public " + myLastClassName + "() : this(null) {}\n";
myCSharpText.Text += " public " + myLastClassName + "(ViewStreamDatabase db)\n {\n";
myCSharpText.Text += variableDeclarations;
if (lastVar != null)
myCSharpText.Text += "\n";
myCSharpText.Text += code + "\n";
if (lastVar != null)
myCSharpText.Text += " mySetRealSource(" + lastVar + ");\n";
myCSharpText.Text += " mySetRealSource(" + lastVar + ");\n";
myCSharpText.Text += " }\n";
myCSharpText.Text += " }\n";
myCSharpText.Text += "}";
@@ -310,27 +298,31 @@ namespace BCG
return Math.Max(header_width, min_width);
}
}
private void myCallback(object o)
{
private HighPerformanceTimer _timer = new HighPerformanceTimer();
// this is the stream callback
private void myCallback(object o) {
_timer.start();
DataPacket dp = o as DataPacket;
myCrono.stop();
Log.Ui.diag($"Received callback for {dp.schema.tableName}");
if (o == null)
{
System.Windows.Forms.MessageBox.Show (this, "Received a Null Data packet",
if (o == null) {
System.Windows.Forms.MessageBox.Show(this, "Received a Null Data packet",
"Invalid Data", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Log.Ui.diag(dp.toIncrementalIDString());
myToolStripStatusLabelTime.Text = "Last update: " + DateTime.Now.ToString ("hh:mm:ss:fff tt");
myToolStripStatusLabelTime.BackColor = Color.Black;
myToolStripStatusLabelRows.BackColor = Color.Black;
myToolStripStatusLabelTime.ForeColor = Color.White;
myToolStripStatusLabelRows.ForeColor = Color.White;
myToolStripStatusLabelTime.Text = "Last update: " + DateTime.Now.ToString("hh:mm:ss:fff tt");
myToolStripStatusLabelRows.Text = "New = " + dp.newRows.Count + " Added = " + dp.addedRows.Count + " Deleted = " + dp.deletedRows.Count;
Log.Ui.diag(Text);
int hscrollval = myChangeStyle ? 0 : myDataGrid.HorizScrollBarValue;
myDataGrid.DataSource = new SimpleBindableCollection (dp.newRows.schema, dp.newRows);
if (myChangeStyle)
{
myDataGrid.DataSource = new SimpleBindableCollection(dp.newRows.schema, dp.newRows);
var force = false;
if (myChangeStyle && force) {
myChangeStyle = false;
myDataGrid.Columns.Clear();
myDataGrid.Columns.AddRange(Array.ConvertAll(dp.schema.columnInfo, _column_factory));
@@ -338,28 +330,30 @@ namespace BCG
myCrono.start();
// myDataGrid.CaptionText = myCrono.time.TotalMilliseconds + " ms ";
// myDataGrid.CaptionText += dp.newRows.Count.ToString () + " records";
myDataGrid.HorizScrollBarValue = hscrollval;
var varNames = new List<string>(0);
string code = myExp.print(9,varNames);
myPrintCode(dp.schema ,varNames, code);
string code = myExp.print(9, varNames);
myPrintCode(dp.schema, varNames, code);
myConsoleRichTextBox.Clear();
// this was was very very slow
//myConsoleRichTextBox.Text = BlueDataUtility.get_printed_rows(dp.newRows, (col) => 30);
_timer.stop();
var msecs = _timer.lastIntervalTime;
bts.Log.Gen.info($"DSQA MainForm.myCallback table: {dp.schema.tableName} rows: {dp.newRows.Count} time: {msecs}");
}
private Crono myCrono;
private Crono myCrono;
private DataStreamExpression myExp;
private void myTimer_Tick(object sender, System.EventArgs e)
{
try
{
ViewStreamDatabase.instance.doWork ();
private void myTimer_Tick(object sender, System.EventArgs e) {
try {
ViewStreamDatabase.instance.doWork();
MasterWorker.getInstance(false).doWork();
}
catch (Exception exc)
{
} catch (Exception exc) {
Log.Ui.warn(exc.ToString());
myDataGrid.DataSource = null;
@@ -370,27 +364,22 @@ namespace BCG
}
}
class StringWrapper
{
public StringWrapper(string s)
{
class StringWrapper {
public StringWrapper(string s) {
myTableName = s;
}
public string tableName
{
get{return myTableName;}
public string tableName {
get { return myTableName; }
}
private string myTableName;
}
private void MainForm_Closed(object sender, System.EventArgs e)
{
private void MainForm_Closed(object sender, System.EventArgs e) {
if (myExp != null)
myExp.getView(new Dictionary<string, StatementExpression>(0)).onChange -= new DataStream.ChangeDelegate(myCallback);
}
private void myMenuItemExecuteQueryClick(object sender, System.EventArgs e)
{
private void myMenuItemExecuteQueryClick(object sender, System.EventArgs e) {
myQueryTextBox.SelectionStart = myQueryTextBox.Text.Length;
myQueryTextBox.SelectionLength = myQueryTextBox.Text.Length;
myQueryTextBox.SelectionColor = Color.Black;
@@ -398,49 +387,44 @@ namespace BCG
myTryExpression(myQueryTextBox.Text);
}
private void myToolStripMenuItemExecSel_Click (object sender, EventArgs e)
{
int selstart = myQueryTextBox.SelectionStart;
int sellength = myQueryTextBox.SelectionLength;
myQueryTextBox.SelectionStart = 0;
myQueryTextBox.SelectionLength = myQueryTextBox.Text.Length;
myQueryTextBox.SelectionColor = Color.Black;
myQueryTextBox.SelectionStart = selstart;
myQueryTextBox.SelectionLength = sellength;
myQueryTextBox.SelectionColor = Color.Crimson;
myTryExpression (myQueryTextBox.SelectedText);
myQueryTextBox.SelectionStart = myQueryTextBox.Text.Length;
myQueryTextBox.SelectionLength = 0;
myQueryTextBox.SelectionColor = Color.Black;
private void myToolStripMenuItemExecSel_Click(object sender, EventArgs e) {
// int selstart = myQueryTextBox.SelectionStart;
// int sellength = myQueryTextBox.SelectionLength;
// myQueryTextBox.SelectionStart = 0;
// myQueryTextBox.SelectionLength = myQueryTextBox.Text.Length;
// myQueryTextBox.SelectionColor = Color.White;
// myQueryTextBox.SelectionStart = selstart;
// myQueryTextBox.SelectionLength = sellength;
// myQueryTextBox.SelectionColor = Color.Crimson;
// myTryExpression(myQueryTextBox.SelectedText);
// myQueryTextBox.SelectionStart = myQueryTextBox.Text.Length;
// myQueryTextBox.SelectionLength = 0;
// myQueryTextBox.SelectionColor = Color.White;
}
private void myMenuItemOpenClick(object sender, System.EventArgs e)
{
private void myMenuItemOpenClick(object sender, System.EventArgs e) {
OpenFileDialog od = new OpenFileDialog();
od.Filter = "C# class (*.cs)|*.cs";
if(od.ShowDialog() == DialogResult.OK)
if (od.ShowDialog() == DialogResult.OK)
loadFile(od.FileName);
}
private void mySave(string fileName)
{
private void mySave(string fileName) {
using (TextWriter w = new StreamWriter(fileName))
w.Write(myCSharpText.Text);
myLastFileName = fileName;
this.Text = fileName;
}
private void myMenuItemSaveClick(object sender, System.EventArgs e)
{
private void myMenuItemSaveClick(object sender, System.EventArgs e) {
if (myLastFileName == null)
myMenuItemSaveAsClick(sender,e);
myMenuItemSaveAsClick(sender, e);
else
mySave(myLastFileName);
}
private void myMenuItemSaveAsClick(object sender, System.EventArgs e)
{
private void myMenuItemSaveAsClick(object sender, System.EventArgs e) {
SaveFileDialog sd = new SaveFileDialog();
if (myLastFileName != null)
sd.FileName = myLastFileName;
@@ -448,62 +432,53 @@ namespace BCG
sd.FileName = myLastClassName + ".cs";
if (sd.ShowDialog() == DialogResult.OK)
mySave (sd.FileName);
mySave(sd.FileName);
}
private void myTableListBox_DoubleClick(object sender, System.EventArgs e)
{
if (myTableListBox.SelectedItem != null)
{
string tableName = myTableListBox.SelectedItem.ToString ();
private void myTableListBox_DoubleClick(object sender, System.EventArgs e) {
if (myTableListBox.SelectedItem != null) {
string tableName = myTableListBox.SelectedItem.ToString();
myQueryTextBox.Text = myQueryTextBox.Text == "" ? tableName : myQueryTextBox.Text + "\n" + tableName;
myTryExpression (myQueryTextBox.Text);
myTryExpression(myQueryTextBox.Text);
}
}
private void myDataGrid_MouseEnter(object sender, System.EventArgs e)
{
private void myDataGrid_MouseEnter(object sender, System.EventArgs e) {
//myDataGrid.TableStyles[0].GridLineColor = Color.LightSteelBlue;
// if (myDataGrid.TableStyles.Count > 0)
// myDataGrid.TableStyles[0].HeaderBackColor = Color.LightSteelBlue;
}
private void myDataGrid_MouseLeave(object sender, System.EventArgs e)
{
private void myDataGrid_MouseLeave(object sender, System.EventArgs e) {
//myDataGrid.TableStyles[0].GridLineColor = Color.Gainsboro;
// if (myDataGrid.TableStyles.Count > 0)
// myDataGrid.TableStyles[0].HeaderBackColor = Color.Gainsboro;
}
private void myCSharpText_MouseEnter(object sender, System.EventArgs e)
{
myCSharpText.BackColor = Color.Gainsboro;
myCSharpText.Font = new Font (myCSharpText.Font.Name, myCSharpText.Font.Size, FontStyle.Bold);
private void myCSharpText_MouseEnter(object sender, System.EventArgs e) {
//myCSharpText.BackColor = Color.Gainsboro;
myCSharpText.Font = new Font(myCSharpText.Font.Name, myCSharpText.Font.Size, FontStyle.Bold);
}
private void myCSharpText_MouseLeave(object sender, System.EventArgs e)
{
myCSharpText.BackColor = Color.White;
myCSharpText.Font = new Font (myCSharpText.Font.Name, myCSharpText.Font.Size, FontStyle.Regular);
private void myCSharpText_MouseLeave(object sender, System.EventArgs e) {
//myCSharpText.BackColor = Color.White;
myCSharpText.Font = new Font(myCSharpText.Font.Name, myCSharpText.Font.Size, FontStyle.Regular);
}
private void myTableListBox_MouseEnter(object sender, System.EventArgs e)
{
myTableListBox.BackColor = Color.Gainsboro;
myTableListBox.Font = new Font (myTableListBox.Font.Name, myTableListBox.Font.Size, FontStyle.Bold);
private void myTableListBox_MouseEnter(object sender, System.EventArgs e) {
//myTableListBox.BackColor = Color.Gainsboro;
myTableListBox.Font = new Font(myTableListBox.Font.Name, myTableListBox.Font.Size, FontStyle.Bold);
}
private void myTableListBox_MouseLeave(object sender, System.EventArgs e)
{
myTableListBox.BackColor = Color.White;
myTableListBox.Font = new Font (myTableListBox.Font.Name, myTableListBox.Font.Size, FontStyle.Regular);
private void myTableListBox_MouseLeave(object sender, System.EventArgs e) {
//myTableListBox.BackColor = Color.White;
myTableListBox.Font = new Font(myTableListBox.Font.Name, myTableListBox.Font.Size, FontStyle.Regular);
}
private void myLoad (object sender, EventArgs e)
{
myFreezeView (false);
private void myLoad(object sender, EventArgs e) {
myFreezeView(false);
myToolStripMenuItemSite.DropDownItems.Clear ();
myToolStripMenuItemSite.DropDownItems.Clear();
// foreach (var name in SitesCfg.instance.siteNames)
// {
// ToolStripMenuItem mi = new ToolStripMenuItem (name);
@@ -517,144 +492,123 @@ namespace BCG
// }
myConsoleRichTextBox.ReadOnly = true;
myConsoleOutput = new RichTextBoxStreamWriter (myConsoleRichTextBox);
Console.SetOut (myConsoleOutput);
Console.SetError (myConsoleOutput);
if(BCG.Utilities.Win32.WindowsAPI.SetStdHandle(-11, myConsoleRichTextBox.Handle) == 0) // set stdout
myConsoleOutput = new RichTextBoxStreamWriter(myConsoleRichTextBox);
Console.SetOut(myConsoleOutput);
Console.SetError(myConsoleOutput);
if (BCG.Utilities.Win32.WindowsAPI.SetStdHandle(-11, myConsoleRichTextBox.Handle) == 0) // set stdout
{
var ex = new Win32Exception (); // same as new Win32Exception(Marshal.GetLastWin32Error())
Console.WriteLine (ex.Message);
}
else
{
Console.WriteLine ("Set stdout worked.");
var ex = new Win32Exception(); // same as new Win32Exception(Marshal.GetLastWin32Error())
Console.WriteLine(ex.Message);
} else {
Console.WriteLine("Set stdout worked.");
}
if(BCG.Utilities.Win32.WindowsAPI.SetStdHandle(-12, myConsoleRichTextBox.Handle) == 0) // set stderr
if (BCG.Utilities.Win32.WindowsAPI.SetStdHandle(-12, myConsoleRichTextBox.Handle) == 0) // set stderr
{
var ex = new Win32Exception (); // same as new Win32Exception(Marshal.GetLastWin32Error())
Console.WriteLine (ex.Message);
var ex = new Win32Exception(); // same as new Win32Exception(Marshal.GetLastWin32Error())
Console.WriteLine(ex.Message);
} else {
Console.WriteLine("Set stderr worked.");
}
else
{
Console.WriteLine ("Set stderr worked.");
}
Console.WriteLine ("Redirecting console ouput to this window...");
Console.WriteLine("Redirecting console ouput to this window...");
myLoadAssemblies ();
myLoadAssemblies();
ViewStreamDatabase.instance = new ViewStreamDatabase ();
myAllTagsStream = myGetAllTagsStream ();
myAllTagsStream.onChange += new BCG.DataStream.ChangeDelegate (myHandleTableListChange);
ViewStreamDatabase.instance = new ViewStreamDatabase();
myAllTagsStream = myGetAllTagsStream();
myAllTagsStream.onChange += new BCG.DataStream.ChangeDelegate(myHandleTableListChange);
myTabControl.SelectedIndex = 3;
myTreeView.AfterSelect += new TreeViewEventHandler (myHandleTreeNodeSelect);
myTreeView.AfterSelect += new TreeViewEventHandler(myHandleTreeNodeSelect);
//do this lazily so we don't have to have bps, etc up to run dsqa
//_library = new LibraryForm(this);
}
private void myMenuItemSiteClick (object sender, System.EventArgs e)
{
ToolStripMenuItem mi = (ToolStripMenuItem) sender;
private void myMenuItemSiteClick(object sender, System.EventArgs e) {
ToolStripMenuItem mi = (ToolStripMenuItem)sender;
if (mi.Text != mySite)
{
if (mi.Text != mySite) {
mySite = mi.Text;
foreach (var m in mySiteItems)
m.Checked = false;
mi.Checked = true;
myAllTagsStream.onChange -= new BCG.DataStream.ChangeDelegate (myHandleTableListChange);
myTableListBox.Items.Clear ();
myAllTagsStream.onChange -= new BCG.DataStream.ChangeDelegate(myHandleTableListChange);
myTableListBox.Items.Clear();
// SitesCore.setMySiteName (mySite);
ViewStreamDatabase.instance = new ViewStreamDatabase ();
myAllTagsStream = myGetAllTagsStream ();
myAllTagsStream.onChange += new BCG.DataStream.ChangeDelegate (myHandleTableListChange);
ViewStreamDatabase.instance = new ViewStreamDatabase();
myAllTagsStream = myGetAllTagsStream();
myAllTagsStream.onChange += new BCG.DataStream.ChangeDelegate(myHandleTableListChange);
myDataGrid.DataSource = null;
myTabControl.SelectedIndex = 3;
mySetText ();
mySetText();
}
}
private void myClosing (object sender, CancelEventArgs e)
{
private void myClosing(object sender, CancelEventArgs e) {
}
private void myHandleTreeNodeSelect(object sender, TreeViewEventArgs e)
{
if (myTreeView.SelectedNode != null)
{
if (myTreeView.SelectedNode.LastNode == null)
{
private void myHandleTreeNodeSelect(object sender, TreeViewEventArgs e) {
if (myTreeView.SelectedNode != null) {
if (myTreeView.SelectedNode.LastNode == null) {
string sn = myTreeView.SelectedNode.Parent.Text + "()";
myQueryTextBox.Text = myQueryTextBox.Text == "" ? sn : myQueryTextBox.Text + "\n" + sn;
}
}
}
private void myToolStripMenuItemExit_Click (object sender, EventArgs e)
{
Close ();
private void myToolStripMenuItemExit_Click(object sender, EventArgs e) {
Close();
}
private void myToolStripMenuItemFreeze_Click (object sender, EventArgs e)
{
myFreezeView (myTimer.Enabled);
private void myToolStripMenuItemFreeze_Click(object sender, EventArgs e) {
myFreezeView(myTimer.Enabled);
}
private void myFreezeView (bool freeze)
{
private void myFreezeView(bool freeze) {
myTimer.Enabled = !freeze;
myToolStripMenuItemFreeze.Checked = freeze;
myToolStripMenuItemStep.Enabled = freeze;
}
private void myToolStripMenuItemStep_Click (object sender, EventArgs e)
{
ViewStreamDatabase.instance.doWork ();
private void myToolStripMenuItemStep_Click(object sender, EventArgs e) {
ViewStreamDatabase.instance.doWork();
}
private void myToolStripMenuItemLoadAss_Click (object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog ();
private void myToolStripMenuItemLoadAss_Click(object sender, EventArgs e) {
OpenFileDialog ofd = new OpenFileDialog();
ofd.ShowReadOnly = true;
DialogResult dr = ofd.ShowDialog (this);
if (ofd.CheckFileExists && ofd.CheckPathExists && dr == DialogResult.OK)
{
PrimitiveManager.instance.loadAssembly (ofd.FileName);
myLoadAssemblies ();
DialogResult dr = ofd.ShowDialog(this);
if (ofd.CheckFileExists && ofd.CheckPathExists && dr == DialogResult.OK) {
PrimitiveManager.instance.loadAssembly(ofd.FileName);
myLoadAssemblies();
}
}
private void myToolStripMenuItemTest_Click (object sender, EventArgs e)
{
if (myCurrentStream != null)
{
myCurrentStream.onChange -= new DataStream.ChangeDelegate (myCallback);
myCurrentStream.onChange += new DataStream.ChangeDelegate (myCallback);
private void myToolStripMenuItemTest_Click(object sender, EventArgs e) {
if (myCurrentStream != null) {
myCurrentStream.onChange -= new DataStream.ChangeDelegate(myCallback);
myCurrentStream.onChange += new DataStream.ChangeDelegate(myCallback);
}
}
private void myToolStripMenuItemClearConsole_Click (object sender, EventArgs e)
{
myConsoleRichTextBox.Clear ();
Console.WriteLine ("Redirecting console ouput to this window...");
private void myToolStripMenuItemClearConsole_Click(object sender, EventArgs e) {
myConsoleRichTextBox.Clear();
Console.WriteLine("Redirecting console ouput to this window...");
}
private void myTableFilterBox_TextChanged(object sender, EventArgs e)
{
private void myTableFilterBox_TextChanged(object sender, EventArgs e) {
myUpdateTableList();
}
private void myUpdateTableList()
{
private void myUpdateTableList() {
IBlueRowCollection rows = myAllTagsStream.rows;
if (rows == null)
return;
ICollection oldItems = myTableListBox.Items;
myTableListBox.BeginUpdate();
@@ -664,15 +618,12 @@ namespace BCG
myTableListBox.Items.Clear();
SortedList<string, bool> sl = new SortedList<string, bool>();
if (string.IsNullOrEmpty(myTableFilterBox.Text))
foreach (IBlueRow r in rows)
{
foreach (IBlueRow r in rows) {
sl[r["tag"].ToString().Substring(PubStreamPrefixer.prefix("").Length)] = true;
}
else
{
else {
Regex tableRegex = new Regex(myTableFilterBox.Text);
foreach (IBlueRow r in rows)
{
foreach (IBlueRow r in rows) {
string thisTable = r["tag"].ToString().Substring(PubStreamPrefixer.prefix("").Length);
if (tableRegex.IsMatch(thisTable))
sl[thisTable] = true;
@@ -687,11 +638,10 @@ namespace BCG
myTableListBox.TopIndex = top;
else
myTableListBox.TopIndex = Math.Min(sl.Count - 1, topindex);
myTableListBox.EndUpdate();
myTableListBox.EndUpdate();
}
private void testGridToolStripMenuItem_Click(object sender, EventArgs e)
{
private void testGridToolStripMenuItem_Click(object sender, EventArgs e) {
HighPerformanceTimer timer = new HighPerformanceTimer();
//while (true)
//{
@@ -713,11 +663,9 @@ namespace BCG
foreach (IBlueRow r in s.rows)
rows.Add(r);
for (int i = 0; i < 100; i++)
{
for (int i = 0; i < 100; i++) {
timer.start();
rows.Sort(delegate(IBlueRow r1, IBlueRow r2)
{
rows.Sort(delegate (IBlueRow r1, IBlueRow r2) {
return _sort_dicts_index(r1, r2, 5, true);
});
timer.stop();
@@ -725,22 +673,19 @@ namespace BCG
}
}
private static int mySortDictionaries(IBlueRow r1, IBlueRow r2, string column, bool low_to_high)
{
private static int mySortDictionaries(IBlueRow r1, IBlueRow r2, string column, bool low_to_high) {
if (r1.Contains(column) && r2.Contains(column))
return compare_send_dontcare_to_last(r1[column], r2[column], low_to_high);
else
return 0;
}
private static int _sort_dicts_index(IBlueRow r1, IBlueRow r2, int col_no, bool low_to_high)
{
private static int _sort_dicts_index(IBlueRow r1, IBlueRow r2, int col_no, bool low_to_high) {
//return compare_send_dontcare_to_last(r1[col_no], r2[col_no], low_to_high);
return ((IComparable)r1[col_no]).CompareTo(r2[col_no]);
}
internal static int compare_send_dontcare_to_last(object o1, object o2, bool low_to_high)
{
internal static int compare_send_dontcare_to_last(object o1, object o2, bool low_to_high) {
if (myIsDontCare(o1))
return myIsDontCare(o2) ? 0 : 1;
else
@@ -748,16 +693,14 @@ namespace BCG
: ((IComparable)o2).CompareTo(o1));
}
private static bool myIsDontCare(object o)
{
private static bool myIsDontCare(object o) {
return o == null || o == DBNull.Value ||
o is string && String.IsNullOrEmpty((string)o) ||
o is double && (Double.IsInfinity((double)o) || Double.IsNaN((double)o)) ||
o is float && (Single.IsInfinity((float)o) || Single.IsNaN((float)o));
}
private void _new_grid_form(object args)
{
private void _new_grid_form(object args) {
//System.Timers.Timer t = new System.Timers.Timer();
////t.SynchronizingObject
//BCG.Utilities.BlueEventLog.logEvent(String.Format("New BTSTabularGridTestForm created on thread {0}", System.Threading.Thread.CurrentThread.ManagedThreadId),
@@ -768,5 +711,13 @@ namespace BCG
}
private void libraryToolStripMenuItem_Click(object sender, EventArgs e) { }
private void myTableFilterLabel_Click(object sender, EventArgs e) {
}
private void MainForm_Load(object sender, EventArgs e) {
}
}
}
@@ -1,64 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
@@ -1,24 +1,35 @@
using System;
using System.Windows.Forms;
using BCG;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using bts;
using mbts;
using mbts.config;
using bts.utils;
using mbts.config;
using System;
using System.Linq;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.ComponentModel;
static class Program {
[STAThread]
static void Main(string[] args) {
static void init(string[] args) {
Func<string, string, Task> login = async (l, p) => {
var login = l;
var passwd = p;
var service_ctx = bts.api.core.ServiceContext.create();
await service_ctx.login(login, passwd);
};
BTSNativeMethods.provide_command_line(args, args.Length);
Configuration.initialize();
bts.Log.Gen.info($"Starting DSQA");
Console.WriteLine("Starting DataStreamQueryAnalyzer...");
Console.WriteLine("Starting Test Publisher");
// TestPubliser.publish();
// TestPubliser.subscribe();
Task.Run(async () => await login("bts", String.Empty));
}
[STAThread]
static void Main(string[] args) {
init(args);
string args_concat = String.Empty;
args.ToList().ForEach(t => args_concat += t);
var init_log = $"Starting DSQA args: {args_concat} len: {args.Length}";
bts.Log.Gen.info(init_log);
Console.WriteLine(init_log);
Console.WriteLine("Launching Main Window");
MainForm mainForm = new MainForm();
if (args.Length > 0) {
@@ -27,65 +38,3 @@ static class Program {
Application.Run(mainForm);
}
}
class TestPubItem : IFormatter, IPubItem
{
public DateTime send_time = DateTime.Now;
public object Deserialize(Stream str)
{
BinaryReader br = new BinaryReader(str);
var d = br.ReadDouble();
TestPubItem rv = new TestPubItem();
rv.send_time = DateTime.FromOADate(d);
return rv;
}
public void Serialize(Stream str, Object obj)
{
TestPubItem tpi = obj as TestPubItem;
BinaryWriter bw = new BinaryWriter(str);
bw.Write(tpi.send_time.ToOADate());
}
public System.Runtime.Serialization.SerializationBinder? Binder { get; set; }
public System.Runtime.Serialization.StreamingContext Context { get; set; }
public System.Runtime.Serialization.ISurrogateSelector? SurrogateSelector { get; set; }
public string getTag()
{
return "Test_Tag";
}
}
class TestPubliser
{
public static void publish()
{
int n_pubs = 1000;
Publisher<TestPubItem> publisher = new Publisher<TestPubItem>();
for (int i = 0; i < n_pubs; i++)
{
TestPubItem pi = new TestPubItem();
pi.send_time = DateTime.Now;
bts.Log.Gen.info($"DSQA publishing tag: {pi.getTag()}");
publisher.publish(pi);
System.Threading.Thread.Sleep(100);
MasterWorker.getInstance(false).doWork();
}
}
public static void subscribe()
{
ManagedSubscriber ms = new ManagedSubscriber();
ms.subscribe("Test_Tag", new Handler(on_data));
while (true)
{
ms.doWork();
}
}
public static void on_data(IPubItem pi)
{
Console.WriteLine("Received data");
}
}
+12 -1
View File
@@ -1,4 +1,3 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
@@ -35,6 +34,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColumnMapExpressions", "Col
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExpressionCore", "ExpressionCore\ExpressionCore.csproj", "{B94AB04B-76D0-4D37-8F2E-7A57A70D289F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamTests", "DataStreamTests\DataStreamTests.csproj", "{66AB10D3-155F-4663-B1BC-D0818E17B87B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedStreams", "SharedStreams\SharedStreams.csproj", "{C1EBC423-4668-43D4-B7E5-A291086BA823}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -80,6 +83,10 @@ Global
{52DD33DB-00F5-44BF-AE0F-5FC58FB2277E}.Debug|Any CPU.Build.0 = Debug|x64
{52DD33DB-00F5-44BF-AE0F-5FC58FB2277E}.Release|Any CPU.ActiveCfg = Release|x64
{52DD33DB-00F5-44BF-AE0F-5FC58FB2277E}.Release|Any CPU.Build.0 = Release|x64
{66AB10D3-155F-4663-B1BC-D0818E17B87B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{66AB10D3-155F-4663-B1BC-D0818E17B87B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{66AB10D3-155F-4663-B1BC-D0818E17B87B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{66AB10D3-155F-4663-B1BC-D0818E17B87B}.Release|Any CPU.Build.0 = Release|Any CPU
{0FD1BE7A-AEC8-4575-BA58-20E0F45E5214}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0FD1BE7A-AEC8-4575-BA58-20E0F45E5214}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0FD1BE7A-AEC8-4575-BA58-20E0F45E5214}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -108,5 +115,9 @@ Global
{B94AB04B-76D0-4D37-8F2E-7A57A70D289F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B94AB04B-76D0-4D37-8F2E-7A57A70D289F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B94AB04B-76D0-4D37-8F2E-7A57A70D289F}.Release|Any CPU.Build.0 = Release|Any CPU
{C1EBC423-4668-43D4-B7E5-A291086BA823}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C1EBC423-4668-43D4-B7E5-A291086BA823}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1EBC423-4668-43D4-B7E5-A291086BA823}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C1EBC423-4668-43D4-B7E5-A291086BA823}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.0" />
<PackageReference Include="NUnit.Analyzers" Version="3.5.0" />
<PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\client\spark_api\spark_api.csproj" />
<ProjectReference Include="..\..\client\spark_core\spark_core.csproj" />
<ProjectReference Include="..\pubsub\pubsub.csproj" />
<ProjectReference Include="..\DataStreamCore\DataStreamCore.csproj" />
<ProjectReference Include="..\DataStream\DataStream.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,195 @@
using System;
using System.IO;
using NUnit.Framework;
namespace BCG {
/// <summary>
/// Tests the deserialization happening within the pubsub.
/// </summary>
public class UniversalSerializationTest {
protected IBlueTableSchema mySchema;
protected BlueTable myTable;
protected IBlueDataSerializer mySer = new BlueDataSerializationController();
protected IPubsubDeserializer myPubsubDeser = new PubsubDeserializationController();
protected IClientDeserializer myClientDeser = new ClientDeserializationController();
public UniversalSerializationTest() {
mySchema = new BlueTableSchema(myGetTableName(),
new ColumnInfo("id", 0, typeof(int)),
new ColumnInfo("i1", 1, typeof(int)),
new ColumnInfo("d1", 2, typeof(double)),
new ColumnInfo("dt", 3, typeof(DateTime)),
new ColumnInfo("x", 4, typeof(byte))
);
}
protected virtual string myGetTableName() {
return "testUniversal";
}
/// <summary>
/// Tests the entire cycle. This is done by 'publishing' data to the serializationController (ie a series of
/// adds, deletions, changes etc) and getting the bytes and feeding it into a pubsubDeseriazlier and a clientDeserializer.
/// At every step the data is tested for consistency. At the end the getState is used to get all the data, and its passed
/// through the clientDeserializer to get all the rows.
///
/// </summary>
[Test]
public void testEntireProcess() {
myTable = new BlueTable(mySchema);
byte[] data;
int id;
//create
for (id = 0; id < 100; id++)
myTable.addRow(myGetRow(id));
byte[] ops;
Array rows;
IBlueRowCollection del, add;
IBlueRowCollection[] receivedData;
IBlueRow r;
//create
mySer.serialize(StreamOpCode.create, new IBlueRowCollection[] { myTable }, out data);
myWrite(StreamOpCode.create, data);
myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
Assert.AreEqual(1, ops.Length);
Assert.AreEqual(StreamOpCode.create, ops[0]);
Assert.AreEqual(1, rows.Length);
receivedData = rows.GetValue(0) as IBlueRowCollection[];
Assert.AreEqual(1, receivedData.Length);
BlueDataUtility.computeDifferences(receivedData[0], myTable, out del, out add);
Assert.AreEqual(0, del.Count);
Assert.AreEqual(0, add.Count);
//single add
r = myGetRow(id);
BlueTable temp = new BlueTable(mySchema);
myTable.addRow(r);
temp.addRow(r);
mySer.serialize(StreamOpCode.add, new IBlueRowCollection[] { temp }, out data);
myWrite(StreamOpCode.add, data);
myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
Assert.AreEqual(1, ops.Length);
Assert.AreEqual(StreamOpCode.add, ops[0]);
Assert.AreEqual(1, rows.Length);
receivedData = rows.GetValue(0) as IBlueRowCollection[];
Assert.AreEqual(1, receivedData.Length);
BlueDataUtility.computeDifferences(receivedData[0], temp, out del, out add);
Assert.AreEqual(0, del.Count);
Assert.AreEqual(0, add.Count);
//single delete
r = myTable[0]; //delete row with id 0
temp = new BlueTable(mySchema);
myTable.deleteRow(0);
temp.addRow(r);
mySer.serialize(StreamOpCode.remove, new IBlueRowCollection[] { temp }, out data);
myWrite(StreamOpCode.remove, data);
myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
Assert.AreEqual(1, ops.Length);
Assert.AreEqual(StreamOpCode.remove, ops[0]);
Assert.AreEqual(1, rows.Length);
receivedData = rows.GetValue(0) as IBlueRowCollection[];
Assert.AreEqual(1, receivedData.Length);
BlueDataUtility.computeDifferences(receivedData[0], temp, out del, out add);
Assert.AreEqual(0, del.Count);
Assert.AreEqual(0, add.Count);
//batch deletes and adds
//0 was removed earlier, so lets delete from 1 to 24 first, and then add 101 to 124
BlueTable delRows = new BlueTable(mySchema), addRows = new BlueTable(mySchema);
for (int i = 1; i < 25; i++) {
delRows.addRow(myTable[i]);
myTable.deleteRow(i);
}
for (id = 101; id < 125; id++) {
r = myGetRow(id);
addRows.addRow(r);
myTable.addRow(r);
}
for (int i = 25; i < 125; i++)
Assert.AreEqual(true, myTable.containsID(i));
Assert.AreEqual(100, myTable.Count);
mySer.serialize(StreamOpCode.multipleRemoveAdd, new IBlueRowCollection[] { delRows, addRows }, out data);
myWrite(StreamOpCode.multipleRemoveAdd, data);
myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
Assert.AreEqual(1, ops.Length);
Assert.AreEqual(StreamOpCode.multipleRemoveAdd, ops[0]);
Assert.AreEqual(1, rows.Length);
receivedData = rows.GetValue(0) as IBlueRowCollection[];
Assert.AreEqual(2, receivedData.Length);
BlueDataUtility.computeDifferences(receivedData[0], delRows, out del, out add);
Assert.AreEqual(0, del.Count);
Assert.AreEqual(0, add.Count);
BlueDataUtility.computeDifferences(receivedData[1], addRows, out del, out add);
Assert.AreEqual(0, del.Count);
Assert.AreEqual(0, add.Count);
//pure changes only
//change the first 25, 25-49
BlueTable changedRows = new BlueTable(mySchema);
for (int i = 25; i < 50; i++) {
MutableBlueRow mr = new MutableBlueRow(myTable[i]);
mr.setValue(4, Byte.MaxValue);
myTable.changeRow(mr);
changedRows.addRow(mr);
}
mySer.serialize(StreamOpCode.multipleChange, new IBlueRowCollection[] { changedRows }, out data);
myWrite(StreamOpCode.multipleChange, data);
myPubsubDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
myClientDeser.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
Assert.AreEqual(1, ops.Length);
Assert.AreEqual(StreamOpCode.multipleChange, ops[0]);
Assert.AreEqual(1, rows.Length);
receivedData = rows.GetValue(0) as IBlueRowCollection[];
Assert.AreEqual(1, receivedData.Length);
BlueDataUtility.computeDifferences(receivedData[0], changedRows, out del, out add);
Assert.AreEqual(0, del.Count);
Assert.AreEqual(0, add.Count);
//final test
data = myPubsubDeser.getState();
new ClientDeserializationController().deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows);
Assert.AreEqual(1, ops.Length);
Assert.AreEqual(StreamOpCode.create, ops[0]);
Assert.AreEqual(1, rows.Length);
receivedData = rows.GetValue(0) as IBlueRowCollection[];
Assert.AreEqual(1, receivedData.Length);
BlueDataUtility.computeDifferences(receivedData[0], myTable, out del, out add);
Assert.AreEqual(0, del.Count);
Assert.AreEqual(0, add.Count);
}
private IBlueRow myGetRow(int id) {
return new BlueRow(mySchema, // the day pp fixed this test.
id, id + 10, id * 3.0, new DateTime(2008, 6, 4, 0, 0, 0, DateTimeKind.Unspecified), Convert.ToByte(id));
}
private void myWrite(byte op, byte[] data) {
string s = "";
if (op == StreamOpCode.add)
s = "add one row";
else if (op == StreamOpCode.change)
s = "change one row";
else if (op == StreamOpCode.create)
s = "create";
else if (op == StreamOpCode.multipleChange)
s = "multiple change";
else if (op == StreamOpCode.multipleRemoveAdd)
s = "multiple add remove";
else if (op == StreamOpCode.remove)
s = "remove one row";
Console.WriteLine("yes, here , op = {0}, size = {1}", s, data.Length);
}
}
}
@@ -0,0 +1 @@
global using NUnit.Framework;
@@ -4,15 +4,13 @@ using System.Collections;
using System.Collections.Generic;
using BCG.Utilities;
namespace BCG
{
namespace BCG {
/// <summary>
/// Holds the state for a single tag. If the tagType has an
/// IPubSubServerTagHandler, it is updated and the state stored
/// there. Otherwise, this class saves the last published data.
/// </summary>
internal class SingleTagHandler
{
internal class SingleTagHandler {
private IPubSubServerTagHandler myHandler = null;
private string myTagType, myTag;
/// <summary>
@@ -20,9 +18,7 @@ namespace BCG
/// </summary>
private byte[] myData = null;
public SingleTagHandler(string tag, string tagType)
{
public SingleTagHandler(string tag, string tagType) {
myTagType = tagType;
myTag = tag;
myHandler = TagType2HandlerMap.getHandler(tagType, false);
@@ -30,23 +26,18 @@ namespace BCG
public string tagType { get { return myTagType; } }
public void publish(Stream data)
{
public void publish(Stream data) {
long pos = data.Position;
if (myHandler != null)
{
if (myHandler != null) {
myHandler.update(myTag, new Stream[] { data });
}
else
{
} else {
myData = new byte[data.Length];
data.Read(myData, 0, myData.Length);
}
data.Position = pos;
}
public byte[] getContent()
{
public byte[] getContent() {
return myHandler == null ? myData : myHandler.getContent(myTag);
}
}
@@ -54,46 +45,37 @@ namespace BCG
/// <summary>
/// Keeps the state of all the tags published.
/// </summary>
public class AllPublishedTagState
{
public class AllPublishedTagState {
private Dictionary<string, SingleTagHandler> myTagHandler = new Dictionary<string, SingleTagHandler>();
public AllPublishedTagState() { }
public void publish(string tag, string tagType, Stream data)
{
public void publish(string tag, string tagType, Stream data) {
if (!myTagHandler.ContainsKey(tag))
myTagHandler.Add(tag, new SingleTagHandler(tag, tagType));
myTagHandler[tag].publish(data);
}
public void publish(string tag, string tagType, byte[] data)
{
public void publish(string tag, string tagType, byte[] data) {
publish(tag, tagType, new MemoryStream(data));
}
public string[] publishedTags
{ get { return new ArrayList(myTagHandler.Keys).ToArray(typeof(string)) as string[]; } }
public string[] publishedTags { get { return new ArrayList(myTagHandler.Keys).ToArray(typeof(string)) as string[]; } }
public byte[] getContent(string tag, out string tagType)
{
public byte[] getContent(string tag, out string tagType) {
tagType = myTagHandler[tag].tagType;
return myTagHandler[tag].getContent();
}
public bool contains(string tag)
{
return myTagHandler.ContainsKey(tag);
public bool contains(string tag) {
return myTagHandler.ContainsKey(tag);
}
public void clear(string tag)
{
if (myTagHandler.ContainsKey(tag))
{
public void clear(string tag) {
if (myTagHandler.ContainsKey(tag)) {
myTagHandler.Remove(tag);
}
else{}
// BlueEventLog.logEvent("AllPublishTagState told to clear nonexisting tag " + tag, BlueEventLog2Level.Warning);
} else { }
// BlueEventLog.logEvent("AllPublishTagState told to clear nonexisting tag " + tag, BlueEventLog2Level.Warning);
}
}
@@ -1,117 +1,117 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using mbts;
//using BCG.Utilities;
// using System;
// using System.Collections.Generic;
// using System.Text;
// using System.Runtime.InteropServices;
// using mbts;
// //using BCG.Utilities;
namespace BCG
{
public class PubSubServerUnmanagedTCPConnection : IPubSubServerConnection
{
private BlutoSubAddress myServerAddress;
private SmartConnectionManagedWrapper myWrapper;
private ConnectionStatusChange myConnCallback;
private SyncQueue<Pair<int, byte[]>> myAllMsgsQueue = new SyncQueue<Pair<int, byte[]>>();
// namespace BCG
// {
// public class PubSubServerUnmanagedTCPConnection : IPubSubServerConnection
// {
// private BlutoSubAddress myServerAddress;
// private SmartConnectionManagedWrapper myWrapper;
// private ConnectionStatusChange myConnCallback;
// private SyncQueue<Pair<int, byte[]>> myAllMsgsQueue = new SyncQueue<Pair<int, byte[]>>();
public PubSubServerUnmanagedTCPConnection(string serverURL, SmartConnectionManagedWrapper wrapper)
{
myServerAddress = new BlutoSubAddress(serverURL);
myWrapper = wrapper;
myWrapper.initConnection(new BlutoSubAddress(serverURL));
myWrapper.resgisterDataCallback(myServerAddress, new SmartConnectionManagedWrapper.MessageDelegate(myHandleServerMessages));
}
// public PubSubServerUnmanagedTCPConnection(string serverURL, SmartConnectionManagedWrapper wrapper)
// {
// myServerAddress = new BlutoSubAddress(serverURL);
// myWrapper = wrapper;
// myWrapper.initConnection(new BlutoSubAddress(serverURL));
// myWrapper.resgisterDataCallback(myServerAddress, new SmartConnectionManagedWrapper.MessageDelegate(myHandleServerMessages));
// }
#region IPubSubServerConnection Members
// #region IPubSubServerConnection Members
public void sendWithConfirmation(byte[] data, ref string confId)
{
//BlueEventLog.logAssert(false, "This function should not be used on this class");
}
// public void sendWithConfirmation(byte[] data, ref string confId)
// {
// //BlueEventLog.logAssert(false, "This function should not be used on this class");
// }
public void send(byte[] data)
{
myWrapper.send(myServerAddress, data);
}
// public void send(byte[] data)
// {
// myWrapper.send(myServerAddress, data);
// }
public void send(System.IO.Stream str)
{
send (StreamUtilityMethods.getBytesFromStream(str));
}
// public void send(System.IO.Stream str)
// {
// send (StreamUtilityMethods.getBytesFromStream(str));
// }
public IList<byte[]> getUpdates(TimeSpan timeout, int maxElements)
{
List<Pair<int, byte[]>> msgs = myAllMsgsQueue.dequeueMultipleElements(Convert.ToInt32 (timeout.TotalMilliseconds), maxElements);
List<byte[]> rv = new List<byte[]>();
bool connSet = false;
foreach (Pair<int, byte[]> p in msgs)
{
int msgType = p.first;
byte[] msg = p.second;
if (msgType == 1)
{
rv.Add(msg);
}
else
{
connSet = true;
string connMsg = "connection to " + myServerAddress.ToString() + (msgType == 2 ? " broken" : " established");
Console.WriteLine(connMsg);
myConnCallback(myServerAddress.ToString(), msgType == 3);
}
}
return connSet ? new List<byte[]>() : rv;
}
public string serverURL
{
get { return myServerAddress.ToString(); }
}
// public IList<byte[]> getUpdates(TimeSpan timeout, int maxElements)
// {
// List<Pair<int, byte[]>> msgs = myAllMsgsQueue.dequeueMultipleElements(Convert.ToInt32 (timeout.TotalMilliseconds), maxElements);
// List<byte[]> rv = new List<byte[]>();
// bool connSet = false;
// foreach (Pair<int, byte[]> p in msgs)
// {
// int msgType = p.first;
// byte[] msg = p.second;
// if (msgType == 1)
// {
// rv.Add(msg);
// }
// else
// {
// connSet = true;
// string connMsg = "connection to " + myServerAddress.ToString() + (msgType == 2 ? " broken" : " established");
// Console.WriteLine(connMsg);
// myConnCallback(myServerAddress.ToString(), msgType == 3);
// }
// }
// return connSet ? new List<byte[]>() : rv;
// }
public string clientURL
{
get { return myWrapper.getClientAsSeenByServer (serverURL); }
}
// public string serverURL
// {
// get { return myServerAddress.ToString(); }
// }
public void registerCallback(ConnectionStatusChange del)
{
myConnCallback = del;
}
// public string clientURL
// {
// get { return myWrapper.getClientAsSeenByServer (serverURL); }
// }
public void registerDataCallback(DataDelegate del)
{
}
// public void registerCallback(ConnectionStatusChange del)
// {
// myConnCallback = del;
// }
public void registerSendConfirmationCallback(SendConfirmationDelegate del)
{
}
// public void registerDataCallback(DataDelegate del)
// {
// }
#endregion
// public void registerSendConfirmationCallback(SendConfirmationDelegate del)
// {
// }
#region IDisposable Members
// #endregion
public void Dispose()
{
}
// #region IDisposable Members
#endregion
// public void Dispose()
// {
#region IWorker Members
public void doWork()
{
}
#endregion
// }
/// <summary>
/// this is the only method that it executed on
/// a different thread
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
private void myHandleServerMessages(int msgType, byte[] msg)
{
myAllMsgsQueue.enqueue(new Pair<int, byte[]>(msgType, msg));
}
}
}
// #endregion
// #region IWorker Members
// public void doWork()
// {
// }
// #endregion
// /// <summary>
// /// this is the only method that it executed on
// /// a different thread
// /// </summary>
// /// <param name="data"></param>
// /// <returns></returns>
// private void myHandleServerMessages(int msgType, byte[] msg)
// {
// myAllMsgsQueue.enqueue(new Pair<int, byte[]>(msgType, msg));
// }
// }
// }
@@ -4,8 +4,7 @@ using System.Text;
using System.IO;
using BCG.Utilities.General;
namespace BCG
{
namespace BCG {
/// <summary>
/// This is the interface that both the PublisherCore and the
/// SubscriberCore use to communicate with the PubsubServer.
@@ -20,22 +19,23 @@ namespace BCG
/// multiple threads need to communicate to the PubSub, they
/// should create their own Subscribers.
/// </summary>
public interface IPubSubServerConnection : IDisposable, IWorker
{
public interface IPubSubServerConnection : IDisposable, IWorker {
/// <summary>
/// The delegate is fired signalling if the data send was
/// successful or not
/// </summary>
void sendWithConfirmation(byte[] data, ref string confId);
//void sendWithConfirmation(byte[] data, ref string confId);
/// <summary>
/// send is a non waiting call with no guarantee
/// of data being delivered
/// </summary>
void send (byte[] data);
/// <summary>
/// similiar to above
/// </summary>
// void send(byte[] data);
// /// <summary>
// /// similiar to above
// /// </summary>
void send(Stream str);
void send(PubSubMessage msg);
void send_with_confirmation(PubSubMessage msg, ref string confId);
/// <summary>
/// Returns with 0 or more elements, iff the timeout
/// expires or maxElements have been reached (selective polling),
@@ -51,13 +51,13 @@ namespace BCG
/// <summary>
/// server URL to which the connection is made
/// </summary>
string serverURL { get;}
string serverURL { get; }
/// <summary>
/// client URL as seen by the server. if a connection has not
/// been established (as can happen in TCP) an empty string
/// is returned
/// </summary>
string clientURL { get;}
string clientURL { get; }
/// <summary>
/// registers the callback to receive
@@ -9,8 +9,7 @@ using System.IO;
using System.Threading;
using mbts;
namespace BCG
{
namespace BCG {
/// <summary>
/// Keeps an ITCPConnection for talking to the server. It also monitors heartbeats
/// from the server, and in case of missing hbs, informs its clients, and tries to
@@ -23,91 +22,94 @@ namespace BCG
/// </summary>
public class PubSubServerManagedTCPConnection : IPubSubServerConnection,
ITCPMessageHandler,
ITCPConnectionHandler
{
private ITCPConnection myConnection, myTempNewConnection;
private BlutoSubAddress myServerAddress;
private ThreadSafeQueue<Pair<string, bool>> myConfs = new ThreadSafeQueue<Pair<string, bool>>();
private SyncQueue<byte[]> myDataQueue = new SyncQueue<byte[]>();
private DateTime myLastHB = DateTime.Now;
private ConnectionStatusChange myConnCallback;
private DataDelegate myDataCallback;
private SendConfirmationDelegate myOnSendConfirmCallback;
private TimeSpan myConnectionDropThreshold =
ITCPConnectionHandler {
private ITCPConnection _connection, _new_connection;
private readonly BlutoSubAddress _server_address;
// if a message(with confirm) can not be sent , its id is queued here,
// on reconnection, _on_send_onfirm_callback is fired with a negative on these ids, so the user
//can re-send it. The re-send mechanism is not in implemented in this class, but by the user of this class
private ThreadSafeQueue<string> _negative_unsent_confs = new ThreadSafeQueue<string>();
// in onData, data is queued here
private SyncQueue<byte[]> _in_data_queue = new SyncQueue<byte[]>();
private DateTime _last_hb = DateTime.Now;
private ConnectionStatusChange _conn_callback;
private DataDelegate _data_callback;
private SendConfirmationDelegate _on_send_onfirm_callback;
private readonly TimeSpan _connection_drop_threshold =
new TimeSpan(0, 0, 0, 0, PubSub3Config.instance.PS3_HeartBeatInterval * PubSub3Config.instance.PS3_MissingHeartBeatsForGC);
public PubSubServerManagedTCPConnection(string serverURL)
: this(new BlutoSubAddress(serverURL)) { }
public PubSubServerManagedTCPConnection(BlutoSubAddress serverAddress)
{
myServerAddress = serverAddress;
ClientToServerManagedTCPConnector.connectTo(serverAddress, this);
public PubSubServerManagedTCPConnection(BlutoSubAddress server_address) {
_server_address = server_address;
_connect_to_ps_server();
}
private void _connect_to_ps_server() {
bts.Log.Gen.info($"PubSubServerManagedTCPConnection._connect_to_ps_server server: {_server_address}");
ClientToServerManagedTCPConnector.connect_to(_server_address, this, TimeSpan.FromSeconds(1));
}
#region IPubSubServerConnection Members
public void sendWithConfirmation(byte[] data, ref string confId)
{
if (myConnection != null)
{
myConnection.sendWithConfirmation(data, ref confId, new SendConfirmationDelegate(myOnSendConfirm));
}
else
{
confId = Guid.NewGuid().ToString();
myConfs.enqueue(new Pair<string, bool>(confId, false));
public void sendWithConfirmation(byte[] data, ref string conf_id) {
bts.Log.Gen.info($"PubSubServerManagedTCPConnection.sendWithConfirmation server: {_server_address} data: {data.Length} myConnection : {_connection != null}");
if (_connection != null) {
_connection.sendWithConfirmation(data, ref conf_id, (msg_id, confirmed) => {
if (_on_send_onfirm_callback != null)
_on_send_onfirm_callback(msg_id, confirmed);
});
} else {
bts.Log.Gen.warn($"PubSubServerManagedTCPConnection.sendWithConfirmation server: {_server_address} no connection, buffering send");
conf_id = Guid.NewGuid().ToString();
_negative_unsent_confs.enqueue(conf_id);
}
}
public void send(byte[] data)
{
Console.WriteLine($"PubSubServerManagedTCPConnection.send server: {myServerAddress} data: {data.Length} myConnection : {myConnection != null}");
if (myConnection != null)
{
Console.WriteLine("PubSubServerManagedTCPConnection.send server: " + myServerAddress + "data: " + data.Length);
myConnection.send(data);
public void send(byte[] data) {
bts.Log.Gen.info($"PubSubServerManagedTCPConnection.send server: {_server_address} data: {data.Length} myConnection : {_connection != null}");
if (_connection != null) {
bts.Log.Gen.info("PubSubServerManagedTCPConnection.send server: " + _server_address + "data: " + data.Length);
_connection.send(data);
}
}
public void send(Stream str)
{
public void send(Stream str) {
BinaryReader br = new BinaryReader(str);
send(br.ReadBytes(Convert.ToInt32(str.Length - str.Position)));
}
public IList<byte[]> getUpdates(TimeSpan timeout, int maxElements)
{
return myDataQueue.dequeueMultipleElements(Convert.ToInt32(timeout.TotalMilliseconds), maxElements);
public void send(PubSubMessage msg) {
send(msg.to_stream());
}
public string serverURL
{
get { return myServerAddress.ToString(); }
public void send_with_confirmation(PubSubMessage msg, ref string conf_id) {
var bytes = msg.to_bytes();
sendWithConfirmation(bytes, ref conf_id);
}
public string clientURL
{
get
{
public IList<byte[]> getUpdates(TimeSpan timeout, int maxElements) {
return _in_data_queue.dequeueMultipleElements(Convert.ToInt32(timeout.TotalMilliseconds), maxElements);
}
public string serverURL {
get { return _server_address.ToString(); }
}
public string clientURL {
get {
string rv = "";
lock (this)
{
if (myConnection == null)
{
lock (this) {
if (_connection == null) {
rv = "";
}
else
{
if (PubSub3Config.instance.PS3_IPTranslation == null || PubSub3Config.instance.PS3_IPTranslation == String.Empty)
{
} else {
if (PubSub3Config.instance.PS3_IPTranslation == null || PubSub3Config.instance.PS3_IPTranslation == String.Empty) {
string ip;
int port;
myConnection.getSelfAddress(out ip, out port);
_connection.getSelfAddress(out ip, out port);
rv = new BlutoSubAddress(ip, port).ToString();
}
else
{
} else {
rv = "";
}
}
@@ -116,42 +118,35 @@ namespace BCG
}
}
public void registerCallback(ConnectionStatusChange del)
{
myConnCallback = del;
public void registerCallback(ConnectionStatusChange del) {
_conn_callback = del;
}
public void registerDataCallback(DataDelegate del)
{
myDataCallback = del;
public void registerDataCallback(DataDelegate del) {
_data_callback = del;
}
public void registerSendConfirmationCallback(SendConfirmationDelegate del)
{
myOnSendConfirmCallback = del;
public void registerSendConfirmationCallback(SendConfirmationDelegate del) {
_on_send_onfirm_callback = del;
}
#endregion
#region IDisposable Members
private bool myIsDisposed = false;
public void Dispose()
{
Console.WriteLine("PubSubServerManagedTCPConnection.Dispose");
private bool _is_disposed = false;
public void Dispose() {
bts.Log.Gen.info("PubSubServerManagedTCPConnection.Dispose");
//throw new Exception("The method or operation is not implemented.");
if (myConnection != null)
{
(myConnection as AsyncTCPConnection).Dispose();
if (_connection != null) {
_connection.Dispose();
}
myIsDisposed = true;
_is_disposed = true;
}
public bool isDisposed
{
get
{
return myIsDisposed;
public bool isDisposed {
get {
return _is_disposed;
}
}
@@ -166,20 +161,42 @@ namespace BCG
/// (long) is safe for multi threaded operations
/// </summary>
/// <param name="message"></param>
public void onData(RemoteMessage message)
{
Console.WriteLine($"PubSubServerManagedTCPConnection.onData msg:type: {message.messageType}");
if (message.messageType == RemoteMessageType.data)
{
if (myDataCallback != null)
myDataCallback(message.remoteConnectionInfo.ToString(), message.message);
else
myDataQueue.enqueue(message.message);
}
else
{
myLastHB = DateTime.Now;
public void onData(RemoteMessage message) {
bts.Log.Gen.info($"PubSubServerManagedTCPConnection.onData message: {message}");
// TODO check for disconenction
switch (message.messageType) {
case RemoteMessageType.Data:
if (_data_callback != null)
_data_callback(message.remoteConnectionInfo.ToString(), message.message);
else
_in_data_queue.enqueue(message.message);
break;
case RemoteMessageType.Heartbeat:
_last_hb = DateTime.Now;
break;
case RemoteMessageType.Connection:
_conn_callback(_server_address.ToString(), true);
break;
case RemoteMessageType.Disconnection:
if (_conn_callback != null)
_conn_callback(_server_address.ToString(), false);
_connection.Dispose();
_connect_to_ps_server();
break;
}
// this stupid shit, caused duplicating og messages and 2 days of wild goose chase
// if (message.messageType == RemoteMessageType.Data)
// {
// if (_data_callback != null)
// _data_callback(message.remoteConnectionInfo.ToString(), message.message);
// else
// _in_data_queue.enqueue(message.message);
// }
// else
// {
// _last_hb = DateTime.Now;
// }
}
#endregion
@@ -191,22 +208,52 @@ namespace BCG
/// except onData)
/// </summary>
/// <param name="connection"></param>
public void onConnection(ITCPConnection connection)
{
public void onConnection(ITCPConnection connection) {
string ip;
int port;
connection.getPeerAddress(out ip, out port);
BlutoSubAddress add = new BlutoSubAddress(ip, port);
Console.WriteLine($"PubSubServerManagedTCPConnection.onConnection add: {add.ToString()}");
if (add.ToString() == myServerAddress.ToString())
{
myLastHB = DateTime.Now;
myTempNewConnection = connection;
bts.Log.Gen.info($"PubSubServerManagedTCPConnection.onConnection add: {add.ToString()} connection type: {connection.GetType()}");
if (add.ToString() == _server_address.ToString()) {
_last_hb = DateTime.Now;
_new_connection = connection;
}
}
#endregion
void _dispose_and_reconnect_if_missing_hb() {
if (!_connection.isDisposed) {
TimeSpan hb_interval = DateTime.Now - _last_hb;
bool hb_missed = hb_interval > _connection_drop_threshold;
if (hb_missed) {
if (_conn_callback != null)
_conn_callback(_server_address.ToString(), false);
bts.Log.Gen.info("PubSubServerManagedTCPConnection._dispose_and_reconnect_if_missing_hb disposing connecion: {myServerAddress}");
_connection.Dispose();
_connect_to_ps_server();
}
} else {
// already disposed, nothing to do
}
}
void _check_for_new_connection() {
if (_new_connection != null) {
_connection = _new_connection;
_new_connection = null; // since we are using its presence as a marker of nw connections
bts.Log.Gen.info("PubSubServerManagedTCPConnection._check_for_new_connection assigning new connection");
_connection.register(this);
if (_conn_callback != null)
_conn_callback(_server_address.ToString(), true);
if (_on_send_onfirm_callback != null) {
var msg_ids = _negative_unsent_confs.dequeueAll();
foreach (var id in msg_ids)
_on_send_onfirm_callback(id, false);
}
}
}
#region IWorker Members
/// <summary>
@@ -214,57 +261,57 @@ namespace BCG
/// the design only allows for onConnection to be on a different
/// thread.
/// </summary>
public void doWork()
{
public void doWork() {
//_dispose_and_reconnect_if_missing_hb();
_check_for_new_connection();
///check for heartbeats and let clients know in
///case of missing hb (connection breaking)
TimeSpan curr_hb_interval = DateTime.Now - myLastHB;
bool hb_missed = curr_hb_interval > myConnectionDropThreshold;
bool conn_disposed = myConnection != null && myConnection.isDisposed;
if (conn_disposed || hb_missed)
{
if (hb_missed)
{
// since conn breakage was diagnosed logically, lets physically close the connection
myConnection.Dispose();
string dispose_msg = $"PubSubServerManagedTCPConnection.doWork server: {myServerAddress} Disposing connection conn_disposed: {conn_disposed} hb_missed: {hb_missed}";
Console.WriteLine(dispose_msg);
}
myConnection = null; // this is used as a marker for a dead connection
if (myConnCallback != null)
myConnCallback(myServerAddress.ToString(), false);
string reconn_msg = $"PubSubServerManagedTCPConnection.doWork disconnecting client from server: {myServerAddress} conn_disposed: {conn_disposed} hb_missed: {hb_missed} " +
$"because of missing hbs last_hb: {myLastHB}, now: {DateTime.Now} curr_hb_interval: {curr_hb_interval.TotalSeconds} threshold: {myConnectionDropThreshold.TotalSeconds} conn_disposed: {conn_disposed}";
Console.WriteLine(reconn_msg);
ClientToServerManagedTCPConnector.connectTo(myServerAddress, this);
}
if (myTempNewConnection != null)
{
if (myConnection != null)
{
// TODOds
// log error and close it
// BlueEventLog.logAssert(myConnection == null, "Connection has to be nulled out and disposed "
// + " before a new connection is established");
}
Console.WriteLine("PubSubServerManagedTCPConnection hooking new connection");
myConnection = myTempNewConnection;
myTempNewConnection = null;
myConnection.register(this);
myConfs.dequeueAll();
if (myConnCallback != null)
myConnCallback(myServerAddress.ToString(), true);
}
foreach (Pair<string, bool> p in myConfs.dequeueAll())
if (myOnSendConfirmCallback != null)
myOnSendConfirmCallback(p.first, p.second);
// TimeSpan hb_interval = DateTime.Now - myLastHB;
// bool hb_missed = hb_interval > myConnectionDropThreshold;
// bool conn_disposed = myConnection != null || myConnection.isDisposed;
// if (conn_disposed || hb_missed)
// {
// if (hb_missed)
// {
// // since conn breakage was diagnosed logically, lets physically close the connection
// myConnection.Dispose();
// string dispose_msg = $"PubSubServerManagedTCPConnection.doWork server: {myServerAddress} Disposing connection conn_disposed: {conn_disposed} hb_missed: {hb_missed}";
// Console.WriteLine(dispose_msg);
// }
// myConnection = null; // this is used as a marker for a dead connection
// if (myConnCallback != null)
// myConnCallback(myServerAddress.ToString(), false);
// string reconn_msg = $"PubSubServerManagedTCPConnection.doWork disconnecting client from server: {myServerAddress} conn_disposed: {conn_disposed} hb_missed: {hb_missed} " +
// $"because of missing hbs last_hb: {myLastHB}, now: {DateTime.Now} curr_hb_interval: {hb_interval.TotalSeconds} threshold: {myConnectionDropThreshold.TotalSeconds} conn_disposed: {conn_disposed}";
// ClientToServerManagedTCPConnector.connectTo(myServerAddress, this);
// }
// if (myTempNewConnection != null)
// {
// if (myConnection != null)
// {
// // TODOds
// // log error and close it
// // BlueEventLog.logAssert(myConnection == null, "Connection has to be nulled out and disposed "
// // + " before a new connection is established");
// }
// Console.WriteLine("PubSubServerManagedTCPConnection hooking new connection");
// myConnection = myTempNewConnection;
// myTempNewConnection = null;
// myConnection.register(this);
// myConfs.dequeueAll();
// if (myConnCallback != null)
// myConnCallback(myServerAddress.ToString(), true);
// }
// foreach (Pair<string, bool> p in myConfs.dequeueAll())
// if (myOnSendConfirmCallback != null)
// myOnSendConfirmCallback(p.first, p.second);
}
#endregion
private void myOnSendConfirm(string messageId, bool confirmed)
{
myConfs.enqueue(new Pair<string, bool>(messageId, confirmed));
}
// private void myOnSendConfirm(string messageId, bool confirmed) {
// _negative_confs.enqueue(new Pair<string, bool>(messageId, confirmed));
// }
}
}
@@ -7,144 +7,116 @@ using System.Text;
using BCG;
//using BCG.Utilities;
using System.Collections.Generic;
namespace BCG
{
public class MetaData : ICloneable
{
private Hashtable myHash = new Hashtable();
namespace BCG {
// Thhis "wraps" around the following 4 PubSub meta objects, serializes it on the client and
// deserialize it on the pubsub
// PubMetaData
// SubMetaData
// TransactionMetaData
// UnSubMetaData
public class MetaData : ICloneable {
private IDictionary _name_value_map = new Dictionary<string, string>();
int mySize = -1;
public MetaData()
{}
public MetaData() { }
public MetaData(object o)
{copyFrom(o);}
public MetaData(object o) { copyFrom(o); }
public MetaData(Stream s)
{
public MetaData(Stream s) {
long initPos = s.Position;
load(s);
mySize = Convert.ToInt32(s.Position - initPos);
}
public string this[string name]
{
get
{return (string) myHash[name];}
set
{
public string this[string name] {
get { return (string)_name_value_map[name]; }
set {
if (value != null)
myHash[name] = value;
_name_value_map[name] = value;
}
}
public void add(string name, string [] values)
{
private void _add_string_array(string name, string[] values) {
StringBuilder sb = new StringBuilder();
foreach (string s in values)
{
foreach (string s in values) {
if (sb.Length != 0)
sb.Append(" ");
sb.Append(s);
}
myHash[name] = sb.ToString();
_name_value_map[name] = sb.ToString();
}
public int getAsInt(string name)
{return Int32.Parse(this[name]);}
private int getAsInt(string name) { return Int32.Parse(this[name]); }
public string[] getAsStringArray (string name)
{
private string[] _get_as_string_array(string name) {
if (this[name] != "" && this[name] != null)
return this[name].Split(' ');
else
return new string[0];
}
public int size()
{
if (mySize < 0)
{
public int size() {
if (mySize < 0) {
MemoryStream ms = new MemoryStream();
this.save(ms);
return mySize = (int)ms.Position;
}
else
} else
return mySize;
}
public bool isEqual (MetaData md)
{
if (md.myHash.Keys.Count != myHash.Keys.Count)
private bool isEqual(MetaData md) {
if (md._name_value_map.Keys.Count != _name_value_map.Keys.Count)
return false;
foreach (string k in myHash.Keys)
if (!myHash[k].Equals(md.myHash[k]))
foreach (string k in _name_value_map.Keys)
if (!_name_value_map[k].Equals(md._name_value_map[k]))
return false;
return true;
}
public void load(Stream s)
{
myHash = new Hashtable();
string [] state =
// loads the content of the stream into this instance's map
private void load(Stream s) {
_name_value_map = new Hashtable();
string[] state =
new BinaryReader(s).ReadString().Split('\n');
for (int i = 0; i < state.Length-1; i+= 2)
myHash[state[i]] = state[i+1];
for (int i = 0; i < state.Length - 1; i += 2)
_name_value_map[state[i]] = state[i + 1];
}
public void save(Stream s)
{
// writes the content of this instance to stream s
public void save(Stream s) {
new BinaryWriter(s).Write(this.ToString());
}
public override string ToString()
{
public override string ToString() {
StringBuilder sb = new StringBuilder();
foreach (string key in myHash.Keys)
sb.AppendFormat("{0}\n{1}\n",key,myHash[key]);
foreach (string key in _name_value_map.Keys)
sb.AppendFormat("{0}\n{1}\n", key, _name_value_map[key]);
return sb.ToString();
}
public void copyFrom(object o)
{
// iterates through the fields and enters the name, values into _hash
public void copyFrom(object o) {
this["op-code"] = o.GetType().Name;
foreach (FieldInfo fi in o.GetType().GetFields())
{
foreach (FieldInfo fi in o.GetType().GetFields()) {
if (fi.GetValue(o) == null)
continue;
else if (fi.GetValue(o) is String[])
add(fi.Name, (string[])fi.GetValue(o));
_add_string_array(fi.Name, (string[])fi.GetValue(o));
else
myHash[fi.Name] = fi.GetValue(o).ToString();
_name_value_map[fi.Name] = fi.GetValue(o).ToString();
}
}
public void copyTo(object o)
{
foreach (FieldInfo fi in o.GetType().GetFields())
{
// copies the name value map into object o
public void copyTo(object o) {
foreach (FieldInfo fi in o.GetType().GetFields()) {
string value = this[fi.Name];
//this should only be here temporarily, while the new decompression changes are waiting to go into prod.
if (value == null)
{
//BlueEventLog.logEvent("Error: Metadata missing field " + fi.Name, BlueEventLog2Level.MissingMetadata);
}
else
{
if (value == null) {
} else {
if (fi.FieldType.Equals(typeof(string)))
fi.SetValue(o, value);
else if (fi.FieldType.Equals(typeof(int)))
@@ -167,11 +139,10 @@ namespace BCG
}
}
public object Clone()
{
public object Clone() {
MemoryStream ms = new MemoryStream();
this.save(ms);
ms.Seek(0,SeekOrigin.Begin);
ms.Seek(0, SeekOrigin.Begin);
return new MetaData(ms);
}
}
@@ -1,25 +1,25 @@
using System;
// using System;
namespace BCG
{
[Serializable]
public class RenewMetaData
{
public string subscriber;
public int lease;
public bool c;
public SubAddress getSubAddress()
{return SubAddress.decode(subscriber);}
// namespace BCG
// {
// [Serializable]
// public class RenewMetaData
// {
// public string subscriber;
// public int lease;
// public bool c;
public RenewMetaData()
{}
// public SubAddress getSubAddress()
// {return SubAddress.decode(subscriber);}
public RenewMetaData(string s,
int lease)
{
this.subscriber = s;
this.lease = lease;
}
}
}
// public RenewMetaData()
// {}
// public RenewMetaData(string s,
// int lease)
// {
// this.subscriber = s;
// this.lease = lease;
// }
// }
// }
@@ -3,10 +3,8 @@ using BCG;
//using BCG.Utilities;
using System.Text.RegularExpressions;
namespace BCG
{
public class PubSubRoute : IComparable<PubSubRoute>
{
namespace BCG {
public class PubSubRoute : IComparable<PubSubRoute> {
public string serverAddress;
public string tagRegExp;
//route names are used in intermediary code (i.e. while substations are being deployed)
@@ -16,8 +14,7 @@ namespace BCG
public PubSubRoute() { }
public PubSubRoute(string theServerAddress, string theTagRegExp)
{
public PubSubRoute(string theServerAddress, string theTagRegExp) {
serverAddress = theServerAddress;
tagRegExp = theTagRegExp;
}
@@ -28,41 +25,39 @@ namespace BCG
// // tagRegExp = cfg.tagsRegex;
// }
public string[] getAllPubSubs()
{
public string[] getAllPubSubs() {
return serverAddress.Split(';');
}
public Regex getRegex()
{
public Regex getRegex() {
return myRegex ?? new Regex(tagRegExp);
}
#region IComparable<PubSubRoute> Members
public int CompareTo(PubSubRoute other)
{
public int CompareTo(PubSubRoute other) {
return serverAddress == other.serverAddress ? tagRegExp.CompareTo(other.tagRegExp)
: serverAddress.CompareTo(other.serverAddress);
}
#endregion
public override bool Equals(object obj)
{
public override bool Equals(object obj) {
if (!(obj is PubSubRoute) || obj == null)
return false;
else
{
else {
PubSubRoute other = obj as PubSubRoute;
return serverAddress.Equals(other.serverAddress) &&
tagRegExp.Equals(other.tagRegExp);
}
}
public override int GetHashCode()
{
public override int GetHashCode() {
return base.GetHashCode();
}
public static PubSubRoute get_default_route() {
return new PubSubRoute("bluto://127.0.0.0.1:1976", ".*");
}
}
}
@@ -7,26 +7,22 @@ using BCG;
//using BCG.Utilities;
//using bts;
namespace BCG
{
public class PubSubRouter : IPubSubRouter
{
namespace BCG {
public class PubSubRouter : IPubSubRouter {
private Regex[] myPubRouteRegExps;
private Regex[] mySubRouteRegExps;
private PubSubRoute[] myPubRoutes;
private PubSubRoute[] mySubRoutes;
private readonly string _temp_only_pubsub = "bluto://127.0.0.1:1976";
public PubSubRouter() : this(
PubSub3Config.instance.getSubRouting(),
PubSub3Config.instance.getPubRouting())
{ }
PubSub3Config.instance.getPubRouting()) { }
public PubSubRouter(params PubSubRoute[] routes) : this(routes, routes)
{ }
public PubSubRouter(params PubSubRoute[] routes) : this(routes, routes) { }
public PubSubRouter(PubSubRoute[] subRoutes, PubSubRoute[] pubRoutes)
{
public PubSubRouter(PubSubRoute[] subRoutes, PubSubRoute[] pubRoutes) {
mySubRouteRegExps = new Regex[subRoutes.Length];
myPubRouteRegExps = new Regex[pubRoutes.Length];
@@ -39,8 +35,7 @@ namespace BCG
myPubRouteRegExps[i] = new Regex(pubRoutes[i].tagRegExp);
}
private int myGetRouteIndex(string forTag, PubSubRoute[] routes, Regex[] regexes)
{
private int myGetRouteIndex(string forTag, PubSubRoute[] routes, Regex[] regexes) {
for (int i = 0; i < routes.Length; i++)
if (regexes[i].IsMatch(forTag))
return i;
@@ -50,49 +45,43 @@ namespace BCG
#region IPubSubRouter methods
private string myPickAServer(string tag, string[] urls)
{
private string myPickAServer(string tag, string[] urls) {
if (urls.Length == 1)
return urls[0];
else
{
else {
uint hc = (uint)tag.GetHashCode();
return urls[hc % urls.Length];
}
}
public string getPubURLForTag(string tag)
{
var rv = "bluto://127.0.0.1:1976"; //myPickAServer(tag, myPubRoutes[myGetRouteIndex(tag, myPubRoutes, myPubRouteRegExps)].getAllPubSubs());
public string getPubURLForTag(string tag) {
var rv = _temp_only_pubsub;
bts.Log.Gen.info($"PubSubRouter.getPubURLForTag tag: {tag} route: {rv}");
return rv;
}
public string getSubURLForTag(string tag)
{
var rv = "bluto://127.0.0.1:1976"; // myPickAServer(tag, mySubRoutes[myGetRouteIndex(tag, mySubRoutes, mySubRouteRegExps)].getAllPubSubs());
public string getSubURLForTag(string tag) {
var rv = _temp_only_pubsub; // myPickAServer(tag, mySubRoutes[myGetRouteIndex(tag, mySubRoutes, mySubRouteRegExps)].getAllPubSubs());
bts.Log.Gen.info($"PubSubRouter.getSubURLForTag tag: {tag} route: {rv}");
return rv;
}
public List<string> getAllPubSubSubURLs()
{
List<string> theURLs = new List<string>();
foreach (PubSubRoute subRoute in mySubRoutes)
theURLs.AddRange(subRoute.getAllPubSubs());
return theURLs;
public List<string> getAllPubSubSubURLs() {
// List<string> theURLs = new List<string>();
// foreach (PubSubRoute subRoute in mySubRoutes)
// theURLs.AddRange(subRoute.getAllPubSubs());
// return theURLs;
return new List<string>() { _temp_only_pubsub };
}
public List<string> getAllPubSubPubURLs()
{
List<string> theURLs = new List<string>();
foreach (PubSubRoute pubRoute in myPubRoutes)
theURLs.AddRange(pubRoute.getAllPubSubs());
return theURLs;
public List<string> getAllPubSubPubURLs() {
// List<string> theURLs = new List<string>();
// foreach (PubSubRoute pubRoute in myPubRoutes)
// theURLs.AddRange(pubRoute.getAllPubSubs());
// return theURLs;
return new List<string>() { _temp_only_pubsub };
}
public event PubSubTagURLChangeDelegate onSubURLTagRouteChange;
public event PubSubTagURLChangeDelegate onPubURLTagRouteChange;
@@ -100,10 +89,8 @@ namespace BCG
#endregion
//this function is put here so that the events are used, in order to prevent build errors.
private void myNeverCallThisFunction()
{
if (onPubURLTagRouteChange == null || onSubURLTagRouteChange == null)
{
private void myNeverCallThisFunction() {
if (onPubURLTagRouteChange == null || onSubURLTagRouteChange == null) {
int aVar = 2;
aVar = aVar + 2;
}
@@ -3,37 +3,33 @@ using System.Collections;
using System.Reflection;
using BCG.Utilities;
using System.Collections.Generic;
using System.Reactive.Subjects;
namespace BCG
{
public class TagType2HandlerMap
{
namespace BCG {
public class TagType2HandlerMap {
private static TagType2HandlerMap myServerHandlerMap = null,
myPublisherStateMap = null;
private Dictionary<string, IPubSubServerTagHandler> myTagTypeToPubHandlerMap = new Dictionary<string, IPubSubServerTagHandler>();
private Dictionary<string, IPubSubServerTagHandler> myTagTypeToPubHandlerMap =
new Dictionary<string, IPubSubServerTagHandler>();
public TagType2HandlerMap()
{
if (PubSub3Config.instance.PS3_TagTypeToAssemblyMap != null)
{
foreach (TagTypeToAssembly.Entry entry in PubSub3Config.instance.PS3_TagTypeToAssemblyMap.entries)
{
try
{
public TagType2HandlerMap() {
if (PubSub3Config.instance.PS3_TagTypeToAssemblyMap != null) {
foreach (TagTypeToAssembly.Entry entry in PubSub3Config.instance.PS3_TagTypeToAssemblyMap.entries) {
try {
var ass_loc = assembly_location;
bts.Log.Gen.info($"TagType2HandlerMap entry: {entry} assembly_location: {ass_loc}");
Assembly assem = Assembly.LoadFrom(entry.assembly);
Type t = assem.GetType(entry.handlerClass, true, false);
Type t = assem.GetType(entry.handlerClass, true, true);
object obj = Activator.CreateInstance(t);
IPubSubServerTagHandler tagHandler = obj as IPubSubServerTagHandler;
bts.Log.Gen.info($"TagType2HandlerMap successfully created obj: {obj} of type: {t} from assem: {assem}");
string[] tagTypes = tagHandler.supportedTagTypes;
foreach (string tagType in tagTypes)
{
foreach (string tagType in tagTypes) {
bts.Log.Gen.info($"TagType2HandlerMap adding tagType: {tagType} tagHandler: {tagHandler}");
myTagTypeToPubHandlerMap[tagType] = tagHandler;
}
}
catch (Exception ex)
{
// BlueEventLog.logEvent(string.Format("error happened while loading type from the assembly ", entry.handlerClass, entry.assembly), BlueEventLevel.Warning);
// BlueEventLog.logEvent(ex);
} catch (Exception ex) {
bts.Log.Gen.error($"TagType2HandlerMap threw exception ex: {ex}");
if (ex is OutOfMemoryException)
throw ex;
}
@@ -41,30 +37,41 @@ namespace BCG
}
}
private IPubSubServerTagHandler myGetHandlerFromTagType(string tagType)
{
public static string assembly_location {
get {
// string codeBase = Assembly.GetExecutingAssembly().CodeBase;
// UriBuilder uri = new UriBuilder(codeBase);
// string path = Uri.UnescapeDataString(uri.Path);
// return Path.GetDirectoryName(path);
// Get the executing assembly
Assembly executingAssembly = Assembly.GetExecutingAssembly();
// Get the location (path) of the executing assembly
string assembly_location = executingAssembly.Location;
return assembly_location;
}
}
private IPubSubServerTagHandler myGetHandlerFromTagType(string tagType) {
IPubSubServerTagHandler rv;
myTagTypeToPubHandlerMap.TryGetValue(tagType, out rv);
bts.Log.Gen.info($"TagType2HandlerMap.myGetHandlerFromTagType tag_type: {tagType} rv: {rv}");
return rv;
}
public static IPubSubServerTagHandler getHandler(string type, bool isServer)
{
lock (typeof(IPubSubServerTagHandler))
{
if (isServer)
{
public static IPubSubServerTagHandler getHandler(string type, bool isServer) {
lock (typeof(IPubSubServerTagHandler)) {
if (isServer) {
if (myServerHandlerMap == null)
myServerHandlerMap = new TagType2HandlerMap();
return myServerHandlerMap.myGetHandlerFromTagType(type);
}
else
{
} else {
if (myPublisherStateMap == null)
myPublisherStateMap = new TagType2HandlerMap();
return myPublisherStateMap.myGetHandlerFromTagType(type);
}
}
}
}
}
}
@@ -1,17 +1,23 @@
using System;
using System.IO;
using System.Reflection;
namespace BCG
{
namespace BCG {
[Serializable]
public class TagTypeToAssembly
{
public class TagTypeToAssembly {
//[Serializable]
public class Entry
{
public string handlerClass;
public string assembly;
public class Entry {
public string handlerClass = "BCG.PubSubServerTagHandler";
public string assembly = Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!,
"DataStreamCore.dll");
public override string ToString() {
return $"handlerClass: {handlerClass} assembly: {assembly}";
}
}
public Entry[] entries;
public Entry[] entries = new Entry[] { new Entry() };
}
}
@@ -5,17 +5,13 @@ using System.Text.RegularExpressions;
//using BCG.Utilities.BlueConfiguration;
//using BCG.Utilities;
namespace BCG
{
namespace BCG {
public class PubSub3Config //: ConfigurationRequest
{
private static PubSub3Config myInstance;
public static PubSub3Config instance
{
get
{
if (myInstance == null)
{
public static PubSub3Config instance {
get {
if (myInstance == null) {
myInstance = new PubSub3Config();
//myInstance = (PubSub3Config) ConfigurationRequester.request(typeof(PubSub3Config));
}
@@ -43,7 +39,7 @@ namespace BCG
private string[] myPS3_CrushableTags = new string[] { };
//moved from PS2
private TagTypeToAssembly myTagTypeToAssemblyMap;
private TagTypeToAssembly myTagTypeToAssemblyMap = new TagTypeToAssembly();
private string myPS3_ServerQueue;
//substation stuff
@@ -83,145 +79,112 @@ namespace BCG
// bluecomm transition
//public ConfigKeys.BlueComm_PSTransition BlueComm_PSTransition { get; set; }
public PubSub3Config()
{
public PubSub3Config() {
//BlueComm_PSTransition = new BCG.ConfigKeys.BlueComm_PSTransition(true);
}
public bool isValid()
{
public bool isValid() {
return true;
}
public int PS3_retriesOnNoBufferSpace
{
public int PS3_retriesOnNoBufferSpace {
get { return myPS3_retriesOnNoBufferSpace; }
set { myPS3_retriesOnNoBufferSpace = value; }
}
public int PS3_millisecondsBetweenNoBufferSpaceRetries
{
public int PS3_millisecondsBetweenNoBufferSpaceRetries {
get { return myPS3_millisecondsBetweenNoBufferSpaceRetries; }
set { myPS3_millisecondsBetweenNoBufferSpaceRetries = value; }
}
public int PS3_millisecondsBetweenTimeSliceUpdates
{
public int PS3_millisecondsBetweenTimeSliceUpdates {
get { return myPS3_millisecondsBetweenTimeSliceUpdates; }
set { myPS3_millisecondsBetweenTimeSliceUpdates = value; }
}
public bool BlueComm_mustDie
{
public bool BlueComm_mustDie {
get { return myBlueComm_mustDie; }
set { myBlueComm_mustDie = value; }
}
public int PS3_HeartBeatInterval
{
public int PS3_HeartBeatInterval {
get { return myPS3_HeartBeatInterval; }
set { myPS3_HeartBeatInterval = value; }
}
public int PS3_DoItAllSecondsBetweenLogs
{
public int PS3_DoItAllSecondsBetweenLogs {
get { return myPS3_DoItAllSecondsBetweenLogs; }
set { myPS3_DoItAllSecondsBetweenLogs = value; }
}
public int PS3_MissingHeartBeatsForGC
{
public int PS3_MissingHeartBeatsForGC {
get { return myPS3_MissingHeartBeatsBeforeGC; }
set { myPS3_MissingHeartBeatsBeforeGC = value; }
}
public bool PS3_UseManagedSockets
{
public bool PS3_UseManagedSockets {
get { return myPS3_UseManagedSockets; }
set { myPS3_UseManagedSockets = value; }
}
public int PS3_StateUpdatePeriod
{
public int PS3_StateUpdatePeriod {
get { return myPS3_StateUpdatePeriod; }
set { myPS3_StateUpdatePeriod = value; }
}
public int PS3_StatisticsUpdatePeriod
{
public int PS3_StatisticsUpdatePeriod {
get { return myPS3_StatisticsUpdatePeriod; }
set { myPS3_StatisticsUpdatePeriod = value; }
}
public int PS3_DisposedConnectionCheckPeriod
{
public int PS3_DisposedConnectionCheckPeriod {
get { return myPS3_DisposedConnectionCheckPeriod; }
set { myPS3_DisposedConnectionCheckPeriod = value; }
}
public int PS3_MessageProcessingWarningThreshold
{
public int PS3_MessageProcessingWarningThreshold {
get { return myPS3_MessageProcessingWarningThreshold; }
set { myPS3_MessageProcessingWarningThreshold = value; }
}
public int PS3_millisecondsBetweenSubInfoUpdates
{
public int PS3_millisecondsBetweenSubInfoUpdates {
get { return myPS3_millisecondsBetweenSubInfoUpdates; }
set { myPS3_millisecondsBetweenSubInfoUpdates = value; }
}
public double PS3_LatencyReportThresholdMS
{
public double PS3_LatencyReportThresholdMS {
get { return myPS3_LatencyReportThresholdMS; }
set { myPS3_LatencyReportThresholdMS = value; }
}
public int PS3_ServerPort
{
public int PS3_ServerPort {
get { return myPS3_ServerPort; }
set { myPS3_ServerPort = value; }
}
public PubSubRoute[] getSubRouting()
{ return getRouting(); }
public PubSubRoute[] getSubRouting() { return getRouting(); }
public PubSubRoute[] getPubRouting()
{ return getRouting(); }
public PubSubRoute[] getPubRouting() { return getRouting(); }
public PubSubRoute[] getRouting()
{
public PubSubRoute[] getRouting() {
// TODO
return new PubSubRoute[] { };
return new PubSubRoute[] { PubSubRoute.get_default_route() };
// return getRouting(SitesCore.getMySiteName());
}
public PubSubRoute[] getRouting(string forSite)
{
public PubSubRoute[] getRouting(string forSite) {
// TODO
return new PubSubRoute[] { };
// if (sites_layout != null) {
// foreach (var s in sites_layout.sites)
// if (s.name == forSite) {
// List<PubSubRoute> result = new List<PubSubRoute>();
// foreach (var cfgRoute in s.pubSub.routes)
// result.Add(new PubSubRoute(cfgRoute));
// return result.ToArray();
// }
// }
//BlueEventLog2.instance().assert(false, "Could not find site {0} in config", forSite);
return null;
return getRouting();
}
public List<string> getAllPubSubs()
{
public List<string> getAllPubSubs() {
return new List<string>();
//return getAllPubSubs(SitesCore.getMySiteName());
}
public List<string> getAllPubSubs(string forSite)
{
public List<string> getAllPubSubs(string forSite) {
List<string> result = new List<string>();
foreach (PubSubRoute r in getRouting(forSite))
result.AddRange(r.getAllPubSubs());
@@ -233,17 +196,14 @@ namespace BCG
// public ConfigKeys.sites_siteName sites_siteName { get; set; }
public TagTypeToAssembly PS3_TagTypeToAssemblyMap
{
public TagTypeToAssembly PS3_TagTypeToAssemblyMap {
get { return myTagTypeToAssemblyMap; }
set { myTagTypeToAssemblyMap = value; }
}
//[Description("PUBSUB: The Message queue to look for pub sub messages")]
public string PS3_ServerQueue
{
get
{
public string PS3_ServerQueue {
get {
if (myPS3_ServerQueue == null || myPS3_ServerQueue == "")
return "PubSubQueue";
else
@@ -252,14 +212,12 @@ namespace BCG
set { myPS3_ServerQueue = value; }
}
public bool PS3_InternallyPublishSubInfo
{
public bool PS3_InternallyPublishSubInfo {
get { return myPS3_InternallyPublishSubInfo; }
set { myPS3_InternallyPublishSubInfo = value; }
}
public string[] PS3_CrushableTags
{
public string[] PS3_CrushableTags {
get { return myPS3_CrushableTags; }
set { myPS3_CrushableTags = value; }
}
@@ -299,95 +257,80 @@ namespace BCG
// }
public bool PS3_UseSubstations
{
public bool PS3_UseSubstations {
get { return myPS3_UseSubstations; }
set { myPS3_UseSubstations = value; }
}
public PubSubPortRange PS3_PortRange
{
public PubSubPortRange PS3_PortRange {
get { return myPS3_PortRange; }
set { myPS3_PortRange = value; }
}
public bool PS3_BindToRandomPort
{
public bool PS3_BindToRandomPort {
get { return myPS3_BindToRandomPort; }
set { myPS3_BindToRandomPort = value; }
}
public bool PS3_IsSubstation
{
public bool PS3_IsSubstation {
get { return myPS3_IsSubstation; }
set { myPS3_IsSubstation = value; }
}
public bool PS3_UseDynamicClients
{
public bool PS3_UseDynamicClients {
get { return myPS3_UseDynamicClients; }
set { myPS3_UseDynamicClients = value; }
}
public bool PS3_UseManagedClientsInNativeCode
{
public bool PS3_UseManagedClientsInNativeCode {
get { return myPS3_UseManagedClientsInNativeCode; }
set { myPS3_UseManagedClientsInNativeCode = value; }
}
public string PS3_CompressedTagsRegex
{
public string PS3_CompressedTagsRegex {
get { return myPS3_CompressedTagsRegex; }
set { myPS3_CompressedTagsRegex = value; }
}
public string PS3_DebugTags
{
public string PS3_DebugTags {
get { return myPS3_DebugTags; }
set { myPS3_DebugTags = value; }
}
public string PS3_TagsToReportCompressionRatio
{
public string PS3_TagsToReportCompressionRatio {
get { return myPS3_TagsToReportCompressionRatio; }
set { myPS3_TagsToReportCompressionRatio = value; }
}
public bool PS3_DisableMSMQ
{
public bool PS3_DisableMSMQ {
get { return myPS3_DisableMSMQ; }
set { myPS3_DisableMSMQ = true; }
}
public string PS3_IPTranslation
{
public string PS3_IPTranslation {
get { return myPS3_IPTranslation; }
set { myPS3_IPTranslation = value; }
}
public long PS3_GCActivationThreshold
{
public long PS3_GCActivationThreshold {
get { return myGCActivationThreshold; }
set { myGCActivationThreshold = value; }
}
public int PS3_WaitPeriodAfterGC
{
public int PS3_WaitPeriodAfterGC {
get { return myWaitPeriodAfterGC; }
set { myWaitPeriodAfterGC = value; }
}
public bool PS3_UsePrepublishedServerState
{
public bool PS3_UsePrepublishedServerState {
get { return myPS3_UsePrepublishedServerState; }
set { myPS3_UsePrepublishedServerState = value; }
}
public int PS3_MaxPacketSize
{
public int PS3_MaxPacketSize {
get { return myPS3_MaxPacketSize; }
set { myPS3_MaxPacketSize = value; }
}
@@ -404,21 +347,17 @@ namespace BCG
// set { myRecovery_PubSubCopies = value; }
// }
public bool isTagDebugTag(string tag)
{
if (myDebugTagsRegex == null)
{
public bool isTagDebugTag(string tag) {
if (myDebugTagsRegex == null) {
myDebugTagsRegex = new Regex(myPS3_DebugTags, RegexOptions.IgnoreCase);
}
return myDebugTagsRegex.IsMatch(tag);
}
public bool isTagCompressed(string tag)
{
public bool isTagCompressed(string tag) {
if (myCompressedTagsRegex == null)
{
if (myCompressedTagsRegex == null) {
myCompressedTagsRegex = new Regex(myPS3_CompressedTagsRegex, RegexOptions.IgnoreCase);
}
@@ -426,10 +365,8 @@ namespace BCG
return (myCompressedTagsRegex.IsMatch(tag));
}
public bool shouldReportTagsCompressionRatio(string tag)
{
if (myTagsToReportCompressionRatioRegex == null)
{
public bool shouldReportTagsCompressionRatio(string tag) {
if (myTagsToReportCompressionRatioRegex == null) {
myTagsToReportCompressionRatioRegex = new Regex(myPS3_TagsToReportCompressionRatio, RegexOptions.IgnoreCase);
}
return (myTagsToReportCompressionRatioRegex.IsMatch(tag));
@@ -45,8 +45,7 @@ namespace BCG
public SendConfirmationDelegate onSendDel;
public AsyncMessage(byte[] theBuffer, int theOffset)
: this(theBuffer, theOffset, String.Empty, null)
{ }
: this(theBuffer, theOffset, String.Empty, null) { }
public AsyncMessage(byte[] theBuffer, int theOffset, string theMessageId, SendConfirmationDelegate theOnSendDel)
{
@@ -445,7 +444,7 @@ namespace BCG
myDataReceived = true;
Console.WriteLine($"AsyncTCPConnection Data received for the first time from peer {myPeer.ToString()}");
}
myMessageHandler.onData(new RemoteMessage(data, RemoteMessageType.data, myPeer));
myMessageHandler.onData(new RemoteMessage(data, RemoteMessageType.Data, myPeer));
}
else if (msgType == 1)
@@ -456,7 +455,7 @@ namespace BCG
Console.WriteLine($"AsyncTCPConnection HB received for the first time from peer {myPeer.ToString()}");
}
myLastHBReceivedTime = DateTime.Now;
myMessageHandler.onData(new RemoteMessage(null, RemoteMessageType.heartbeat, myPeer));
myMessageHandler.onData(new RemoteMessage(null, RemoteMessageType.Heartbeat, myPeer));
}
myReadSize();
}
@@ -0,0 +1,296 @@
using BCG;
using Google.Protobuf;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using BCG;
using System.Xml.Serialization;
using System.Reflection;
using BCG.Utilities.General;
using System.Net.WebSockets;
namespace BCG
{
public class AsyncTCPConnection2 : ITCPConnection, IWorker, IDisposable
{
//private Socket _socket;
// tied to the socket above
private NetworkStream _nw_stream;
private readonly ConnectionSide _side;
ITCPMessageHandler _message_handler;
private int _msg_id = 0;
RemoteConnectionInfo _peer_address;
RemoteConnectionInfo _self_address;
private TimeSpan _hb_period = TimeSpan.FromSeconds(1);
private DateTime _last_hb_sent = DateTime.MinValue;
private DateTime _last_hb_received = DateTime.MaxValue;
private static byte _msg_type_data = 1;
private static byte _msg_type_hb = 0;
private bool _is_disposed = false;
SyncQueue<QueuedMessage> _data_send_queue = new SyncQueue<QueuedMessage>();
public class QueuedMessage
{
public string id;
public SendConfirmationDelegate del;
public byte[] data;
public QueuedMessage(string id, SendConfirmationDelegate del, byte[] data)
{
id = id;
del = del;
data = data;
}
public QueuedMessage(byte[] data)
: this(String.Empty, null, data) { }
}
public enum ConnectionSide
{
Client,
Server
}
public AsyncTCPConnection2(Socket socket, ConnectionSide side)
{
//_socket = socket;
_nw_stream = new NetworkStream(socket);
_side = side;
IPEndPoint r_ep = socket.RemoteEndPoint as IPEndPoint;
_peer_address = new RemoteConnectionInfo(r_ep.Address.ToString(), r_ep.Port);
var loc_ep = socket.LocalEndPoint as IPEndPoint;
_self_address = new RemoteConnectionInfo(loc_ep.Address.ToString(), loc_ep.Port);
}
public void register(ITCPMessageHandler message_handler)
{
_message_handler = message_handler;
Task.Run(async () => _keep_reading());
Task.Run(async () => await _keep_sending());
//_keep_reading();
// if add a _keep_sending threadis added then we can maek send a non async
// methid making it much easier to integrate with the rest
}
// this thread pulls
private async Task _keep_sending()
{
bts.Log.Gen.info($"TCPConnection._keep_sending starting");
while (!_is_disposed)
{
try
{
QueuedMessage m = _data_send_queue.dequeue(100);
if (m == null)
{
continue;
}
await send_async(m.data);
if (String.IsNullOrEmpty(m.id))
{
m.del(m.id, true);
}
}
catch (Exception ex)
{
bts.Log.Gen.error($"TCPConnection._keep_sending ex: {ex.Message}");
await Task.Delay(100);
_handle_error(ex);
}
}
}
private async Task _keep_reading()
{
bts.Log.Gen.info($"TCPConnection._keep_reading starting");
while (!_is_disposed)
{
try
{
byte[] msg = await TCPSocketUtils.read_bytes_async(_nw_stream);
bts.Log.Gen.info($"AsyncTCPConnection2._keep_reading side: {_side} self: {get_self_address()} peer: {get_peer_address()} msg len: {msg.Length}");
await _handle_msg(msg);
}
catch (Exception ex)
{
bts.Log.Gen.error($"TCPConnection._keep_reading ex: {ex.Message}");
await Task.Delay(100);
_handle_error(ex);
}
}
}
private async Task _handle_msg(byte[] msg)
{
// read the first byte to read the msg type and deal with it accordingly
BinaryReader br = new BinaryReader(new MemoryStream(msg));
byte msg_type = br.ReadByte();
if (msg_type == _msg_type_data)
{
byte[] data = br.ReadBytes(msg.Length - 1);
RemoteMessage m = new RemoteMessage(data, RemoteMessageType.Data, _peer_address);
_message_handler.onData(m);
}
else
{
RemoteMessage m = new RemoteMessage(null, RemoteMessageType.Heartbeat, _peer_address);
_message_handler.onData(m);
}
}
// not very efficient
private static byte[] _prefix_msg_type(byte[] data)
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
bw.Write(_msg_type_data);
bw.Write(data);
ms.Position = 0;
return ms.ToArray();
}
private async void _handle_error(Exception ex)
{
bts.Log.Gen.error($"TCPConnection._handle_error ex: {ex}");
try
{
var socket = _nw_stream.Socket;
socket.Close();
socket.Dispose();
}
catch (Exception ex2)
{
bts.Log.Gen.error($"TCPConnection._handle_error got exception when closing Socket ex: {ex}");
}
_is_disposed = true;
RemoteMessage rm = new RemoteMessage(new byte[] { }, RemoteMessageType.Disconnection, _peer_address);
_message_handler.onData(rm);
}
public void send_with_confirmation(byte[] data, string confId, SendConfirmationDelegate del) { }
public async Task send_with_confirmation_async(byte[] data, string conf_id, SendConfirmationDelegate del)
{
try
{
conf_id = (++_msg_id).ToString();
await TCPSocketUtils.send_bytes_async(_nw_stream, data);
del(conf_id, true);
}
catch (Exception ex)
{
_handle_error(ex);
}
}
public void sendWithConfirmation(byte[] data, ref string conf_id, SendConfirmationDelegate del)
{
conf_id = (++_msg_id).ToString();
send(data);
del(conf_id, true);
}
public void send(byte[] data)
{
Task.Run(async () => await send_async(data));
bts.Log.Gen.info($"AsyncTCPConnection2.send self: {get_self_address()} peer: {get_peer_address()} msg len: {data.Length} sent successfully");
//_data_send_queue.enqueue(new QueuedMessage(data));
}
public async Task send_async(byte[] data)
{
// prefix 4 bytes for type (data vs hb)
MemoryStream str = new MemoryStream();
BinaryWriter bw = new BinaryWriter(str);
bw.Write(_msg_type_data);
bw.Write(data);
try
{
await TCPSocketUtils.send_bytes_async(_nw_stream, str.ToArray());
}
catch (Exception ex)
{
bts.Log.Gen.error($"AsyncTCPConnection2.send_async ex: {ex}");
_handle_error(ex);
}
}
public void getPeerAddress(out string ip, out int port)
{
ip = _peer_address.ip;
port = _peer_address.port;
///.Net has some problems getting the port, so using
///native code for that
//sockaddr addr = new sockaddr();
//int namelen = 16;
//getsockname(mySock.Handle, ref addr, ref namelen);
//port = addr.sin_port;
}
public RemoteConnectionInfo get_peer_address()
{
string ip; int port;
getPeerAddress(out ip, out port);
return new RemoteConnectionInfo(ip, port);
}
public RemoteConnectionInfo get_self_address()
{
string ip; int port;
getSelfAddress(out ip, out port);
return new RemoteConnectionInfo(ip, port);
}
public void getSelfAddress(out string ip, out int port)
{
ip = _self_address.ip;
port = _self_address.port;
}
private async void _send_hb()
{
if (_last_hb_sent - DateTime.Now > _hb_period)
{
MemoryStream ms = new MemoryStream();
BinaryWriter bw = new BinaryWriter(ms);
bw.Write(_msg_type_hb);
ms.Position = 0;
byte[] hb_msg = ms.ToArray();
await TCPSocketUtils.send_bytes_async(_nw_stream, hb_msg);
}
}
public void doWork()
{
_send_hb();
}
public void Dispose()
{
_nw_stream.Close();
_nw_stream.Dispose();
_is_disposed = true;
}
public bool isDisposed
{
get
{
return _is_disposed;
}
}
}
}
@@ -4,21 +4,19 @@ using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
//using BCG.Utilities;
//using BCG.Utilities.General;
namespace BCG
{
internal class SocketConnectionArgs
{
namespace BCG {
internal class SocketConnectionArgs {
public EndPoint ep;
public Socket sock;
public ITCPConnectionHandler handler;
public string serverURL;
internal SocketConnectionArgs(EndPoint theEp, Socket theSock, ITCPConnectionHandler theHandler,
string theServerURL)
{
string theServerURL) {
ep = theEp;
sock = theSock;
handler = theHandler;
@@ -26,46 +24,46 @@ namespace BCG
}
}
public class ClientToServerManagedTCPConnector
{
public class ClientToServerManagedTCPConnector {
private static Random myRnd = new Random(DateTime.Now.Millisecond);
private static TimeSpan myHBTimeSpan = new TimeSpan(0, 0, 0, 0, PubSub3Config.instance.PS3_HeartBeatInterval);
private static int myWaitTimeBeforeRetryingUpperLimit = 5000,
myWaitTimeBeforeRetryingLowerLimit = 1000;
public static void connectTo(BlutoSubAddress serverAddress, ITCPConnectionHandler handler)
{
// TODOds
// BlueEventLog.logEvent(String.Format("Connection being attempted to server {0}", serverAddress.ToString()),
// PS3LogLevels.connection);
public static void connectTo(BlutoSubAddress serverAddress, ITCPConnectionHandler handler) {
Console.WriteLine($"ClientToServerManagedTCPConnector.connectTo server: {serverAddress}");
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
EndPoint ep = new IPEndPoint(IPAddress.Parse(serverAddress.ip), serverAddress.port);
sock.BeginConnect(ep, new AsyncCallback(myOnConnect), new SocketConnectionArgs(ep, sock, handler, serverAddress.ToString()));
}
private static void myOnConnect(IAsyncResult res)
{
public static async Task connect_to_async(BlutoSubAddress serverAddress, ITCPConnectionHandler handler, TimeSpan wait_before_retrying, int max_n_attempts = 1024) {
bts.Log.Gen.info($"ClientToServerManagedTCPConnector.connectTo server: {serverAddress}");
await TCPSocketUtils.connect_to_server_async(serverAddress.ip, serverAddress.port, handler, wait_before_retrying, max_n_attempts);
}
public static void connect_to(BlutoSubAddress serverAddress, ITCPConnectionHandler handler, TimeSpan wait_before_retrying, int max_n_attempts = 1024) {
bts.Log.Gen.info($"ClientToServerManagedTCPConnector.connectTo server: {serverAddress}");
Task.Run(async () => {
await TCPSocketUtils.connect_to_server_async(serverAddress.ip, serverAddress.port, handler, wait_before_retrying, max_n_attempts);
});
}
private static void myOnConnect(IAsyncResult res) {
Console.WriteLine("ClientToServerManagedTCPConnector.myOnConnect " + res.ToString() + " " + res.AsyncState.ToString());
SocketConnectionArgs args = res.AsyncState as SocketConnectionArgs;
try
{
try {
args.sock.EndConnect(res);
}
catch (SocketException sex)
{
} catch (SocketException sex) {
string errMsg = String.Format("{0}: Connection to {1} failed.", DateTime.Now.ToString(), args.serverURL.ToString());
//BlueEventLog.logEvent(sex.Message + ";" + errMsg, PS3LogLevels.disconnection);
//Console.WriteLine(errMsg);
if (args.handler.isDisposed)
{
if (args.handler.isDisposed) {
string doneMsg = String.Format("{0}: Connection to {1} was disposed. Not Retrying.", DateTime.Now.ToString(), args.serverURL.ToString());
//Console.WriteLine(doneMsg);
// BlueEventLog.logEvent(doneMsg, PS3LogLevels.disconnection);
return;
}
else
{
} else {
string retryMsg = String.Format("{0}: Retrying Connection to {1}.", DateTime.Now.ToString(), args.serverURL.ToString());
//Console.WriteLine(retryMsg);
//BlueEventLog.logEvent(retryMsg, PS3LogLevels.disconnection);
@@ -2,15 +2,13 @@ using System;
using System.Collections.Generic;
using System.Text;
namespace BCG
{
namespace BCG {
public delegate void SendConfirmationDelegate(string messageId, bool confirmed);
/// <summary>
/// This is the very basic connection that sits right
/// on top of the sockets (unmanaged, managed whatever).
/// on top of the sockets (used on both server and client)
/// </summary>
public interface ITCPConnection : IDisposable
{
public interface ITCPConnection : IDisposable {
/// <summary>
/// The delegate is fired signalling if the data send was
/// successful or not
@@ -18,7 +16,7 @@ namespace BCG
/// <param name="data"></param>
/// <param name="confId"></param>
/// <param name="del"></param>
void sendWithConfirmation (byte[] data, ref string confId, SendConfirmationDelegate del);
void sendWithConfirmation(byte[] data, ref string confId, SendConfirmationDelegate del);
/// <summary>
/// sends data to the other side. theres no guaranatee that
/// data is delievered.
@@ -54,6 +52,6 @@ namespace BCG
/// hence this is an indicator of whether the connection is
/// alive or dead
/// </summary>
bool isDisposed { get;}
bool isDisposed { get; }
}
}
@@ -2,46 +2,51 @@ using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using bts.utils;
namespace BCG
{
public class RemoteConnectionInfo
{
namespace BCG {
public class RemoteConnectionInfo {
private string myIp;
private int myPort;
private IPEndPoint myEndPoint;
public RemoteConnectionInfo(string ip, int port)
{
public RemoteConnectionInfo(string ip, int port) {
myIp = ip;
myPort = port;
}
public RemoteConnectionInfo(string ip, short port, IPEndPoint endPoint)
: this (ip, port)
{
: this(ip, port) {
myEndPoint = endPoint;
}
public string ip
{
public string ip {
get { return myIp; }
}
public int port
{
public int port {
get { return myPort; }
}
public IPEndPoint endPoint
{
public IPEndPoint endPoint {
get { return myEndPoint; }
}
public override string ToString()
{
public override string ToString() {
return ip + ":" + port;
}
public override int GetHashCode() {
return ip.GetHashCode() ^ port.GetHashCode();
}
public override bool Equals(object? obj) {
if (obj == null) {
return false;
}
RemoteConnectionInfo other = obj as RemoteConnectionInfo;
return other != null && other.ip == ip && other.port == port;
}
}
}
@@ -9,7 +9,7 @@ namespace BCG
/// </summary>
public enum RemoteMessageType
{
heartbeat, data, connection, disconnection
Heartbeat, Data, Connection, Disconnection
}
/// <summary>
@@ -45,5 +45,11 @@ namespace BCG
get { return myConnInfo; }
}
override public string ToString()
{
Func<byte[], int> len = (byte[] m) => { return m == null ? 0 : m.Length; };
return $"type: {myMsgType} conn: {myConnInfo} msg: {len(myMsg)}";
}
}
}
@@ -5,39 +5,30 @@ using System.Text;
//using BCG.Utilities.General;
//using BCG.Utilities;
namespace BCG
{
public class ServerToClientManagedTCPConnectionAcceptor
{
namespace BCG {
public class ServerToClientManagedTCPConnectionAcceptor {
private static Dictionary<int, SingleServerToClientManagedTCPConnectionAcceptor> myPortToSingleServerAcceptorMap = new Dictionary<int, SingleServerToClientManagedTCPConnectionAcceptor>();
private static object mySyncObject = new object();
public static int activateWithRandomPort(ITCPConnectionHandler handler, TimeSpan clientHBTimeSpan)
{
public static int activateWithRandomPort(ITCPConnectionHandler handler, TimeSpan clientHBTimeSpan) {
SingleServerToClientManagedTCPConnectionAcceptor theAcceptor = new SingleServerToClientManagedTCPConnectionAcceptor();
int portNo = theAcceptor.activateWithRandomPort(handler, clientHBTimeSpan);
lock (mySyncObject)
{
lock (mySyncObject) {
myPortToSingleServerAcceptorMap[portNo] = theAcceptor;
}
return portNo;
return portNo;
}
public static int activate(ITCPConnectionHandler handler, int port, TimeSpan clientHBTimeSpan)
{
lock (mySyncObject)
{
if (myPortToSingleServerAcceptorMap.ContainsKey(port))
{
public static int activate(ITCPConnectionHandler handler, int port, TimeSpan clientHBTimeSpan) {
lock (mySyncObject) {
if (myPortToSingleServerAcceptorMap.ContainsKey(port)) {
string msg = string.Format("Error: Application is already accepting clients on port {0}", port);
// BlueEventLog.logEvent(msg, BlueEventLog2Level.Error);
return port;
}
else
{
} else {
SingleServerToClientManagedTCPConnectionAcceptor theAcceptor = new SingleServerToClientManagedTCPConnectionAcceptor();
int assignedport = theAcceptor.activate(handler, port, clientHBTimeSpan);
myPortToSingleServerAcceptorMap[assignedport] = theAcceptor;
@@ -46,6 +37,23 @@ namespace BCG
} //end lock
} //end activate code
public static int accept_connections(ITCPConnectionHandler handler, int port, TimeSpan clientHBTimeSpan) {
lock (mySyncObject) {
if (myPortToSingleServerAcceptorMap.ContainsKey(port)) {
string msg = string.Format("Error: Application is already accepting clients on port {0}", port);
// BlueEventLog.logEvent(msg, BlueEventLog2Level.Error);
return port;
} else {
SingleServerToClientManagedTCPConnectionAcceptor ps_acceptor = new SingleServerToClientManagedTCPConnectionAcceptor();
int assignedport = ps_acceptor.accept_on_port(handler, "127.0.0.1", port, clientHBTimeSpan);
myPortToSingleServerAcceptorMap[assignedport] = ps_acceptor;
return assignedport;
}
} //end lock
} //end activate code
}
}
@@ -4,13 +4,12 @@ using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
//using BCG.Utilities;
namespace BCG
{
public class SingleServerToClientManagedTCPConnectionAcceptor
{
namespace BCG {
public class SingleServerToClientManagedTCPConnectionAcceptor {
private TimeSpan myHBTimeSpan,
myWaitTimeBeforeRetrying = new TimeSpan(0, 0, 0, 0, 250);
private ITCPConnectionHandler myHandler;
@@ -18,58 +17,50 @@ namespace BCG
private int myPort;
public int activateWithRandomPort(ITCPConnectionHandler handler, TimeSpan clientHBTimeSpan)
{
public int activateWithRandomPort(ITCPConnectionHandler handler, TimeSpan clientHBTimeSpan) {
myHBTimeSpan = clientHBTimeSpan;
myHandler = handler;
myAcceptSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
int port = 0;
bool madeItThrough = false;
// BlueEventLog.logEvent("Looking for open port to run the server on.", PS3LogLevels.connection);
// BlueEventLog.logEvent("Looking for open port to run the server on.", PS3LogLevels.connection);
Random randomizer = new Random();
PubSubPortRange theRange = PubSub3Config.instance.PS3_PortRange;
//if the range of ports is 1000, then trying 5,000 times means
//your odds of missing an open port are less than 1%
int maxAttempts = (theRange.maxPort - theRange.minPort) * 5;
int maxAttempts = (theRange.maxPort - theRange.minPort) * 5;
int totalAttempts = 0;
while (!madeItThrough)
{
port = randomizer.Next();
while (!madeItThrough) {
port = randomizer.Next();
port = theRange.minPort + (port % (theRange.maxPort - theRange.minPort));
try
{
try {
myAcceptSock.Bind(new IPEndPoint(IPAddress.Any, port));
madeItThrough = true;
}
catch (Exception)
{
} catch (Exception) {
totalAttempts++;
if (totalAttempts < maxAttempts){
if (totalAttempts < maxAttempts) {
//BlueEventLog.logEvent("Couldn't bind to port " + port.ToString() + "; retrying...", PS3LogLevels.connection);
}
else
{
} else {
// BlueEventLog2.instance().abort("Couldn't find an open port to advertise the server on. Consider modifying PS3_PortRange. Talk to Mark for details.");
}
}
}
myPort = port;
myAcceptSock.Listen(250);
myAcceptSock.BeginAccept(new AsyncCallback(myOnAccept), new object[] { });
myAcceptSock.BeginAccept(new AsyncCallback(myOnAccept), new object[] { });
return myPort;
}
public int activate (ITCPConnectionHandler handler, int port, TimeSpan clientHBTimeSpan)
{
public int activate(ITCPConnectionHandler handler, int port, TimeSpan clientHBTimeSpan) {
myHBTimeSpan = clientHBTimeSpan;
myHandler = handler;
myAcceptSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint endpoint = new IPEndPoint (IPAddress.Any, port);
IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, port);
myAcceptSock.Bind(endpoint);
myAcceptSock.Listen(250);
myAcceptSock.BeginAccept(new AsyncCallback(myOnAccept), new object[] { });
@@ -77,15 +68,18 @@ namespace BCG
return myPort; // not sure why we need this class variable myPort, but I am just keeping it up with the existing code
}
private void myOnAccept(IAsyncResult res)
{
public int accept_on_port(ITCPConnectionHandler handler, string ip, int port, TimeSpan client_HB_timespan) {
Task.Run(async () => {
await TCPSocketUtils.accept_connections_async(ip, port, handler, TimeSpan.FromSeconds(1));
});
return port;
}
private void myOnAccept(IAsyncResult res) {
Socket newSock;
try
{
try {
newSock = myAcceptSock.EndAccept(res);
}
catch (Exception ex)
{
} catch (Exception ex) {
// BlueEventLog.logEvent(ex);
Thread.Sleep(myWaitTimeBeforeRetrying);
myAcceptSock.BeginAccept(new AsyncCallback(myOnAccept), new object[] { });
@@ -98,10 +92,10 @@ namespace BCG
ITCPConnection newConn = new AsyncTCPConnection(newSock, myHBTimeSpan);
myHandler.onConnection(newConn);
myAcceptSock.BeginAccept(new AsyncCallback(myOnAccept), new object[] { });
string ip;int port;
newConn.getPeerAddress (out ip, out port);
string ip; int port;
newConn.getPeerAddress(out ip, out port);
string connMsg = String.Format("Connection to port {2} made from {0}:{1}", ip, port, myPort);
// BlueEventLog.logEvent(connMsg, PS3LogLevels.connection);
// BlueEventLog.logEvent(connMsg, PS3LogLevels.connection);
//Console.WriteLine(connMsg);
}
}
@@ -0,0 +1,113 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using BCG;
using System.Xml.Serialization;
using System.Reflection;
using BCG.Utilities.General;
using System.Net.WebSockets;
namespace BCG
{
// utility functions for TCP socket async communications. Does the following
// client to server connect
// server to client connect accepting
// send data
// receive data
public static class TCPSocketUtils
{
#region socket opening and connecting
// keeps accepting connections forever
public static async Task accept_connections_async(string ip, int port, ITCPConnectionHandler handler,
TimeSpan wait_after_error)
{
IPAddress ipAddress = String.IsNullOrEmpty(ip) ? IPAddress.Parse(ip) : IPAddress.Any;
var ip_end_point = new IPEndPoint(ipAddress, port);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ip_end_point);
listener.Listen(10);
Socket client_socket = null;
while (true)
{
try
{
// keeps on accepting connections
client_socket = await listener.AcceptAsync();
AsyncTCPConnection2 new_conn = new(client_socket, AsyncTCPConnection2.ConnectionSide.Server);
handler.onConnection(new_conn);
}
catch (Exception ex)
{
bts.Log.Gen.error($"TCPConnection.accept ex: {ex} trying again");
Task.Delay(wait_after_error);
}
}
}
// connects to the server and ona successful connection, calls con__handler.on_connection_async with an ITCPConnection.
// In case of failures to connect it waits for a given amount of time before retrying
public static async Task<Socket> connect_to_server_async(string ip, int server_port, ITCPConnectionHandler conn_handler,
TimeSpan wait_after_failed_attempt, int n_max_attempts = 1024)
{
Socket client_socket = null;
for (int i = 0; i < n_max_attempts; i++)
{
try
{
string log_conn = $"{ip}:{server_port}";
bts.Log.Gen.info($"AsyncTCPConnection2.connect_to_server conn: {log_conn} attempt no: {i}");
IPAddress server_ip_address = IPAddress.Parse(ip);
client_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
await client_socket.ConnectAsync(server_ip_address, server_port);
bts.Log.Gen.info($"AsyncTCPConnection2.connect_to_server conn: {log_conn} successfully connected after {i} attempts");
ITCPConnection new_conn = new AsyncTCPConnection2(client_socket, AsyncTCPConnection2.ConnectionSide.Client);
conn_handler.onConnection(new_conn);
break;
}
catch (Exception ex)
{
bts.Log.Gen.error($"AsyncTCPConnection2.connect_to_server threw ex: {ex}, will reattempt now");
Task.Delay(wait_after_failed_attempt);
}
}
return client_socket;
}
#endregion
#region data sending/receiving
// prefixes the size of the data and sends it as 2 sends, for size and data
// (can be done as one send perhaps)
public static async Task send_bytes_async(NetworkStream nw_stream, byte[] data_buff)
{
var data_sz = data_buff.Length;
byte[] sz_buff = new byte[4];
// aend the size first
BinaryWriter bw = new BinaryWriter(new MemoryStream(sz_buff));
bw.Write(data_sz);
await nw_stream.WriteAsync(sz_buff, 0, 4);
await nw_stream.WriteAsync(data_buff, 0, data_buff.Length);
}
// reads the bytes on a connected socket, by doing the opposite of the above,
// reads the size first and then the data
public static async Task<byte[]> read_bytes_async(NetworkStream nw_stream)
{
byte[] sz_buffer = new byte[4];
//Asynchronously reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
int bytesRead = await nw_stream.ReadAsync(sz_buffer, 0, sz_buffer.Length);
BinaryReader br = new BinaryReader(new MemoryStream(sz_buffer));
int msg_sz = br.ReadInt32();
byte[] data_buffer = new byte[msg_sz];
bytesRead = await nw_stream.ReadAsync(data_buffer, 0, data_buffer.Length);
//Console.WriteLine($"read_bytes sz: {data_buffer.Length}");
return data_buffer;
}
#endregion
}
}
+23 -15
View File
@@ -4,31 +4,39 @@ using System.IO;
using BCG;
using BCG.Utilities;
namespace BCG
{
// Tuple of
public class PubSubMessage
{
public PubSubMessage (MetaData metaData, Stream body)
{this.metaData = metaData; this.body = body;}
namespace BCG {
// PubItems are published to the pubsub wrapped in this class. It contains PubMetaData, wrapped in the MetaData
// object and the actualy published payload in the body stream
public class PubSubMessage {
public PubSubMessage(MetaData metaData, Stream body) { this.meta_data = metaData; this.body = body; }
public PubSubMessage (MetaData metaData)
{this.metaData = metaData;}
public PubSubMessage(PubMetaData pub_meta_data, Stream body)
: this(new MetaData(pub_meta_data), body) { }
public MetaData metaData;
public PubSubMessage(MetaData metaData) { this.meta_data = metaData; }
public MetaData meta_data;
public Stream body = new MemoryStream(0);
public Stream toStream()
{
public Stream to_stream() {
MemoryStream ms = new MemoryStream();
metaData.save(ms);
if (body.Length == 0 || body.Length == body.Position)
meta_data.save(ms);
if (body.Length == 0 || body.Length == body.Position) {
bts.Log.Gen.error("Error: Trying to publishing message with no content.");
Console.WriteLine("Error: Trying to publishing message with no content.");
}
StreamUtilityMethods.copyTo(new Stream[] { body }, ms);
ms.Position = 0;
return ms;
}
public byte[] to_bytes() {
return StreamUtilityMethods.getBytesFromStream(to_stream());
}
public override string ToString() {
return $"PubSubMessage meta:data: {meta_data.ToString()} body.Posiiton: {body.Position} body.Length: {body.Length}";
}
}
}
+7 -8
View File
@@ -2,22 +2,21 @@ using System;
using System.Collections;
using System.IO;
namespace BCG
{
namespace BCG {
/// <summary>
/// this is the data returned from the
/// pubsub server
/// </summary>
public class PubSubUpdate
{
public PubSubUpdate(string tag, string tagType, Stream body)
{ this.tag = tag; this.body = body; this.tagType = tagType; }
public class PubSubUpdate {
public PubSubUpdate(string tag, string tagType, Stream body) { this.tag = tag; this.body = body; this.tagType = tagType; }
public string tag;
public Stream body;
public string tagType;
public override string ToString() {
return $"PubSubUpdate tag: {tag} tag_type: {tagType} len: {body.Position}";
}
};
}
+26 -130
View File
@@ -7,171 +7,67 @@ using System.Text.RegularExpressions;
using BCG.Utilities;
namespace BCG
{
public class PublisherCore : IPublisherCore
{
//private static BlueCommManaged.IPubSub myBCPS;
// TODO: what is this?
// public static void setPubSub(BlueCommManaged.IPubSub ps)
// {
// lock(typeof(PublisherCore))
// {
// BlueEventLog2.instance().assert(myBCPS == null,
// "PublisherCore.setPubSub() should be called only once and before any use of PublisherCore");
// myBCPS = ps;
// }
// }
namespace BCG {
public class PublisherCore : IPublisherCore {
public static string pubSubBlueCommPrefix = "ps/";
public static string pubSubBlueCommTransactionPrefix = "tgps/";
public static string pubSubBlueCommTransactionComponentPrefix = "tcps/";
// public static BlueCommManaged.IPubSub getPubSub()
// {
// lock (typeof(PublisherCore)) {
// return myBCPS;
// }
// }
enum Destination
{
enum Destination {
None,
BlueComm,
PubSub,
Both
}
//private IPublisherCore myBlueCommPublisher = null;
private IPublisherCore myPubSubPublisher = null;
private Dictionary<string, Destination> myPubDestinations =
new Dictionary<string, Destination>();
private IPublisherCore _publisher_core = null;
public PublisherCore()
{
myPubSubPublisher = new StaticPublisherCore();
//myBlueCommPublisher = new BlueCommPublisherCore(getPubSub());
public PublisherCore() {
_publisher_core = new StaticPublisherCore();
}
public PublisherCore(IPubSubRouter theRouter)
{
myPubSubPublisher = new StaticPublisherCore(theRouter);
//myBlueCommPublisher = new BlueCommPublisherCore(getPubSub());
public PublisherCore(IPubSubRouter theRouter) {
_publisher_core = new StaticPublisherCore(theRouter);
}
public PublisherCore(string URL)
{
myPubSubPublisher = new StaticPublisherCore(URL);
//myBlueCommPublisher = new BlueCommPublisherCore(getPubSub());
public PublisherCore(string URL) {
_publisher_core = new StaticPublisherCore(URL);
}
#region IPublisherCore Methods
public void Dispose()
{
myPubSubPublisher.Dispose();
//myBlueCommPublisher.Dispose();
public void Dispose() {
_publisher_core.Dispose();
}
public int getNumberOfWaitingMessages() { return myPubSubPublisher.getNumberOfWaitingMessages(); }
public int getNumberOfWaitingMessages() { return _publisher_core.getNumberOfWaitingMessages(); }
private Destination myGetPublishDestionation (string tag)
{
return Destination.PubSub;
// lock (this)
// {
// if (PubSub3Config.instance.BlueComm_mustDie)
// return Destination.PubSub;
// else
// {
// Destination d;
// return Destination.PubSub;
// if (myPubDestinations.TryGetValue(tag, out d))
// return d;
// else
// {
// foreach (string regexp in PubSub3Config.instance.BlueComm_PSTransition.tagsToPublishInPubSub)
// if (Regex.IsMatch(tag, regexp))
// {
// d = Destination.PubSub;
// foreach (string regexp2 in PubSub3Config.instance.BlueComm_PSTransition.exceptionsToTagsToPublishInPubSub)
// if (Regex.IsMatch(tag, regexp2))
// {
// d = Destination.None;
// break;
// }
// break;
// }
// if (!tag.StartsWith("mon"))
// foreach (string regexp in PubSub3Config.instance.BlueComm_PSTransition.tagsToPublishInBlueComm)
// if (Regex.IsMatch(tag, regexp))
// {
// if (d == Destination.PubSub)
// d = Destination.Both;
// else
// d = Destination.BlueComm;
// foreach (string regexp2 in PubSub3Config.instance.BlueComm_PSTransition.exceptionsToTagsToPublishInBlueComm)
// if (Regex.IsMatch(tag, regexp2))
// {
// if (d == Destination.Both)
// d = Destination.PubSub;
// else if (d == Destination.BlueComm)
// d = Destination.None;
// break;
// }
// break;
// }
// myPubDestinations[tag] = d;
// return d;
// }
// }
// }
}
public void publish(string tag, Stream content)
{
public void publish(string tag, Stream content) {
publish(tag, "", content);
}
public void publish(string tagType, string tag, Stream content)
{
Destination d = myGetPublishDestionation(tag);
if (d == Destination.PubSub || d == Destination.Both)
myPubSubPublisher.publish(tagType, tag, content);
if (d == Destination.BlueComm || d == Destination.Both){}
//myBlueCommPublisher.publish(tagType, tag, content);
public void publish(string tagType, string tag, Stream content) {
bts.Log.Gen.info($"PublisherCore.publish tag: {tag} stream.Length: {content.Length} stream.Position: {content.Position}");
_publisher_core.publish(tagType, tag, content);
}
public void beginTransaction()
{
myPubSubPublisher.beginTransaction();
//myBlueCommPublisher.beginTransaction();
public void beginTransaction() {
_publisher_core.beginTransaction();
}
public void commitTransaction()
{
myPubSubPublisher.commitTransaction();
//myBlueCommPublisher.commitTransaction();
public void commitTransaction() {
_publisher_core.commitTransaction();
}
public void abortTransaction()
{
myPubSubPublisher.abortTransaction();
//myBlueCommPublisher.abortTransaction();
public void abortTransaction() {
_publisher_core.abortTransaction();
}
public void clearState(string tagToClear)
{
Destination d = myGetPublishDestionation(tagToClear);
if (d == Destination.PubSub || d == Destination.Both)
myPubSubPublisher.clearState(tagToClear);
if (d == Destination.BlueComm || d == Destination.Both){}
//myBlueCommPublisher.clearState(tagToClear);
public void clearState(string tagToClear) {
_publisher_core.clearState(tagToClear);
}
public bool inTransaction
{ get { return myPubSubPublisher.inTransaction; } }
public bool inTransaction { get { return _publisher_core.inTransaction; } }
#endregion
@@ -3,27 +3,25 @@ using System.IO;
using System.Collections;
using BCG.Utilities;
namespace BCG
{
namespace BCG {
/// <summary>
/// Controls (ie creates dynamically) an IPubsubDeserializer based on the type name which is
/// part of the published data. Since its also a IPubsubDeserializer, all subsequent calls
/// are passed though to the interface
/// </summary>
public class PubsubDeserializationController : IPubsubDeserializer
{
public class PubsubDeserializationController : IPubsubDeserializer {
private IPubsubDeserializer myDeserializer;
public PubsubDeserializationController() { }
public void update(Stream stream)
{
public void update(Stream stream) {
bts.Log.Gen.info("PubsubDeserializationController.update stream: {stream.Position} / {stream.Length}");
byte[] ops;
Array rows;
deserialize(new Stream[] { stream }, out ops, out rows);
}
public void update(byte[] bytes)
{
public void update(byte[] bytes) {
bts.Log.Gen.info("PubsubDeserializationController.update bytes: {bytes.Length}");
byte[] ops;
Array rows;
deserialize(new Stream[] { new MemoryStream(bytes, 0, bytes.Length, false, true) }, out ops, out rows);
@@ -31,39 +29,36 @@ namespace BCG
#region IPubsubDeserializer Members
public void deserialize(Stream[] streams, out byte[] theOps, out Array theRows)
{
if (myDeserializer != null)
{
public void deserialize(Stream[] streams, out byte[] theOps, out Array theRows) {
if (myDeserializer != null) {
myDeserializer.deserialize(streams, out theOps, out theRows);
}
else
{
bts.Log.Gen.info($"PubsubDeserializationController.deserialize myDeserializer: {myDeserializer} ops: {theOps.Length} theRows: {theRows.Length}");
} else {
Stream totalStream = UtilityMethods.getAggregatedStream(streams);
long initialPos = totalStream.Position;
BinaryReader br = new BinaryReader(totalStream);
byte opCode = br.ReadByte();
if (opCode == StreamOpCode.create)
{
bts.Log.Gen.info($"PubsubDeserializationController.deserialize opCode: {opCode}");
if (opCode == StreamOpCode.create) {
string deserName = br.ReadString();
if (deserName == "BCG.PubsubUniversalDeserializer") // so we can play old replay files which would not include the assembly name
deserName = "BCG.PubsubUniversalDeserializer, DataStreamGateway";
myDeserializer = Activator.CreateInstance(Type.GetType(deserName))
as IPubsubDeserializer;
// TODOds
if (deserName == "BCG.PubsubUniversalDeserializer, DataStreamGateway") // so we can play old replay files which would not include the assembly name
deserName = "BCG.PubsubUniversalDeserializer, DataStreamCore";
myDeserializer = Activator.CreateInstance(Type.GetType(deserName)) as IPubsubDeserializer;
totalStream.Position = initialPos;
myDeserializer.deserialize(new Stream[] { totalStream }, out theOps, out theRows);
}
else
{
// BlueEventLog.logEvent("Received a non create before a create. Bad op code was " + opCode.ToString(), BlueEventLevel.Warning);
bts.Log.Gen.info($"PubsubDeserializationController.deserialize myDeserializer: {myDeserializer} ops: {theOps.Length} theRows: {theRows.Length}");
} else {
bts.Log.Gen.error($"Received a non create before a create. Bad op code was : {opCode} ");
theOps = new byte[] { };
theRows = new object[] { };
}
}
}
public byte[] getState()
{
public byte[] getState() {
return myDeserializer == null ? new byte[] { } : myDeserializer.getState();
}
@@ -9,17 +9,14 @@ using System.IO;
using System.Diagnostics;
using mbts;
namespace BCG
{
namespace BCG {
public class ManagedTCPMessageHub : IPubsubMessageHub,
ITCPConnectionHandler,
ITCPMessageHandler
{
ITCPMessageHandler {
private int myPort;
private bool myIsDisposed = false;
public int port
{
public int port {
get { return myPort; }
//property is read only
@@ -66,8 +63,7 @@ namespace BCG
private DateTime myLastHeartbeatDeadCollectionTime = DateTime.Now;
private DateTime myLastDisposedDeadCollectionTime = DateTime.Now;
public ManagedTCPMessageHub(int port, TimeSpan hbSendInterval, int missingHBsForGC, TimeSpan collectDisposedConnectionsPeriod)
{
public ManagedTCPMessageHub(int port, TimeSpan hbSendInterval, int missingHBsForGC, TimeSpan collectDisposedConnectionsPeriod) {
myPort = port;
myHeartbeatSendInterval = hbSendInterval;
mySubscriberDropThreshold = new TimeSpan(0, 0, 0, 0, Convert.ToInt32(hbSendInterval.TotalMilliseconds * missingHBsForGC));
@@ -81,24 +77,21 @@ namespace BCG
#region IPubsubMessageHub Members
public void registerDataCallback(DataDelegate del)
{
public void registerDataCallback(DataDelegate del) {
// BlueEventLog.logAssert(!myActivated, "connection callbacks should be registered before the call to activate");
myDataCb = del;
}
public void registerConnectionCallback(ConnectionStatusChange del)
{
public void registerConnectionCallback(ConnectionStatusChange del) {
//BlueEventLog.logAssert(!myActivated, "data callbacks should be registered before the call to activate");
myConnCb = del;
}
public void activate()
{
public void activate() {
if (PubSub3Config.instance.PS3_BindToRandomPort || myPort == 0)
myPort = ServerToClientManagedTCPConnectionAcceptor.activateWithRandomPort(this, myHeartbeatSendInterval);
else
myPort = ServerToClientManagedTCPConnectionAcceptor.activate(this, myPort, myHeartbeatSendInterval);
myPort = ServerToClientManagedTCPConnectionAcceptor.accept_connections(this, myPort, myHeartbeatSendInterval);
string msg = String.Format("TCP Component is ready, listening on port {0} for incoming connections", myPort);
Console.WriteLine(msg);
@@ -108,19 +101,16 @@ namespace BCG
doItAllThread.Start();
}
public List<Pair<string, byte[]>> getUpdates(TimeSpan timeout, int maxElements)
{
public List<Pair<string, byte[]>> getUpdates(TimeSpan timeout, int maxElements) {
return myReceivedData.dequeueMultipleElements(timeout, maxElements);
}
public bool send(string receiver, byte[] data)
{
public bool send(string receiver, byte[] data) {
mySendData.enqueue(new Pair<string, byte[]>(receiver, data));
return true;
}
public bool send(string receiver, System.IO.Stream str)
{
public bool send(string receiver, System.IO.Stream str) {
BinaryReader br = new BinaryReader(str);
return send(receiver, br.ReadBytes(Convert.ToInt32(str.Length - str.Position)));
}
@@ -133,17 +123,13 @@ namespace BCG
/// Reports back connected and disconnected connections
/// via the ConnectionStatucChange callback
/// </summary>
public void doWork()
{
if (myConnCb != null)
{
foreach (string nc in myNewConnectionURLs.dequeueAll())
{
public void doWork() {
if (myConnCb != null) {
foreach (string nc in myNewConnectionURLs.dequeueAll()) {
//BlueEventLog.logEvent(String.Format("doWork : New client {0} connected, making connection callback", nc), PS3LogLevels.connection);
myConnCb(nc, true);
}
foreach (string dc in myDeadConnectionURLs.dequeueAll())
{
foreach (string dc in myDeadConnectionURLs.dequeueAll()) {
//BlueEventLog.logEvent(String.Format("doWork : Client {0} disconnected, making disconnection callback", dc), PS3LogLevels.disconnection);
myConnCb(dc, false);
}
@@ -160,8 +146,7 @@ namespace BCG
/// stored in the hashtable and used for later communication)
/// </summary>
/// <param name="connection"></param>
public void onConnection(ITCPConnection connection)
{
public void onConnection(ITCPConnection connection) {
myNewConnections.enqueue(connection);
}
@@ -169,48 +154,38 @@ namespace BCG
#region ITCPMessageHandler Members
public void onData(RemoteMessage message)
{
public void onData(RemoteMessage message) {
Console.WriteLine("ManagedTCPMessgageHub.onData recv msg :" + message.remoteConnectionInfo.ToString());
string sender = new BlutoSubAddress(message.remoteConnectionInfo.ip, message.remoteConnectionInfo.port).ToString();
if (message.messageType == RemoteMessageType.data)
{
if (message.messageType == RemoteMessageType.Data) {
if (myDataCb != null)
myDataCb(sender, message.message);
else
myReceivedData.enqueue(new Pair<string, byte[]>(sender, message.message));
}
else if (message.messageType == RemoteMessageType.heartbeat)
} else if (message.messageType == RemoteMessageType.Heartbeat)
myReceivedHeartbeats.enqueue(sender);
else
{
else {
//BlueEventLog.logEvent("Unknown message type from the client", BlueEventLevel.Error);
}
}
#endregion
class TimmingInfo
{
public TimmingInfo()
{
class TimmingInfo {
public TimmingInfo() {
myTimer = new Stopwatch();
reset();
}
public void start()
{
if (PubSub3Config.instance.PS3_DoItAllSecondsBetweenLogs > 0)
{
public void start() {
if (PubSub3Config.instance.PS3_DoItAllSecondsBetweenLogs > 0) {
myTimer.Reset();
myTimer.Start();
}
}
public void stop()
{
if (PubSub3Config.instance.PS3_DoItAllSecondsBetweenLogs > 0)
{
public void stop() {
if (PubSub3Config.instance.PS3_DoItAllSecondsBetweenLogs > 0) {
myTimer.Stop();
myMin = Math.Min(myMin, myTimer.ElapsedMilliseconds);
myMax = Math.Max(myMax, myTimer.ElapsedMilliseconds);
@@ -219,16 +194,14 @@ namespace BCG
}
}
public void reset()
{
public void reset() {
myMin = Double.MaxValue;
myMax = Double.MinValue;
myTotal = 0;
myNMeasurements = 0;
}
public override string ToString()
{
public override string ToString() {
if (myNMeasurements > 0)
return String.Format("min={0} max={1} avg={2} nMeasurements={3}", myMin, myMax, myTotal / myNMeasurements, myNMeasurements);
else
@@ -242,8 +215,7 @@ namespace BCG
private double myTotal;
}
private void myDoItAll()
{
private void myDoItAll() {
Dictionary<string, TimmingInfo> times = new Dictionary<string, TimmingInfo>();
times.Add("myHandleNewConnections", new TimmingInfo());
times.Add("myCollectDisposedConnections", new TimmingInfo());
@@ -252,12 +224,9 @@ namespace BCG
DateTime lastTimmingLog = DateTime.Now;
while (true)
{
try
{
while (true)
{
while (true) {
try {
while (true) {
///new connections
times["myHandleNewConnections"].start();
myHandleNewConnections();
@@ -279,16 +248,12 @@ namespace BCG
Pair<string, byte[]> p = mySendData.dequeue(myReadSendQueueTimeout);
times["send"].start();
if (p != null)
{
if (p != null) {
ITCPConnection conn;
myConnections.TryGetValue(p.first, out conn);
if (conn != null)
{
if (conn != null) {
conn.send(p.second);
}
else
{
} else {
string warningMsg = String.Format("sending data to {0} failed, this client might have " +
"disconnected, in which case it will be garbage collected within 60 secs", p.first);
//BlueEventLog.logEvent(warningMsg, PS3LogLevels.disconnection);
@@ -297,25 +262,21 @@ namespace BCG
times["send"].stop();
if (PubSub3Config.instance.PS3_DoItAllSecondsBetweenLogs > 0 &&
(DateTime.Now - lastTimmingLog).TotalSeconds > PubSub3Config.instance.PS3_DoItAllSecondsBetweenLogs)
{
(DateTime.Now - lastTimmingLog).TotalSeconds > PubSub3Config.instance.PS3_DoItAllSecondsBetweenLogs) {
lastTimmingLog = DateTime.Now;
StringBuilder b = new StringBuilder();
b.AppendFormat("myDoItAll stats:\n");
b.AppendFormat("queue size: {0}\n", mySendData.getCount());
foreach (string timerName in times.Keys)
{
foreach (string timerName in times.Keys) {
b.AppendFormat("{0}: {1}\n", timerName, times[timerName]);
times[timerName].reset();
}
//BlueEventLog.logEvent(b.ToString(), PS3LogLevels.performance);
}
}
}
catch (Exception ex)
{
} catch (Exception ex) {
//BlueEventLog.logEvent(ex);
if (ex is OutOfMemoryException)
throw ex;
@@ -323,19 +284,15 @@ namespace BCG
}
}
private void myCollectDisposedConnections()
{
if (DateTime.Now - myLastDisposedDeadCollectionTime > myCollectDisposedConnectionsPeriod)
{
private void myCollectDisposedConnections() {
if (DateTime.Now - myLastDisposedDeadCollectionTime > myCollectDisposedConnectionsPeriod) {
myLastDisposedDeadCollectionTime = DateTime.Now;
List<string> disposedURLs = new List<string>();
foreach (KeyValuePair<string, ITCPConnection> p in myConnections)
{
foreach (KeyValuePair<string, ITCPConnection> p in myConnections) {
if (p.Value.isDisposed)
disposedURLs.Add(p.Key);
}
foreach (string url in disposedURLs)
{
foreach (string url in disposedURLs) {
string disposeMsg = String.Format("Collecting disposed connections : {0} is disposed by the connection itself, " +
"connection count before deleting this = {1}", url, myConnections.Count);
Console.WriteLine(disposeMsg);
@@ -346,10 +303,9 @@ namespace BCG
}
}
private void myCollectMissingHeartbeatConnections()
{
if (DateTime.Now - myLastHeartbeatDeadCollectionTime > mySubscriberDropThreshold)
{
private void myCollectMissingHeartbeatConnections() {
return; // disabling HBs for now to simplify things for the demo
if (DateTime.Now - myLastHeartbeatDeadCollectionTime > mySubscriberDropThreshold) {
myLastHeartbeatDeadCollectionTime = DateTime.Now;
///these are all the hbs received bw the last
///and current collectDeadConnection calls
@@ -365,12 +321,10 @@ namespace BCG
foreach (string clientURL in myConnections.Keys)
if (!indexedHbs.ContainsKey(clientURL))
deadClients.Add(clientURL);
foreach (string deadClient in deadClients)
{
string disposeMsg = String.Format("Collecting missing HB connections : {0} is dead due to missing hbs, Disposing it now, " +
"connection count before deleting this = {1}", deadClient, myConnections.Count);
//BlueEventLog.logEvent(disposeMsg, PS3LogLevels.disconnection);
Console.WriteLine(disposeMsg);
foreach (string deadClient in deadClients) {
string dispose_msg = String.Format("Collecting missing HB connections : {0} is dead due to missing hbs, Disposing it now, " +
"connection count before deleting this = {1}", deadClient, myConnections.Count);
bts.Log.Gen.error(dispose_msg);
myConnections[deadClient].Dispose();
myConnections.Remove(deadClient);
myDeadConnectionURLs.enqueue(deadClient);
@@ -378,11 +332,9 @@ namespace BCG
}
}
private void myHandleNewConnections()
{
private void myHandleNewConnections() {
IList<ITCPConnection> newConns = myNewConnections.dequeueAll();
foreach (ITCPConnection conn in newConns)
{
foreach (ITCPConnection conn in newConns) {
string ip;
int port;
conn.getPeerAddress(out ip, out port);
@@ -399,13 +351,11 @@ namespace BCG
}
#region IDisposable Memebers
public void Dispose()
{
public void Dispose() {
myIsDisposed = true;
}
public bool isDisposed
{
public bool isDisposed {
get { return myIsDisposed; }
}
#endregion
@@ -4,23 +4,20 @@ using System.Text;
using BCG.Utilities.General;
using System.IO;
namespace BCG
{
namespace BCG {
/// <summary>
/// Periodicaly publishes a heartbeat, under the tag name System_Heartbeat.
/// A subscriber can subscribe to it, and find out of a PubSub is alive or
/// not. Infact more so, if the subsriptions are working or not.
/// </summary>
internal class SystemHeartbeatPublisher : IWorker
{
internal class SystemHeartbeatPublisher : IWorker {
public static string tagType = "System_Heartbeat";
public static string tagName = "System_Heartbeat";
private static SystemHeartbeatPublisher mySelf;
private SystemHeartbeatPublisher ()
{
private SystemHeartbeatPublisher() {
///this is using a multithreaded MasterWorker since the
///regular one is called within the MessageReactor, which
///waits 2500 msecs before calling doWork. This 2500 msecs
@@ -29,16 +26,14 @@ namespace BCG
MasterWorker.getInstance(true).addWorker(this, new TimeSpan(0, 0, 0, 0, 500));
}
public static void init()
{
public static void init() {
if (mySelf == null)
mySelf = new SystemHeartbeatPublisher();
}
#region IWorker Members
public void doWork()
{
public void doWork() {
PubMetaData pub = new PubMetaData(tagType, tagName, 1, "local", ClientInfo.thisClient.processString);
MetaData md = new MetaData(pub);
MemoryStream ms = new MemoryStream();
@@ -16,10 +16,8 @@ using System.Collections.Generic;
using mbts;
using mbts.spark;
namespace BCG
{
public class PubSubMessageReactor
{
namespace BCG {
public class PubSubMessageReactor {
private ServerMessageHub myMessageHub;
private delegate void MyMsgHandler(string sender, Stream msg, MetaData m);
private Dictionary<string, MyMsgHandler> myOperationToHandler = new Dictionary<string, MyMsgHandler>();
@@ -39,32 +37,24 @@ namespace BCG
/* This delegate allows pubsub components to be notified when the identity of the pubsub is known*/
public delegate void IdentityFoundDelegate(string identity, bool isRoot);
public event IdentityFoundDelegate onIdentityFound;
public void fireIdentityFound(string identity, bool isRoot)
{
public void fireIdentityFound(string identity, bool isRoot) {
if (onIdentityFound != null)
onIdentityFound(identity, isRoot);
}
private IPubSubGovernor myGovernor;
public Dictionary<string, bool> myTagCompressionState = new Dictionary<string, bool>();
public PubSubMessageReactor() : this(false, false, string.Empty, string.Empty) { }
public PubSubMessageReactor(string q) : this(false, false, string.Empty, q) { }
public PubSubMessageReactor(bool clearQueue, bool bootEvent, string oldIP, string psq)
{
public PubSubMessageReactor(bool clearQueue, bool bootEvent, string oldIP, string psq) {
myOperationToHandler.Add(typeof(PubMetaData).Name, new MyMsgHandler(myHandlePub));
myOperationToHandler.Add(typeof(SubMetaData).Name, new MyMsgHandler(myHandleSub));
myOperationToHandler.Add(typeof(UnSubMetaData).Name, new MyMsgHandler(myHandleUnsub));
myOperationToHandler.Add(typeof(TransactionMetaData).Name, new MyMsgHandler(myHandleTransaction));
// TODO, governor needs to be removed since its subststaion retired code
// if (PubSub3Config.instance.PS3_Components.governor != null)
// myGovernor = PubSubComponentFactory.buildGovernor(this);
//BlueEventLog.logEvent("System Initialized", PS3LogLevels.info);
bts.Log.Gen.info("PubSubMessageReactor.cons System Initialized");
myReceivingProcThread = new Thread(new ThreadStart(myReceivingThreadProc));
myMessageHub = ServerMessageHub.instance;
@@ -75,93 +65,49 @@ namespace BCG
#region message handlers
public PubSubState state
{
public PubSubState state {
get { return myState; }
//this variable is read only
}
private void myHandlePub(string sender, Stream msg, MetaData m)
{
// all publishes to the pubsub end here
private void myHandlePub(string sender, Stream msg_str, MetaData meta_data) {
bts.Log.Gen.info($"PubSubMessageReactor.myHandlePub sender: {sender} metadata: {meta_data} str.pos: {msg_str.Position} str.len: {msg_str.Length}");
mySingleTagTimeSliceTimer.start();
///the position in the stream is set to where the data starts with,
///since the meta data was already read in the myProcessMsg
PubMetaData pub = new PubMetaData();
m.copyTo(pub);
meta_data.copyTo(pub);
pub.connection = sender;
Console.WriteLine("PubSubMessageReactor.myHandlePub sender: " + sender + " tag: " + pub.tag);
//check to see if this publish took a while to get here
pub.warnIfLatencyExceedsThreshold();
//check the governor to see if this publish is allowed, if we have a governor
PubSubGovernorResponse response = PubSubGovernorResponse.Accepted;
if (myGovernor != null)
response = myGovernor.requestToPublish(pub, msg);
if (response != PubSubGovernorResponse.Accepted)
{
// BlueEventLog2.instance().logEvent(string.Concat("PubSub Governor ",
// myGovernor.GetType().Name,
// " returned response ",
// response.ToString(),
// " publish on tag",
// pub.tag,
// "was ignored."), BlueEventLog2Level.Warning);
return;
}
//report the fact that we have a publish on this tag, if it's a debug tag
if (PubSub3Config.instance.isTagDebugTag(pub.tag))
{
// BlueEventLog.logEvent(string.Concat(GetType().Name,
// " got publish on tag ",
// pub.tag,
// " from app ", pub.publishingApp,
// " over connection ",
// pub.connection, ".\n",
// pub.isCompressed ? "Data was compressed.\n" : "Data was not compresed.\n",
// "total size: ",
// pub.size),
// PS3LogLevels.debug);
}
var subs_for_tag = myState.getSubscriberConnectionsForTag(pub.tag);
bts.Log.Gen.info($"PubSubMessageReactor.myHandlePub {subs_for_tag.Count} subs for tag: {pub.tag}");
///for all the subscribers, sends the messages over straightaway
foreach (string address in myState.getSubscriberConnectionsForTag(pub.tag))
{
foreach (string address in myState.getSubscriberConnectionsForTag(pub.tag)) {
///the position is adjusted to zero, so as to include
///the meta data as part of the message
msg.Position = 0;
myMessageHub.send(address, msg);
msg_str.Position = 0;
bts.Log.Gen.info($"PubSubMessageReactor.myHandlePub sending tag: {pub.tag} to {address} len: {msg_str.Length - msg_str.Position}");
myMessageHub.send(address, msg_str);
}
//reset the position of the message so we can decompress it appropriately
msg.Position = 0;
msg.Position = m.size();
msg_str.Position = 0;
msg_str.Position = meta_data.size();
if (pub.isCompressed)
{
long mdLength = msg.Position;
long compressedSize = msg.Length - mdLength;
if (compressedSize == 0)
{
if (pub.isCompressed) {
long mdLength = msg_str.Position;
long compressedSize = msg_str.Length - mdLength;
if (compressedSize == 0) {
string errorMsg = "Error: tag " + pub.tag + " had compressed size of 0 bytes. This shouldnt' happen. Not decompressing tag or sending out update.";
//BlueEventLog.logEvent(errorMsg, BlueEventLevel.Error);
bts.Log.Gen.error(errorMsg);
return;
}
msg = StreamDecompressor.decompressStream(msg);
long decompressedSize = msg.Length - mdLength;
if (decompressedSize != pub.decompressedSize || compressedSize != pub.size)
{
msg_str = StreamDecompressor.decompressStream(msg_str);
long decompressedSize = msg_str.Length - mdLength;
if (decompressedSize != pub.decompressedSize || compressedSize != pub.size) {
string compressionWarning = string.Format("Warning: Stream for tag {0} decompressed from {1} to {2} bytes, with {3} byes of metadata. Metadata expected {4} to {5}. Tag state not updated.",
pub.tag,
compressedSize,
@@ -169,43 +115,30 @@ namespace BCG
mdLength,
pub.size,
pub.decompressedSize);
//BlueEventLog.logEvent(compressionWarning, BlueEventLevel.Error);
bts.Log.Gen.warn(compressionWarning);
return;
}
}
//give the user a notification of the compression status of the tag has changed.
if ((!(myTagCompressionState.ContainsKey(pub.tag)) ||
myTagCompressionState[pub.tag] != pub.isCompressed))
{
myTagCompressionState[pub.tag] != pub.isCompressed)) {
string compressionMessage;
myTagCompressionState[pub.tag] = pub.isCompressed;
if (pub.isCompressed)
{
if (pub.isCompressed) {
compressionMessage = "Tag " + pub.tag + " is compressed.";
//BlueEventLog.logEvent(compressionMessage, PS3LogLevels.compressionRatio);
}
else
{
} else {
compressionMessage = "Tag " + pub.tag + " is not compressed.";
//BlueEventLog.logEvent(compressionMessage, PS3LogLevels.compressionRatio);
}
}
///updating state
msg.Position = 0;
msg.Position += m.size();
myState.updatePubData(pub, msg);
msg_str.Position = 0;
msg_str.Position += meta_data.size();
myState.updatePubData(pub, msg_str);
mySingleTagTimeSliceTimer.stop();
double thisTagProcessingTime = mySingleTagTimeSliceTimer.lastIntervalTime;
if (onSingleTagPub != null)
onSingleTagPub(pub.tag, thisTagProcessingTime);
@@ -213,8 +146,8 @@ namespace BCG
}
private void myHandleSub(string sender, Stream msg, MetaData m)
{
private void myHandleSub(string sender, Stream msg, MetaData m) {
bts.Log.Gen.info($"PubSubMessageReactor.myHandleSub sender: {sender} metadata: {m} str.pos: {msg.Position} str.len: {msg.Length}");
SubMetaData sub = new SubMetaData();
m.copyTo(sub);
sub.connection = sender;
@@ -222,12 +155,10 @@ namespace BCG
///update the state
myState.sub(sub);
///to all these new subscriber s, send the existing data
foreach (string tag in sub.tags)
{
foreach (string tag in sub.tags) {
byte[] data = myState.getContent(tag);
//ie data has been published once
if (data != null)
{
if (data != null) {
string tagType = myState.getTagType(tag);
///passing "" as the 4th arg, as PubMeta is used both by the
///publisher to publish data to the server (where the publisher
@@ -237,17 +168,14 @@ namespace BCG
///needed as of now, so its left black to save a few bytes
PubMetaData pub;
MemoryStream realContent;
if (PubSub3Config.instance.isTagCompressed(tag))
{
if (PubSub3Config.instance.isTagCompressed(tag)) {
SharpZipCompressor Kompessor = new SharpZipCompressor();
realContent = new MemoryStream();
Kompessor.compress(new MemoryStream(data), realContent);
pub = new PubMetaData(tagType, tag, (int)realContent.Length, (int)data.Length, "", "");
}
else
{
} else {
realContent = new MemoryStream(data);
pub = new PubMetaData(tagType, tag, data.Length, "", "");
}
@@ -262,8 +190,7 @@ namespace BCG
}
}
private void myHandleUnsub(string sender, Stream msg, MetaData m)
{
private void myHandleUnsub(string sender, Stream msg, MetaData m) {
UnSubMetaData unsub = new UnSubMetaData();
m.copyTo(unsub);
if (unsub.connection.Trim().Length == 0)
@@ -271,8 +198,7 @@ namespace BCG
myState.unsub(unsub);
}
private void myHandleTransaction(string sender, Stream msg, MetaData md)
{
private void myHandleTransaction(string sender, Stream msg, MetaData md) {
mySingleTagTimeSliceTimer.start();
TransactionMetaData t = new TransactionMetaData();
md.copyTo(t);
@@ -280,8 +206,7 @@ namespace BCG
///form the structure tag->byte[]*
Dictionary<string, byte[]> tagToMessages = new Dictionary<string, byte[]>();
BinaryReader br = new BinaryReader(msg);
for (int i = 0; i < nMessages; i++)
{
for (int i = 0; i < nMessages; i++) {
MetaData pubMd = new MetaData(msg);
PubMetaData pub = new PubMetaData();
pubMd.copyTo(pub);
@@ -289,8 +214,7 @@ namespace BCG
byte[] tagData = new byte[pub.size];
msg.Read(tagData, 0, tagData.Length);
//report the fact that we have a publish on this tag, if it's a debug tag
if (PubSub3Config.instance.isTagDebugTag(pub.tag))
{
if (PubSub3Config.instance.isTagDebugTag(pub.tag)) {
// BlueEventLog.logEvent(string.Concat(GetType().Name,
// " got publish on tag ",
// pub.tag,
@@ -315,13 +239,11 @@ namespace BCG
}
///this gives subscriber->tag*
Dictionary<string, List<string>> subscriberToTags = myState.getSubscriberConnectionsForTags(tagToMessages.Keys);
foreach (KeyValuePair<string, List<string>> kvp in subscriberToTags)
{
foreach (KeyValuePair<string, List<string>> kvp in subscriberToTags) {
MemoryStream subStream = new MemoryStream();
TransactionMetaData subTransaction = new TransactionMetaData(kvp.Value.Count);
new MetaData(subTransaction).save(subStream);
foreach (string tag in kvp.Value)
{
foreach (string tag in kvp.Value) {
byte[] tagData = tagToMessages[tag];
PubMetaData pub = new PubMetaData(myState.getTagType(tag), tag, tagData.Length, "", "");
new MetaData(pub).save(subStream);
@@ -336,8 +258,7 @@ namespace BCG
double timeExpended = mySingleTagTimeSliceTimer.lastIntervalTime;
//Don't try to divide by zero
int numTags = tagToMessages.Keys.Count;
if (numTags != 0)
{
if (numTags != 0) {
double timeExpendedPerTag = timeExpended / tagToMessages.Keys.Count;
if (onSingleTagPub != null)
foreach (string tag in tagToMessages.Keys)
@@ -351,18 +272,16 @@ namespace BCG
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
private void myProcessMsg(string sender, Stream msg, out MetaData md)
{
md = new MetaData(msg);
private void myProcessMsg(string sender, Stream msg, out MetaData md) {
md = new MetaData(msg); // msg's Posiiton moved to end of meta data
MyMsgHandler op = myOperationToHandler[md["op-code"]];
//BlueEventLog.logEvent(string.Format("process message {0}", m));
bts.Log.Gen.info($"PubSubMessageReactor.myProcessMsg sender: {sender} metadata: {md}");
op(sender, msg, md);
}
#endregion
private void myHandleConnections(string client, bool connected)
{
private void myHandleConnections(string client, bool connected) {
Console.WriteLine("PubSubMessageReactor.myHandleConnections client: " + client + " connected: " + connected);
///interested in disconnections only, as connections of no
///significance until they subscribe, in which case an entry
@@ -371,13 +290,11 @@ namespace BCG
myState.removeConnection(client);
}
public void stop()
{
public void stop() {
myStop = true;
}
public void start()
{
public void start() {
myReceivingProcThread.Start();
}
@@ -385,8 +302,7 @@ namespace BCG
/// loops around and reads messages from the messageReceiver. calls processMsg
/// passing in the IClientMessage. also logs stuff about the message.
/// </summary>
private void myReceivingThreadProc()
{
private void myReceivingThreadProc() {
TimeSpan receiveTimeout = new TimeSpan(0, 0, 0, 0, 2500);
myMessageHub.activate();
@@ -398,31 +314,25 @@ namespace BCG
string sender;
Stream msg;
MetaData meta;
while (!myStop)
{
while (!myStop) {
sender = null;
msg = null;
meta = null;
try
{
try {
List<Pair<string, byte[]>> receivedData = myMessageHub.getUpdates(receiveTimeout, 1);
if (receivedData.Count > 0)
{
if (receivedData.Count > 0) {
sender = receivedData[0].first;
msg = new MemoryStream(receivedData[0].second);
myTimer.start();
myProcessMsg(sender, msg, out meta);
myTimer.stop();
if (myTimer.lastIntervalTime > myProcessingWarningThreshold)
{
if (myTimer.lastIntervalTime > myProcessingWarningThreshold) {
string warningMsg = String.Format("processing metadata {0} took {1} msecs", meta, myTimer.lastIntervalTime);
//BlueEventLog.logEvent(warningMsg, PS3LogLevels.performance);
}
}
myMasterWorker.doWork();
}
catch (Exception e)
{
} catch (Exception e) {
//BlueEventLog.logEvent(e, BlueEventLevel.Error);
Console.WriteLine("{0} : exception handling message: {1}\n", DateTime.Now, e.Message);
string errMsg = String.Format("Following information about the meta data and sender is available : " +
@@ -7,21 +7,19 @@ using System.IO;
using mbts;
namespace BCG
{
namespace BCG {
/// <summary>
/// Mantains all the state that there is in the server.
/// This information is keyed off the tags (rather than
/// keyed off subscribers or publishers)
/// State information consists of 2 distints sets :
/// State information consists of 2 distinct sets :
/// myTagToData consists of all the data published to
/// this pubsub.
/// myTagToTagInfo consists of all the subscription and
/// publishing information
/// </summary>
///
public class PubSubState
{
public class PubSubState {
public delegate void PubSubStateSingleTagChangeDelegate(PubSubSingleTagStateEvent theEvent);
public event PubSubStateSingleTagChangeDelegate onSingleTagChange;
@@ -33,8 +31,7 @@ namespace BCG
private Dictionary<string, SingleTagData> myTagToData = new Dictionary<string, SingleTagData>();
private Dictionary<string, SingleTagPubSubMap> myTagToPubsubMap = new Dictionary<string, SingleTagPubSubMap>();
public PubSubState()
{
public PubSubState() {
SystemSubscriptionMapPublisher.init(this);
SystemStatsPublisher.init(this);
SystemHeartbeatPublisher.init();
@@ -49,13 +46,10 @@ namespace BCG
/// </summary>
/// <param name="sub"></param>
/// <param name="md"></param>
public void sub(SubMetaData sub)
{
public void sub(SubMetaData sub) {
///tag based key ds update
foreach (string tag in sub.tags)
{
if (!myTagToPubsubMap.ContainsKey(tag))
{
foreach (string tag in sub.tags) {
if (!myTagToPubsubMap.ContainsKey(tag)) {
myTagToPubsubMap.Add(tag, new SingleTagPubSubMap(tag));
}
myTagToPubsubMap[tag].onSub(sub);
@@ -67,20 +61,15 @@ namespace BCG
onTagMapChanged(sub.tags);
}
public void unsub(UnSubMetaData unsub)
{
foreach (string tag in unsub.tags)
{
if (myTagToPubsubMap.ContainsKey(tag))
{
public void unsub(UnSubMetaData unsub) {
foreach (string tag in unsub.tags) {
if (myTagToPubsubMap.ContainsKey(tag)) {
///maybe check here, that if there are no subscribers
///and publishers for the tag then remove it.
myTagToPubsubMap[tag].onUnsub(unsub);
if (onSingleTagChange != null)
onSingleTagChange(new PubSubSingleTagStateEvent(tag, PubSubSingleTagStateEvent.EventType.unsubscription, unsub.connection, unsub.unsubscribingApp));
}
else
{
} else {
string warningMsg = String.Format("{0} was never published or subscribed on this pubsub, hence" +
" the unsub call by app {1} is voided", tag, unsub.unsubscribingApp);
//BlueEventLog.logEvent(warningMsg, BlueEventLevel.Warning);
@@ -90,11 +79,9 @@ namespace BCG
onTagMapChanged(unsub.tags);
}
public void removeConnection(string connection)
{
public void removeConnection(string connection) {
List<string> tagsEffected = new List<string>();
foreach (KeyValuePair<string, SingleTagPubSubMap> p in myTagToPubsubMap)
{
foreach (KeyValuePair<string, SingleTagPubSubMap> p in myTagToPubsubMap) {
///maybe check here, that if there are no subscribers
///and publishers for the tag then remove it.
bool wasPublisher = false;
@@ -103,8 +90,7 @@ namespace BCG
if (p.Value.onConnectionRemoveIfExists(connection, out wasPublisher, out wasSubscriber))
tagsEffected.Add(tag);
if (onSingleTagChange != null)
{
if (onSingleTagChange != null) {
//we don't know the app or key qualifier or anything for these connection. that is unfortunate.
if (wasPublisher)
onSingleTagChange(new PubSubSingleTagStateEvent(tag, PubSubSingleTagStateEvent.EventType.publisherDie, connection, ""));
@@ -128,67 +114,60 @@ namespace BCG
/// </summary>
/// <param name="tag"></param>
/// <param name="msg"></param>
public void updatePubData(PubMetaData pub, Stream msg)
{
public void updatePubData(PubMetaData pub, Stream msg) {
int sz = (int)(msg.Length - msg.Position);
bts.Log.Gen.info($"PubSubData.updatePubData pub: msg : {msg.Position} / {msg.Length} sz: {sz}");
///this is the only place where SingleTagData should be created
if (!myTagToData.ContainsKey(pub.tag))
{
if (!myTagToData.ContainsKey(pub.tag)) {
///first time data is published for this tag
myTagToData.Add(pub.tag, new SingleTagData(pub.tag, pub.type));
}
myTagToData[pub.tag].pubUpdate(msg);
if (!myTagToPubsubMap.ContainsKey(pub.tag))
{
if (!myTagToPubsubMap.ContainsKey(pub.tag)) {
myTagToPubsubMap.Add(pub.tag, new SingleTagPubSubMap(pub.tag));
}
bool pubChanged = false;
myTagToPubsubMap[pub.tag].onPub(pub, out pubChanged);
if (pubChanged)
{
if (pubChanged) {
if (onTagMapChanged != null)
onTagMapChanged(new string[] { pub.tag });
if (onSingleTagChange != null)
onSingleTagChange(
new PubSubSingleTagStateEvent(pub.tag,
PubSubSingleTagStateEvent.EventType.publish,
new PubSubSingleTagStateEvent(pub.tag,
PubSubSingleTagStateEvent.EventType.publish,
pub.connection, pub.publishingApp));
}
if (onPublishStats != null)
onPublishStats(pub.tag, sz);
}
#endregion
public ICollection<string> getSubscriberConnectionsForTag(string tag)
{
public ICollection<string> getSubscriberConnectionsForTag(string tag) {
if (myTagToPubsubMap.ContainsKey(tag))
return myTagToPubsubMap[tag].subscriberConnections;
else
return new string[] { };
}
public ICollection<string> getSubscribingAppsForTag(string tag)
{
public ICollection<string> getSubscribingAppsForTag(string tag) {
if (myTagToPubsubMap.ContainsKey(tag))
return myTagToPubsubMap[tag].subscripingApps;
else
return new string[] { };
}
public byte[] getContent(string tag)
{
public byte[] getContent(string tag) {
if (!myTagToData.ContainsKey(tag))
return null;
else
return myTagToData[tag].getCurrentContent();
}
public string getTagType(string tag)
{
public string getTagType(string tag) {
if (!myTagToData.ContainsKey(tag))
return null;
else
@@ -207,29 +186,23 @@ namespace BCG
/// <param name="deadPublishers"></param>
public void getAllConnections(string tag, out Dictionary<string, string> subscribers,
out Dictionary<string, string> activePublishers,
out ICollection<Pair<string, string>> deadPublishers)
{
if (myTagToPubsubMap.ContainsKey(tag))
{
out ICollection<Pair<string, string>> deadPublishers) {
if (myTagToPubsubMap.ContainsKey(tag)) {
SingleTagPubSubMap map = myTagToPubsubMap[tag];
subscribers = map.subscribers;
activePublishers = map.activePublishers;
deadPublishers = map.deadPublishers;
}
else
{
} else {
subscribers = activePublishers = new Dictionary<string, string>();
deadPublishers = new List<Pair<string, string>>();
}
}
public ICollection<string> allTags
{
public ICollection<string> allTags {
get { return myTagToPubsubMap.Keys; }
}
public ICollection<string> tagsWithData
{
public ICollection<string> tagsWithData {
get { return myTagToData.Keys; }
}
@@ -239,15 +212,11 @@ namespace BCG
/// </summary>
/// <param name="tags"></param>
/// <returns></returns>
public Dictionary<string, List<string>> getSubscriberConnectionsForTags(IEnumerable<string> tags)
{
public Dictionary<string, List<string>> getSubscriberConnectionsForTags(IEnumerable<string> tags) {
Dictionary<string, List<string>> retVal = new Dictionary<string, List<string>>();
foreach (string tag in tags)
{
if (myTagToPubsubMap.ContainsKey(tag))
{
foreach (string sub in myTagToPubsubMap[tag].subscriberConnections)
{
foreach (string tag in tags) {
if (myTagToPubsubMap.ContainsKey(tag)) {
foreach (string sub in myTagToPubsubMap[tag].subscriberConnections) {
if (!retVal.ContainsKey(sub))
retVal.Add(sub, new List<string>());
retVal[sub].Add(tag);
@@ -7,21 +7,18 @@ using System.Collections.Generic;
using BCG.Utilities;
using mbts;
namespace BCG
{
namespace BCG {
/// <summary>
/// SingleTagData consists of (as the name implies)
/// the data published for a tag
/// </summary>
internal class SingleTagData
{
internal class SingleTagData {
private string myTagType = null;
private string myTag;
private byte[] myLastPublishedMsg;
private IPubSubServerTagHandler myHandler;
public SingleTagData(string tag, string tagType)
{
public SingleTagData(string tag, string tagType) {
myTag = tag;
myTagType = tagType;
if (myTagType == SystemSubscriptionMapPublisher.tagType)
@@ -29,6 +26,7 @@ namespace BCG
else if (myTagType == SystemStatsPublisher.tagType)
myHandler = SystemStatsPublisher.getInstance();
else
// this is where it gets the stream handler
myHandler = TagType2HandlerMap.getHandler(myTagType, true);
if (myHandler != null)
myHandler.register(new InternalPublishDelegate(myHandleHandlerCallbacks));
@@ -38,16 +36,13 @@ namespace BCG
public string tagType { get { return myTagType; } }
internal void pubUpdate(Stream stream)
{
if (myHandler != null)
{
try
{
internal void pubUpdate(Stream stream) {
string handler_str = myHandler != null ? myHandler.GetType().ToString() : "NULL";
bts.Log.Gen.info($"SingleTagData.pubUpdate tag: {myTag} handler: {handler_str} stream: {stream.Position} / {stream.Length}");
if (myHandler != null) {
try {
myHandler.update(myTag, new Stream[] { stream });
}
catch (Exception e)
{
} catch (Exception e) {
// BlueEventLog.logEvent(e);
string errMsg = "tag handler threw an exception " + e.Message + " for tag type = " + myTagType +
" tag = " + myTag + " length = " + stream.Length + "\n" +
@@ -58,30 +53,22 @@ namespace BCG
else
throw new ApplicationException(errMsg, e);
}
}
else
{
} else {
myLastPublishedMsg = new byte[stream.Length - stream.Position];
stream.Read(myLastPublishedMsg, 0, myLastPublishedMsg.Length);
}
}
public byte[] getCurrentContent()
{
if (myHandler != null)
{
public byte[] getCurrentContent() {
if (myHandler != null) {
return myHandler.getContent(myTag);
}
else
{
} else {
return myLastPublishedMsg;
}
}
private void myHandleHandlerCallbacks(ICollection<Triplet<string, string, byte[]>> cbItems)
{
foreach (Triplet<string, string, byte[]> p in cbItems)
{
private void myHandleHandlerCallbacks(ICollection<Triplet<string, string, byte[]>> cbItems) {
foreach (Triplet<string, string, byte[]> p in cbItems) {
string tagName = p.first, tagType = p.second;
byte[] data = p.third;
PubMetaData pub = new PubMetaData(tagType, tagName, data.Length, "local", ClientInfo.thisClient.processString);
@@ -7,8 +7,7 @@ using BCG.Utilities.General;
using mbts;
using mbts.spark;
namespace BCG
{
namespace BCG {
/// <summary>
/// Deals with the subscriptions (and getting data) from one
/// pubsub server. Once again, theres no sharing of conenctions
@@ -17,15 +16,13 @@ namespace BCG
/// its concerned with (passed as a conctructor arg).
/// </summary>
internal interface ISingleServerSubscriberCore : IDisposable
{
internal interface ISingleServerSubscriberCore : IDisposable {
IList<PubSubUpdate> getUpdates(int timeout);
event PubSubConnectionChange onPubSubConnectionChange;
void subscribe(params string[] tags);
void unsubscribe(params string[] tags);
}
internal class SingleServerSubscriberCore : IDisposable, ISingleServerSubscriberCore
{
internal class SingleServerSubscriberCore : IDisposable, ISingleServerSubscriberCore {
private HighPerformanceTimer myTimer = new HighPerformanceTimer();
private PubSubServerConnectionFactory myConnectionFactory;
private IPubSubServerConnection myConnection;
@@ -33,15 +30,13 @@ namespace BCG
public event PubSubConnectionChange onPubSubConnectionChange;
public SingleServerSubscriberCore(string serverURL, PubSubServerConnectionFactory connectionFactory)
{
public SingleServerSubscriberCore(string serverURL, PubSubServerConnectionFactory connectionFactory) {
myConnectionFactory = connectionFactory;
myConnection = myConnectionFactory.getConnection(serverURL);
myConnection.registerCallback(new ConnectionStatusChange(myHandleServerReboot));
}
public IList<PubSubUpdate> getUpdates()
{
public IList<PubSubUpdate> getUpdates() {
return getUpdates(1);
}
@@ -51,54 +46,41 @@ namespace BCG
/// </summary>
/// <param name="timeout"></param>
/// <returns></returns>
public IList<PubSubUpdate> getUpdates(int timeout)
{
public IList<PubSubUpdate> getUpdates(int timeout) {
myConnection.doWork();
List<PubSubUpdate> retVal = new List<PubSubUpdate>();
IList<byte[]> dataItems = myConnection.getUpdates(new TimeSpan(0, 0, 0, 0, timeout), Int32.MaxValue);
foreach (byte[] data in dataItems)
{
foreach (byte[] data in dataItems) {
processMessage(data, retVal);
}
return retVal;
}
public List<string> getSubscribedTags()
{
public List<string> getSubscribedTags() {
return myTags;
}
public void subscribe(params string[] tags)
{
foreach (string tag in tags)
{
if (myTags.Contains(tag))
{
public void subscribe(params string[] tags) {
foreach (string tag in tags) {
if (myTags.Contains(tag)) {
string errMsg = String.Format("tag {0} was already subscribed from server {1}",
tag, myConnection.serverURL);
// BlueEventLog.logEvent(errMsg, BlueEventLevel.Warning);
}
else
{
} else {
myTags.Add(tag);
}
}
mySubscribe(tags);
}
public void unsubscribe(params string[] tags)
{
public void unsubscribe(params string[] tags) {
List<string> unsubTags = new List<string>();
foreach (string tag in tags)
{
if (myTags.Contains(tag))
{
foreach (string tag in tags) {
if (myTags.Contains(tag)) {
myTags.Remove(tag);
unsubTags.Add(tag);
}
else
{
} else {
string errMsg = String.Format("tag {0} is being unsubscribed from server {1}, eventhough " +
"it was never subscribed", tag, myConnection.serverURL);
// BlueEventLog.logEvent(errMsg, BlueEventLevel.Warning);
@@ -108,13 +90,13 @@ namespace BCG
Stream str = new MemoryStream();
new MetaData(unsub).save(str);
str.Position = 0;
// this is where data is actually sent out
myConnection.send(str);
}
#region IDisposable Members
public void Dispose()
{
public void Dispose() {
///remove the subscriber
//myConnection.send(new PubSubMessage(new MetaData(new RemoveSubscriberMetaData(myConnection.clientURL))).toStream());
myConnection.Dispose();
@@ -126,8 +108,7 @@ namespace BCG
#endregion
private void mySubscribe(params string[] tags)
{
private void mySubscribe(params string[] tags) {
SubMetaData sub = new SubMetaData(myConnection.clientURL, tags);
Stream str = new MemoryStream();
new MetaData(sub).save(str);
@@ -135,20 +116,16 @@ namespace BCG
myConnection.send(str);
}
private void myHandleServerReboot(string serverURL, bool connection)
{
if (connection)
{
private void myHandleServerReboot(string serverURL, bool connection) {
if (connection) {
//ie connection established again, so has to
//resubscribe to all the tags
// BlueEventLog.logEvent("Connection to " + serverURL + " established....resubscribing to all the tags",
// PS3LogLevels.disconnection);
mySubscribe(myTags.ToArray());
}
else
{
} else {
// BlueEventLog.logEvent("Connection to " + serverURL + " broke....attempting to reconnect...",
// PS3LogLevels.disconnection);
}
@@ -158,18 +135,17 @@ namespace BCG
onPubSubConnectionChange(connection, serverURL);
}
internal static void processMessage(byte[] data, List<PubSubUpdate> updates)
{
if (data != null && data.Length > 0)
{
internal static void processMessage(byte[] data, List<PubSubUpdate> updates) {
bts.Log.Gen.info($"SingleServerSubscriberCore.processMessage data_len: {data.Length}");
if (data != null && data.Length > 0) {
MemoryStream str = new MemoryStream(data);
MetaData md = new MetaData(str);
bts.Log.Gen.info($"SingleServerSubscriberCore.processMessage meta_data: {md}");
MemoryStream bodyStream = str;
long bodyPosition = str.Position;
object op = Activator.CreateInstance (Type.GetType("BCG." + md["op-code"]));
object op = Activator.CreateInstance(Type.GetType("BCG." + md["op-code"]));
md.copyTo(op);
if (op is PubMetaData)
{
if (op is PubMetaData) {
PubMetaData p = op as PubMetaData;
//BCG.BlueTrace.WriteBlueCommReceiveW(p.tag, p.publishTimeTicks);
@@ -177,41 +153,29 @@ namespace BCG
p.warnIfLatencyExceedsThreshold();
//find out if we need to decompress this data
Stream realBody = bodyStream;
if (p.isCompressed)
{
if (p.isCompressed) {
long compressedSize = bodyStream.Length - bodyStream.Position;
if (compressedSize == 0)
{
if (compressedSize == 0) {
string errorMsg = "Error: tag " + p.tag + " had compressed size of 0 bytes. This shouldnt' happen. Not decompressing tag or sending out update.";
Console.WriteLine(errorMsg);
//BlueEventLog.logEvent(errorMsg, BlueEventLevel.Error);
return;
}
realBody = StreamDecompressor.decompressStream(bodyStream);
realBody.Position = bodyPosition;
}
updates.Add(new PubSubUpdate(p.tag, p.type, realBody));
}
else if (op is TransactionMetaData)
{
} else if (op is TransactionMetaData) {
TransactionMetaData tr = op as TransactionMetaData;
for (int i = 0; i < tr.nMessages; i++)
{
for (int i = 0; i < tr.nMessages; i++) {
PubMetaData pub = new PubMetaData();
new MetaData(bodyStream).copyTo(pub);
byte[] trConstituent = new byte[pub.size];
bodyStream.Read(trConstituent, 0, trConstituent.Length);
updates.Add(new PubSubUpdate(pub.tag, pub.type, new MemoryStream(trConstituent)));
}
}
else{}
//BlueEventLog.logAssert(false, "Unknown message received: " + md.ToString() + " , only Pub and TransactionMetaData are legal");
} else { }
//BlueEventLog.logAssert(false, "Unknown message received: " + md.ToString() + " , only Pub and TransactionMetaData are legal");
}
}
}
+148 -214
View File
@@ -15,91 +15,79 @@ using mbts;
* This file was originally called 'PublisherCore.cs'. It was renamed so that the publisher core could be replaced.
*
* */
namespace BCG
{
public class CrushedTagManager
{
private static CrushedTagManager mySelf;
private Dictionary<string, bool> myTags = new Dictionary<string, bool>();
public static CrushedTagManager instance
{
get
{
if (mySelf == null)
mySelf = new CrushedTagManager();
return mySelf;
namespace BCG {
// Provides a function to check if a tag is crushabel or not
public class CrushedTagManager {
private static CrushedTagManager _self;
private Dictionary<string, bool> _tag_map = new Dictionary<string, bool>();
public static CrushedTagManager instance {
get {
if (_self == null)
_self = new CrushedTagManager();
return _self;
}
}
public bool isTagCrushable(string tag)
{
public bool is_tag_crushable(string tag) {
tag = tag.ToLower();
lock (typeof(CrushedTagManager))
{
if (!myTags.ContainsKey(tag))
{
bool rv = false;
lock (typeof(CrushedTagManager)) {
if (!_tag_map.TryGetValue(tag, out rv)) {
foreach (string r in PubSub3Config.instance.PS3_CrushableTags)
if (new System.Text.RegularExpressions.Regex(r).IsMatch(tag))
{
myTags.Add(tag, true);
if (new System.Text.RegularExpressions.Regex(r).IsMatch(tag)) {
_tag_map.Add(tag, true);
break;
}
if (!myTags.ContainsKey(tag))
myTags.Add(tag, false);
_tag_map.Add(tag, false);
}
}
return myTags[tag];
return rv;
}
}
/// <summary>
/// All the data for a single tag, thats published within
/// a transaction
/// </summary>
public class TagWaitingInTransaction
{
private bool myIsCrushable;
private List<byte[]> myData = new List<byte[]>();
private int myTotalSize = 0;
private string myTag, myTagType;
public TagWaitingInTransaction(string theTagType, string theTag)
{
myTag = theTag;
myTagType = theTagType;
myIsCrushable = CrushedTagManager.instance.isTagCrushable(myTag);
public class TagWaitingInTransaction {
private bool _is_crushable;
private List<byte[]> _buffered_data = new List<byte[]>();
// this is the size of all the buffered data
private int _total_size = 0;
private string _tag, _tag_type;
public TagWaitingInTransaction(string theTagType, string theTag) {
_tag = theTag;
_tag_type = theTagType;
_is_crushable = CrushedTagManager.instance.is_tag_crushable(_tag);
}
public void addPub(Stream pubStream)
{
if (myIsCrushable)
{
byte[] newData = new byte[(int)(pubStream.Length - pubStream.Position)];
pubStream.Read(newData, 0, newData.Length);
myData.Clear();
myData.Add(newData);
myTotalSize = newData.Length;
}
else
{
byte[] newData = new byte[(int)(pubStream.Length - pubStream.Position)];
pubStream.Read(newData, 0, newData.Length);
myData.Add(newData);
myTotalSize += newData.Length;
public void add_pub(Stream pub_stream) {
if (_is_crushable) {
// extract bytes, clear _buffered_data and queue to _buffered_data
byte[] new_data = new byte[(int)(pub_stream.Length - pub_stream.Position)];
pub_stream.Read(new_data, 0, new_data.Length);
_buffered_data.Clear();
_buffered_data.Add(new_data);
_total_size = new_data.Length;
} else {
// extract btes and queue to _buffered_data
byte[] new_data = new byte[(int)(pub_stream.Length - pub_stream.Position)];
pub_stream.Read(new_data, 0, new_data.Length);
_buffered_data.Add(new_data);
_total_size += new_data.Length;
}
}
public void writeTo(Stream s, string connection, string publishingApp)
{
new MetaData(new PubMetaData(myTagType, myTag, myTotalSize, connection, publishingApp)).save(s);
foreach (byte[] data in myData)
public void write_to(Stream s, string connection, string publishing_app) {
new MetaData(new PubMetaData(_tag_type, _tag, _total_size, connection, publishing_app)).save(s);
foreach (byte[] data in _buffered_data)
s.Write(data, 0, data.Length);
}
public string tag { get { return myTag; } }
public string tagType { get { return myTagType; } }
public List<byte[]> data { get { return myData; } }
public string tag { get { return _tag; } }
public string tagType { get { return _tag_type; } }
public List<byte[]> data { get { return _buffered_data; } }
}
public enum PublisherCoreMessageType
{
public enum PublisherCoreMessageType {
transactionBegin,
transactionCommit,
transactionAbort,
@@ -107,37 +95,35 @@ namespace BCG
clear
}
public class PublisherCoreMessage
{
public class PublisherCoreMessage {
public PublisherCoreMessageType msgType;
public string tagType, tag;
public Stream data;
public PublisherCoreMessage(string tagToClear)
{
public PublisherCoreMessage(string tagToClear) {
tag = tagToClear;
msgType = PublisherCoreMessageType.clear;
}
public PublisherCoreMessage(PublisherCoreMessageType theMsgType)
{
public PublisherCoreMessage(PublisherCoreMessageType theMsgType) {
msgType = theMsgType;
}
public PublisherCoreMessage(string theTagType, string theTag, Stream theData)
{
public PublisherCoreMessage(string theTagType, string theTag, Stream theData) {
msgType = PublisherCoreMessageType.publish;
tagType = theTagType;
tag = theTag;
data = theData;
}
public override string ToString() {
return $"PublisherCoreMessage tag: {tag} data.Position: {data.Position} data.Length: {data.Length}";
}
}
// this class uses an internal queue + thread to serialize and process calls
// made through its public interface (IPublisherCore)
public class StaticPublisherCore : IPublisherCore
{
public class StaticPublisherCore : IPublisherCore {
// used to allow for different transports
// to be used when communicating to a pubsubserver
protected PubSubServerConnectionFactory myConnectionFactory = new PubSubServerConnectionFactory(false);
@@ -172,57 +158,48 @@ namespace BCG
public StaticPublisherCore()
// TODOds
: this(new PubSubRouter())
{ }
: this(new PubSubRouter()) { }
public StaticPublisherCore(string serverURL)
: this(new PubSubRouter(new PubSubRoute(serverURL, ".*")))
{ }
: this(new PubSubRouter(new PubSubRoute(serverURL, ".*"))) { }
public StaticPublisherCore(IPubSubRouter r)
{
public StaticPublisherCore(IPubSubRouter r) {
myRouter = r;
Thread pumpThread = new Thread(new ThreadStart(myMessagePump));
pumpThread.IsBackground = true;
pumpThread.Start();
}
public void Dispose()
{ }
public void Dispose() { }
#endregion
public int getNumberOfWaitingMessages() { return myMainQueue.getCount(); }
#region Main Thread - all library functions are called on the main thread and queued to be picked by the pump
public void publish(string tag, Stream content)
{ publish("", tag, content); }
public void publish(string tag, Stream content) { publish("", tag, content); }
public void publish(string tagType, string tag, Stream content)
{
myMainQueue.enqueue(new PublisherCoreMessage(tagType, tag, content));
public void publish(string tagType, string tag, Stream content) {
PublisherCoreMessage msg = new PublisherCoreMessage(tagType, tag, content);
bts.Log.Gen.info($"StaticPublisherCore.publish tag: {tag} msg: {msg} len: {content.Length - content.Position}");
myMainQueue.enqueue(msg);
}
public void beginTransaction()
{
public void beginTransaction() {
myMainQueue.enqueue(new PublisherCoreMessage(PublisherCoreMessageType.transactionBegin));
}
public void commitTransaction()
{
public void commitTransaction() {
myMainQueue.enqueue(new PublisherCoreMessage(PublisherCoreMessageType.transactionCommit));
}
public void abortTransaction()
{
public void abortTransaction() {
myMainQueue.enqueue(new PublisherCoreMessage(PublisherCoreMessageType.transactionAbort));
}
public bool inTransaction
{ get { return myInTransaction; } }
public bool inTransaction { get { return myInTransaction; } }
public void clearState(string tag)
{
public void clearState(string tag) {
myMainQueue.enqueue(new PublisherCoreMessage(tag));
}
@@ -230,70 +207,51 @@ namespace BCG
#region Message Pump Thread - this is where messages are dequeued and the action performed
private void myMessagePump()
{
while (true)
{
try
{
while (true)
{
private void myMessagePump() {
while (true) {
try {
while (true) {
object data = myMainQueue.dequeue(1000);
if (data != null)
{
if (data != null) {
int qc = myMainQueue.getCount();
PublisherCoreMessage msg = data as PublisherCoreMessage;
if (msg.msgType == PublisherCoreMessageType.transactionBegin)
{
bts.Log.Gen.info($"StaticPublisherCore.myMessagePump msg: {msg}");
if (msg.msgType == PublisherCoreMessageType.transactionBegin) {
myBeginTransaction();
}
else if (msg.msgType == PublisherCoreMessageType.transactionCommit)
{
} else if (msg.msgType == PublisherCoreMessageType.transactionCommit) {
myCommitTransaction();
}
else if (msg.msgType == PublisherCoreMessageType.transactionAbort)
{
} else if (msg.msgType == PublisherCoreMessageType.transactionAbort) {
myAbortTransaction();
}
else if (msg.msgType == PublisherCoreMessageType.publish)
{
} else if (msg.msgType == PublisherCoreMessageType.publish) {
myPublish(msg.tagType, msg.tag, msg.data);
}
else if (msg.msgType == PublisherCoreMessageType.clear)
{
} else if (msg.msgType == PublisherCoreMessageType.clear) {
myClearState(msg.tag);
}
}
foreach (IPubSubServerConnection conn in mySenders)
{
foreach (IPubSubServerConnection conn in mySenders) {
conn.doWork();
}
}
}
catch (Exception ex)
{
// BlueEventLog.logEvent(ex);
} catch (Exception ex) {
bts.Log.Gen.error($"StaticPublisherCore.myMessagePump exception ex: {ex}");
if (ex is OutOfMemoryException)
throw ex;
}
}
}
private void myBeginTransaction()
{
private void myBeginTransaction() {
// BlueEventLog.logAssert(!inTransaction);
//BlueEventLog.logEvent("StaticPublisherCore Starting Transaction.", BlueEventLevel.Information);
myInTransaction = true;
}
private void myCommitTransaction()
{
private void myCommitTransaction() {
myEndTransaction(true);
}
private void myAbortTransaction()
{
private void myAbortTransaction() {
myEndTransaction(false);
}
@@ -304,21 +262,17 @@ namespace BCG
//keep it consistent with the way it was done earlier), this should
//simply publish it non transactionally (easy way out), or
//transactionally with respect to each pubsub
protected virtual void myEndTransaction(bool success)
{
lock (this)
{
protected virtual void myEndTransaction(bool success) {
lock (this) {
// BlueEventLog.logAssert(inTransaction);
//BlueEventLog.logEvent("StaticPublisherCore Finishing Transaction.", BlueEventLevel.Information);
myInTransaction = false;
if (success)
{
if (success) {
// pubsub server -> tags with updates
Dictionary<string, List<string>> routesToTags = new Dictionary<string, List<string>>();
// group updates per pubsub server
foreach (string tag in myWaitingInTransactionMessages.Keys)
{
foreach (string tag in myWaitingInTransactionMessages.Keys) {
string thisURL = myRouter.getPubURLForTag(tag);
if (!routesToTags.ContainsKey(thisURL))
routesToTags[thisURL] = new List<string>();
@@ -327,17 +281,14 @@ namespace BCG
// more than one server means we won't be able to honor the transactionality request
// log a warning if that is the case.
if (routesToTags.Keys.Count > 1)
{
if (routesToTags.Keys.Count > 1) {
//this is going to be a long error message, but it's an importat one to be able to debug.
StringBuilder errorMessageBuilder = new StringBuilder();
errorMessageBuilder.Append("Tags within this transaction are routed to different pubSub servers.\n");
errorMessageBuilder.Append("This will break the transactionality of clients receiving the data. Details:\n");
foreach (string route in routesToTags.Keys)
{
foreach (string tag in routesToTags[route])
{
foreach (string route in routesToTags.Keys) {
foreach (string tag in routesToTags[route]) {
errorMessageBuilder.Append("\tTag ");
errorMessageBuilder.Append(tag);
errorMessageBuilder.Append(" is routed to ");
@@ -351,16 +302,14 @@ namespace BCG
}
// iterate through each server with pending messages
foreach (KeyValuePair<string, List<string>> kvp in routesToTags)
{
foreach (KeyValuePair<string, List<string>> kvp in routesToTags) {
IPubSubServerConnection transactionSender = null;
string publishingApp = ClientInfo.thisClient.processString;
string connection = kvp.Key;
Stream transactionData = new MemoryStream();
// iterate through each of the pending tag updates for one server
foreach (string tag in kvp.Value)
{
foreach (string tag in kvp.Value) {
///it would be the same transaction sender that would
///return each time
transactionSender = myGetOrBuildSender(tag);
@@ -372,7 +321,7 @@ namespace BCG
// update internal state
myState.publish(waiting.tag, waiting.tagType, data);
// add a pubsub header and copy each message to the transactionData stream
waiting.writeTo(transactionData, connection, publishingApp);
waiting.write_to(transactionData, connection, publishingApp);
}
// now transactionData holds all the updates for all the tags
// that are to be sent to the PubSub represented by transactionSender
@@ -384,36 +333,33 @@ namespace BCG
transactionData.Position = 0;
// send the entire thing to the specific pubsub server.
transactionSender.send(new PubSubMessage(new MetaData(tMd), transactionData).toStream());
// this is where the data is actually sent out !
var ps_msg = new PubSubMessage(new MetaData(tMd), transactionData);
Console.WriteLine($"serverConn.send metadata: {ps_msg.meta_data}");
bts.Log.Gen.info($"StaticPublisherCore.send ps_msg: {ps_msg}");
transactionSender.send(ps_msg);
}
}
myWaitingInTransactionMessages.Clear();
}
}
protected virtual void myPublish(string tagType, string tag, Stream content)
{
if (myInTransaction)
{
protected virtual void myPublish(string tagType, string tag, Stream content) {
bts.Log.Gen.info($"StaticPublisherCore.myPublish tag: {tag} content: {content.Position} / {content.Length} myInTransaction: {myInTransaction}");
if (myInTransaction) {
///if its in transaction message is cached, and is sent
///only when theres a commit or abort
if (!myWaitingInTransactionMessages.ContainsKey(tag))
myWaitingInTransactionMessages.Add(tag, new TagWaitingInTransaction(tagType, tag));
myWaitingInTransactionMessages[tag].addPub(content);
}
else
{
//if (CrushedTagManager.instance.isTagCrushable(tag))
myWaitingInTransactionMessages[tag].add_pub(content);
} else {
{
myState.publish(tag, tagType, content);
if (!myCrushableTagsWaitingOnAck.ContainsKey(tag))
{
// BlueEventLog.logEvent("Sending crushable tag " + tag, BlueEventLevel.Diagnosis);
mySendData(tag, tagType, content);
}
else
{
// BlueEventLog.logEvent("Could not send tag " + tag + " since its waiting on an ack", BlueEventLevel.Diagnosis);
if (!myCrushableTagsWaitingOnAck.ContainsKey(tag)) {
bts.Log.Gen.info("Sending crushable tag: {tag}");
mySendData(tag, tagType, content, "myPublish");
} else {
bts.Log.Gen.info("Could not send tag: {tag} since its waiting on an ack");
myCrushableTagsWaitingOnAck[tag].second++;
}
}
@@ -428,64 +374,59 @@ namespace BCG
}
// add header, possibly compress the data, and sendto appropriate pubsub
private void mySendData(string tag, string tagType, Stream content)
{
private void mySendData(string tag, string tagType, Stream content, string reason) {
bts.Log.Gen.info($"StaticPublisherCore.mySendData tag: {tag} tagType: {tagType} reason: {reason} len: {content.Length - content.Position}");
long initPos = content.Position;
// locate right pubsub for this tag
IPubSubServerConnection serverConn = myGetOrBuildSender(tag);
Stream contentToPublish = content;
PubMetaData pubMd;
PubMetaData pub_md;
if (PubSub3Config.instance.isTagCompressed(tag))
{
if (PubSub3Config.instance.isTagCompressed(tag)) {
contentToPublish = new MemoryStream();
SharpZipCompressor Kompressor = new SharpZipCompressor();
Kompressor.compress(content, contentToPublish);
contentToPublish.Position = 0;
pubMd = new PubMetaData(tagType, tag, (int)contentToPublish.Length, (int)content.Length, serverConn.serverURL, ClientInfo.thisClient.processString);
if (PubSub3Config.instance.shouldReportTagsCompressionRatio(tag))
{
pub_md = new PubMetaData(tagType, tag, (int)contentToPublish.Length, (int)content.Length, serverConn.serverURL, ClientInfo.thisClient.processString);
if (PubSub3Config.instance.shouldReportTagsCompressionRatio(tag)) {
string msg = String.Format("Compressed tag {0} from {1} to {2} bytes, for a ratio of {3}.", tag, content.Length, contentToPublish.Length, (float)content.Length / (float)contentToPublish.Length);
// BlueEventLog.logEvent(msg, PS3LogLevels.compressionRatio);
}
}
else
pubMd = new PubMetaData(tagType, tag, (int)content.Length, serverConn.serverURL, ClientInfo.thisClient.processString);
} else
pub_md = new PubMetaData(tagType, tag, (int)content.Length, serverConn.serverURL, ClientInfo.thisClient.processString);
content.Position = initPos;
if (CrushedTagManager.instance.isTagCrushable(tag))
{
if (CrushedTagManager.instance.is_tag_crushable(tag)) {
string refId = String.Empty;
Console.WriteLine("StaticPublisherCore.mySend serverConn.sendWithConfirmation tag: " + tag + " server: " + serverConn.serverURL);
serverConn.sendWithConfirmation((new PubSubMessage(new MetaData(pubMd), contentToPublish).toStream() as MemoryStream).ToArray(), ref refId);
// this is where the data is actually sent out (there are multiple sends)
PubSubMessage ps_msg = new PubSubMessage(new MetaData(pub_md), contentToPublish);
//Console.WriteLine($"serverConn.send_with_confirmation metadata: {ps_msg.meta_data}");
bts.Log.Gen.info($"serverConn.send_with_confirmation metadata: {ps_msg.meta_data}");
bts.Log.Gen.info($"StaticPublisherCore.send ps_msg: {ps_msg}");
serverConn.send_with_confirmation(ps_msg, ref refId);
myCrushableTagsWaitingOnAck.Add(tag, new Pair<string, int>(refId, 0));
}
else
{
Console.WriteLine("StaticPublisherCore.mySend serverConn.send tag: " + tag + " server: " + serverConn.serverURL);
serverConn.send(new PubSubMessage(new MetaData(pubMd), contentToPublish).toStream());
} else {
// this is where the data is actually sent out
var ps_msg = new PubSubMessage(pub_md, contentToPublish);
bts.Log.Gen.info($"StaticPublisherCore.send ps_msg: {ps_msg}");
serverConn.send(ps_msg);
}
}
private void myClearState(string tag)
{
if (myTagToSender.ContainsKey(tag))
{
private void myClearState(string tag) {
if (myTagToSender.ContainsKey(tag)) {
myTagToSender.Remove(tag);
}
myState.clear(tag);
}
protected virtual IPubSubServerConnection myGetOrBuildSender(string tag)
{
if (!myTagToSender.ContainsKey(tag))
{
protected virtual IPubSubServerConnection myGetOrBuildSender(string tag) {
if (!myTagToSender.ContainsKey(tag)) {
string route = myRouter.getPubURLForTag(tag);
IPubSubServerConnection sender = myConnectionFactory.getConnection(route);
myTagToSender.Add(tag, sender);
if (!mySenders.Contains(sender))
{
if (!mySenders.Contains(sender)) {
mySenders.Add(sender);
sender.registerCallback(new ConnectionStatusChange(myHandleServerReboot));
sender.registerSendConfirmationCallback(new SendConfirmationDelegate(myOnSendConfirm));
@@ -497,20 +438,17 @@ namespace BCG
///in case of the server coming up, it publishes all the stored state
///for that server, back to it
protected void myHandleServerReboot(string serverURL, bool connection)
{
if (connection)
{
protected void myHandleServerReboot(string serverURL, bool connection) {
bts.Log.Gen.info($"StaticPublisherCore.myHandleServerReboot server_url: {serverURL}");
if (connection) {
string thisPublisherInfo = ClientInfo.thisClient.processString;
foreach (KeyValuePair<string, IPubSubServerConnection> p in myTagToSender)
{
if (p.Value.serverURL == serverURL)
{
foreach (KeyValuePair<string, IPubSubServerConnection> p in myTagToSender) {
if (p.Value.serverURL == serverURL) {
string tagType;
string tag = p.Key;
myCrushableTagsWaitingOnAck.Clear();
byte[] data = myState.getContent(tag, out tagType);
mySendData(tag, tagType, new MemoryStream(data));
mySendData(tag, tagType, new MemoryStream(data), "myHandleServerReboot");
//Stream content = new MemoryStream(data);
//Stream contentToPublish = content;
@@ -547,16 +485,12 @@ namespace BCG
/// of waiting for ack
/// </summary>
private Dictionary<string, Pair<string, int>> myCrushableTagsWaitingOnAck = new Dictionary<string, Pair<string, int>>();
private void myOnSendConfirm(string messageId, bool confirmed)
{
foreach (string tag in new List<string>(myCrushableTagsWaitingOnAck.Keys))
{
private void myOnSendConfirm(string messageId, bool confirmed) {
foreach (string tag in new List<string>(myCrushableTagsWaitingOnAck.Keys)) {
Pair<string, int> tagData = myCrushableTagsWaitingOnAck[tag];
if (messageId == tagData.first)
{
if (messageId == tagData.first) {
myCrushableTagsWaitingOnAck.Remove(tag);
if (tagData.second > 0)
{
if (tagData.second > 0) {
// BlueEventLog.logEvent("Missed sending " + tagData.second + " messages, sending latest message now", BlueEventLevel.Diagnosis);
/// this data was waiting on an
/// ack, need to resend it
@@ -13,8 +13,7 @@ using mbts;
using mbts.spark;
//using BCG.Utilities.BlueConfiguration;
namespace BCG
{
namespace BCG {
/// <summary>
/// This class serves as the subscrition interface to the pubsub. The only methods
@@ -25,70 +24,56 @@ namespace BCG
/// to the servers even though there might be so created by other instances of the SubscriberCore
///
/// </summary>
public class StaticSubscriberCore : ISubscriberCore
{
public class StaticSubscriberCore : ISubscriberCore {
private Dictionary<string, ISingleServerSubscriberCore> myServerURLToSubCore = new Dictionary<string, ISingleServerSubscriberCore>();
private IPubSubRouter myRouter;
private HighPerformanceTimer myTimer = new HighPerformanceTimer();
private PubSubServerConnectionFactory myConnectionFactory = new PubSubServerConnectionFactory(true);
public event PubSubConnectionChange onPubSubConnectionChange;
#region constructors
public StaticSubscriberCore()
{
public StaticSubscriberCore() {
//this defaults to a basic pubsubrouter if the config key is not filled out
myInit(myGetRouter());
}
public StaticSubscriberCore(string siteName)
{
public StaticSubscriberCore(string siteName) {
myInit(new PubSubRouter(PubSub3Config.instance.getRouting(siteName)));
}
private IPubSubRouter myGetRouter()
{return new PubSubRouter(PubSub3Config.instance.getRouting());}
private IPubSubRouter myGetRouter() { return new PubSubRouter(PubSub3Config.instance.getRouting()); }
public StaticSubscriberCore(PubSubRoute[] routes)
{
public StaticSubscriberCore(PubSubRoute[] routes) {
myInit(new PubSubRouter(routes));
}
public StaticSubscriberCore(IPubSubRouter router)
{
public StaticSubscriberCore(IPubSubRouter router) {
myInit(router);
}
#endregion
private void myInit(IPubSubRouter router)
{
private void myInit(IPubSubRouter router) {
myRouter = router;
}
public ArrayList getUpdates()
{
public ArrayList getUpdates() {
return getUpdates(10);
}
public ArrayList getUpdates(TimeSpan timeout)
{
public ArrayList getUpdates(TimeSpan timeout) {
return getUpdates(Convert.ToInt32(timeout.TotalMilliseconds));
}
public ArrayList getUpdates(int timeout)
{
public ArrayList getUpdates(int timeout) {
//BCG.BlueTrace.WriteTraceMethodEnterW("StaticSubscriberCore.getUpdates");
lock (myServerURLToSubCore)
{
lock (myServerURLToSubCore) {
if (myServerURLToSubCore.Count == 0)
{
if (myServerURLToSubCore.Count == 0) {
return new ArrayList();
}
else
{
} else {
///gets a time share for every subscriber and
///calls their updates
myTimer.start();
@@ -96,6 +81,7 @@ namespace BCG
List<PubSubUpdate> retVal = new List<PubSubUpdate>();
foreach (ISingleServerSubscriberCore subCore in myServerURLToSubCore.Values)
retVal.AddRange(subCore.getUpdates(timeShare));
_log_n_updates(retVal);
myTimer.stop();
//if (myTimer.lastIntervalTime > 10)
// BlueEventLog.logEvent("get updates taking " + myTimer.lastIntervalTime, BlueEventLevel.Error);
@@ -104,30 +90,36 @@ namespace BCG
return new ArrayList(retVal);
}
}
}
private Dictionary<string,bool> myBlueCommTags = new Dictionary<string,bool> ();
bool myIsBlueCommTag(string tag)
{
return false;
private IDictionary<string, int> _n_update_map = new Dictionary<string, int>();
private void _log_n_updates(IEnumerable<PubSubUpdate> updates) {
foreach (PubSubUpdate u in updates) {
if (!_n_update_map.ContainsKey(u.tag)) {
_n_update_map.Add(u.tag, 0);
}
_n_update_map[u.tag] = _n_update_map[u.tag] + 1;
}
// log it now
foreach (var kv in _n_update_map) {
bts.Log.Gen.info($"StaticSubscrberCore tag: {kv.Key} n_updates: {kv.Value}");
}
}
public void subscribe(params string[] tags)
{
lock (myServerURLToSubCore)
{
foreach (string tag in tags)
{
if (myIsBlueCommTag(tag))
{
}
else
{
private Dictionary<string, bool> myBlueCommTags = new Dictionary<string, bool>();
bool myIsBlueCommTag(string tag) {
return false;
}
public void subscribe(params string[] tags) {
lock (myServerURLToSubCore) {
foreach (string tag in tags) {
if (myIsBlueCommTag(tag)) {
} else {
string serverURL = myRouter.getSubURLForTag(tag);
if (!myServerURLToSubCore.ContainsKey(serverURL))
{
if (!myServerURLToSubCore.ContainsKey(serverURL)) {
// BlueEventLog.logEvent("Creating a SingleServerSubscriberCore for " + serverURL, BlueEventLevel.Information);
myServerURLToSubCore.Add(serverURL, new SingleServerSubscriberCore(serverURL, myConnectionFactory));
myServerURLToSubCore[serverURL].onPubSubConnectionChange += myHandleConnectionChange;
@@ -138,28 +130,22 @@ namespace BCG
}
}
}
public void myHandleConnectionChange (bool isConnected, string connection)
{
public void myHandleConnectionChange(bool isConnected, string connection) {
if (onPubSubConnectionChange != null)
onPubSubConnectionChange(isConnected, connection);
}
public void unsubscribe(params string[] tags)
{
lock (myServerURLToSubCore)
{
public void unsubscribe(params string[] tags) {
lock (myServerURLToSubCore) {
foreach (string tag in tags)
{
foreach (string tag in tags) {
if (myIsBlueCommTag(tag))
myServerURLToSubCore["bluecomm"].unsubscribe(tag);
else
{
else {
string serverURL = myRouter.getSubURLForTag(tag);
if (!myServerURLToSubCore.ContainsKey(serverURL))
{
if (!myServerURLToSubCore.ContainsKey(serverURL)) {
// BlueEventLog.logEvent("Creating a SingleServerSubscriberCore for " + serverURL, BlueEventLevel.Information);
myServerURLToSubCore.Add(serverURL, new SingleServerSubscriberCore(serverURL, myConnectionFactory));
}
@@ -168,15 +154,13 @@ namespace BCG
}
}
}
public IPubSubRouter getRouter()
{
public IPubSubRouter getRouter() {
return myRouter;
}
#region IDisposable Members
public void Dispose()
{
public void Dispose() {
foreach (ISingleServerSubscriberCore sssc in myServerURLToSubCore.Values)
sssc.Dispose();
+2 -4
View File
@@ -3,10 +3,8 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BCG
{
public class StreamOpCode
{
namespace BCG {
public class StreamOpCode {
public static readonly byte create = 0, //creates a table
add = 1, //adds a single row
remove = 2, //removes a single row
+15 -29
View File
@@ -4,82 +4,68 @@ using System.Linq;
using System.Text;
using System.Collections;
namespace BCG
{
namespace BCG {
/*
* This class has been changed to be a thin pass-through shell around different subscriber core implementations.
* The specific implementation used is determined by the config.
*
*
* */
public class SubscriberCore : ISubscriberCore
{
public class SubscriberCore : ISubscriberCore {
ISubscriberCore mySubscriberCore = null;
public SubscriberCore()
{
public SubscriberCore() {
// TODOds
mySubscriberCore = new StaticSubscriberCore();// PubSubComponentFactory.getSubscriberCore();
mySubscriberCore.onPubSubConnectionChange += myHandleConnectionChange;
}
public SubscriberCore(string siteName)
{
public SubscriberCore(string siteName) {
mySubscriberCore = new StaticSubscriberCore(siteName);
mySubscriberCore.onPubSubConnectionChange += myHandleConnectionChange;
}
public SubscriberCore(IPubSubRouter theRouter)
{
public SubscriberCore(IPubSubRouter theRouter) {
// TODOds
mySubscriberCore = new SubscriberCore(theRouter);// PubSubComponentFactory.getSubscriberCore();
mySubscriberCore = new StaticSubscriberCore(theRouter);// PubSubComponentFactory.getSubscriberCore();
mySubscriberCore.onPubSubConnectionChange += myHandleConnectionChange;
}
public SubscriberCore(PubSubRoute[] routes)
{
public SubscriberCore(PubSubRoute[] routes) {
//this is always a static subscriber core
mySubscriberCore = new StaticSubscriberCore(routes);
mySubscriberCore.onPubSubConnectionChange += myHandleConnectionChange;
}
public IPubSubRouter getRouter()
{
public IPubSubRouter getRouter() {
return mySubscriberCore.getRouter();
}
public ArrayList getUpdates()
{
public ArrayList getUpdates() {
return mySubscriberCore.getUpdates(10);
}
public ArrayList getUpdates(TimeSpan timeout)
{
public ArrayList getUpdates(TimeSpan timeout) {
return mySubscriberCore.getUpdates(Convert.ToInt32(timeout.TotalMilliseconds));
}
public ArrayList getUpdates(int timeout)
{
public ArrayList getUpdates(int timeout) {
return mySubscriberCore.getUpdates(timeout);
}
public void subscribe(params string[] tags)
{
public void subscribe(params string[] tags) {
mySubscriberCore.subscribe(tags);
}
public void unsubscribe(params string[] tags)
{
public void unsubscribe(params string[] tags) {
mySubscriberCore.unsubscribe(tags);
}
public void Dispose()
{
public void Dispose() {
mySubscriberCore.Dispose();
}
private void myHandleConnectionChange(bool isConnected, string connection)
{
private void myHandleConnectionChange(bool isConnected, string connection) {
if (onPubSubConnectionChange != null)
onPubSubConnectionChange(isConnected, connection);
}
@@ -0,0 +1,132 @@
using System;
using System.Linq.Expressions;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Spark.Core.Reactive;
using System.Security.Cryptography.X509Certificates;
using BCG;
namespace BCG
{
// This uses AsyncTCPConnection2's stateful async functions
public class SimpleTCPClientAsync : ITCPConnectionHandler, ITCPMessageHandler
{
AsyncTCPConnection2 _conn = null;
int _m_msgs_received = 0;
public static async Task start(string ip, int port)
{
SimpleTCPClientAsync c = new SimpleTCPClientAsync(ip, port);
c.connect();
}
public void connect()
{
Task.Run(async () => await TCPSocketUtils.connect_to_server_async("127.0.0.1", 12345, this, TimeSpan.FromSeconds(2)));
}
public void onConnection(ITCPConnection connection)
{
Console.WriteLine("SimpleTCPClientAsync.onConnection connected to server, starting task to send data in a loop");
connection.register(this);
// start sending data
Task.Run(async () =>
{
byte[] buff = new byte[1024];
for (int i = 0; i < buff.Length; i++)
{
buff[i] = (byte)i;
}
_conn = connection as AsyncTCPConnection2;
while (!_conn.isDisposed)
{
await _conn.send_async(buff);
await Task.Delay(100);
}
});
}
public void onData(RemoteMessage msg)
{
_m_msgs_received++;
Console.WriteLine($"SimpleTCPClientAsync.onData n_msgs: {_m_msgs_received} msg: {msg}");
if (msg.messageType == RemoteMessageType.Disconnection)
{
connect();
}
}
public bool isDisposed { get { return false; } }
public void Dispose() { }
public SimpleTCPClientAsync(string ip, int port) { }
}
public class SimpleTCPClient : ITCPConnectionHandler, ITCPMessageHandler
{
private int _n_msgs_received = 0;
AsyncTCPConnection2 _conn = null;
public static void start(string ip, int port)
{
SimpleTCPClient c = new SimpleTCPClient(ip, port);
c.connect();
}
public void connect()
{
Console.WriteLine("SimpleTCPClient.onConnection connect() called");
ClientToServerManagedTCPConnector.connect_to(new BlutoSubAddress("bluto://127.0.0.1:12345"), this, TimeSpan.FromSeconds(1));
}
public void onConnection(ITCPConnection connection)
{
_conn = connection as AsyncTCPConnection2;
Console.WriteLine("SimpleTCPClient.onConnection connected to server, starting task to send data in a loop");
_conn.register(this);
byte[] buff = new byte[1024];
for (int i = 0; i < buff.Length; i++)
{
buff[i] = (byte)i;
}
while (!_conn.isDisposed)
{
_conn.send(buff);
System.Threading.Thread.Sleep(1000);
}
// Task.Run(async () =>
// {
// while (!_conn.isDisposed)
// {
// await _conn.send_async(buff);
// await Task.Delay(100);
// }
// });
}
public void onData(RemoteMessage msg)
{
_n_msgs_received++;
Console.WriteLine($"SimpleTCPClient.onData messages received: {_n_msgs_received} msg: {msg} messages received: {_n_msgs_received}");
if (msg.messageType == RemoteMessageType.Disconnection)
{
connect();
}
}
public bool isDisposed { get { return false; } }
public void Dispose() { }
public SimpleTCPClient(string ip, int port) { }
}
}
@@ -0,0 +1,123 @@
using BCG;
using Google.Protobuf;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using BCG;
using System.Xml.Serialization;
using System.Reflection;
using System.Data;
using System.Collections.Generic;
namespace BCG
{
public class SimpleTCPServerAsync : ITCPConnectionHandler, ITCPMessageHandler
{
int _n_msgs_received = 0;
SingleServerToClientManagedTCPConnectionAcceptor _acceptor = new SingleServerToClientManagedTCPConnectionAcceptor();
IDictionary<RemoteConnectionInfo, ITCPConnection> _conn_map = new Dictionary<RemoteConnectionInfo, ITCPConnection>();
public static async Task start()
{
Console.WriteLine("SimpleTCPServer.start accepting socket connections");
SimpleTCPServerAsync s = new SimpleTCPServerAsync();
//await AsyncTCPConnection2.accept_connections("127.0.0.1", 12345, s, TimeSpan.FromMilliseconds(100));
s.accept();
}
// public static async Task init()
// {
// }
public void accept()
{
_acceptor.accept_on_port(this, "127.0.0.1", 12345, TimeSpan.Zero);
}
public void onConnection(ITCPConnection connection)
{
AsyncTCPConnection2 new_conn = connection as AsyncTCPConnection2;
RemoteConnectionInfo rci = new_conn.get_peer_address();
_conn_map.Add(rci, new_conn);
Console.WriteLine($"SimpleTCPServerAsync.onConnection new client connected conn: {rci}");
new_conn.register(this);
}
public void onData(RemoteMessage msg)
{
Console.WriteLine($"SimpleTCPServerAsync.onData msg: {msg}");
RemoteConnectionInfo rci = msg.remoteConnectionInfo;
ITCPConnection this_conn;
bool found = _conn_map.TryGetValue(rci, out this_conn);
if (!found)
{
Console.WriteLine("Could not find connection !!!!!!");
return;
}
_n_msgs_received++;
Console.WriteLine($"SimpleTCPServerAsync.onData msgs_received: {_n_msgs_received} msg: {msg} ci: {rci} echoing it back");
if (msg.messageType == RemoteMessageType.Data)
{
this_conn.send(msg.message);
// Task.Run(async () => {
// Console.WriteLine($"SimpleTCPServerAsync.onData sending msg: {msg} to client");
// await _conn.send_async(msg.message);
// });
}
}
public bool isDisposed { get { return false; } }
public void Dispose() { }
}
// public class SimpleTCPServer : ITCPConnectionHandler, ITCPMessageHandler {
// private AsyncTCPConnection2 _conn = null;
// private int _n_msgs_received = 0;
// SingleServerToClientManagedTCPConnectionAcceptor _acceptor = new SingleServerToClientManagedTCPConnectionAcceptor();
// public static async Task start() {
// Console.WriteLine("SimpleTCPServer.start accepting socket connections");
// SimpleTCPServer s = new SimpleTCPServer();
// s.accept();
// //await AsyncTCPConnection2.accept_connections("127.0.0.1", 12345, s, TimeSpan.FromMilliseconds(100));
// }
// public void accept() {
// _acceptor.accept_on_port(this, "127.0.0.1", 12345, TimeSpan.Zero);
// }
// public void onConnection(ITCPConnection connection) {
// Console.WriteLine("SimpleTCPServerAsync.onConnection new client connected");
// _conn = connection as AsyncTCPConnection2;
// connection.register(this);
// }
// public async void onData(RemoteMessage msg) {
// _n_msgs_received++;
// Console.WriteLine($"SimpleTCPServerAsync.onData msg: {msg} , msgs received: {_n_msgs_received} echoing it back");
// if (msg.messageType == RemoteMessageType.data && _conn != null) {
// Task.Run(async () => {
// //Console.WriteLine($"SimpleTCPServerAsync.onData sending msg: {msg} to client");
// //await _conn.send_async(msg.message);
// _conn.send(msg.message);
// });
// }
// }
// public bool isDisposed { get { return false; } }
// public void Dispose() { }
// }
}
Loaded 100 of 183 files, more files were not shown because too many files have changed in this diff. Show more