Compare commits

...
Author SHA1 Message Date
Taha 20617c6ee9 Fixing AsyncTCPCOnnection_APM's double partial messages for messages > 100 MB 2024-06-03 23:54:36 -04:00
Taha 753deba2f1 RemoteQueryStream 2024-06-01 02:02:15 -04:00
Taha f2b931fdc5 deleting old serializers 2024-05-17 12:16:35 -04:00
Taha 5162cd6711 Streams can eb published and subscribed now 2024-05-07 01:11:15 -04:00
Taha 80252502e7 Cleaned up the cashe held by PublisherCore 2024-05-04 00:41:34 -04:00
Taha ad3fe9e6c0 Stream serialization revamp, all tests pass (TestsStream.s) 2024-05-01 11:02:16 -04:00
Taha e2f5e6717d Adding tests for stream serialization 2024-04-22 13:29:50 -04:00
Taha a4005d1e74 Re-fixing PubSubserver exception caused by null server in internal tags 2024-03-31 01:57:08 -04:00
Taha Afzal a1de0faac9 Removing unused files 2024-03-06 14:19:12 -05:00
Taha Afzal ee4e011611 Meta tags work now 2024-02-29 22:12:08 -05:00
Taha Afzal 4512e085f2 Pubsub stats 2024-02-28 19:13:43 -05:00
Taha Afzal e8bfe89780 CPublisherCore, SubscriberCore, PubsubMessageReactor claned 2024-02-20 19:34:26 -05:00
Taha Afzal ad6f86ca98 PubUBState cleaned up and modernized 2024-02-03 10:41:07 -05:00
Taha Afzal a79126c43b removing old handlers from PubsubMessageReactor 2024-01-31 14:24:14 -05:00
Taha Afzal b4d7bbcfcd Clearing up PubSubMessageReactor 2024-01-30 23:19:20 -05:00
Taha Afzal d301d75305 Starting the server cleanup work 2024-01-29 14:13:36 -05:00
Taha Afzal 65d85c07e9 PublisherCore cleaned up 2024-01-29 07:33:26 -05:00
Taha Afzal 7e558bc108 CHanging member names from old style 2024-01-25 07:21:20 -05:00
Taha Afzal c545aeb1ea Cleaning up ISubscriberCore to use ne PubSubClientMssage class 2024-01-24 18:32:05 -05:00
Taha Afzal ad51d9f7f5 Adding testss for PubSubMessages 2024-01-23 22:58:26 -05:00
Taha Afzal c7722e223b Cleaning up PubSubMessages, as types messages instead of PubSubMetaData untypes dictionary 2024-01-21 22:46:49 -05:00
Taha Afzal 6e3f9f99c0 Merge branch 'development' of bitbucket.org:bluetradesys/spark into development 2024-01-17 10:08:17 -05:00
John Colvin b53d9d7d4c refactor: Remove 'Platform' (md source) config
Good riddance. Improper 'PlatformMap' config was often the reason market
data mysteriously wouldn't show up in the client. Especially with new
exchanges. We should keep all md source/connection configuration in one
place (one proto message), to avoid any confusion.
2024-01-17 01:42:57 -05:00
Taha Afzal cc3e289345 KeyValueToRelationalStream added 2024-01-16 19:08:40 -05:00
John Colvin 60a8b4f8c7 Gitignore all .tmp dirs (at any level) 2024-01-15 13:34:35 -05:00
John Colvin c5e0a93869 Gitignore all .venv* dirs (at any level) 2024-01-15 13:33:05 -05:00
John Colvin 3a3216421b Remove unnecessary file temp.cpp 2024-01-15 13:33:05 -05:00
Taha Afzal 8cbbbc6da3 Merging 2024-01-13 23:45:51 -05:00
241 changed files with 10010 additions and 13730 deletions

No files matched your search

+2 -2
View File
@@ -47,8 +47,8 @@ trace_data/
/src/.clang-format /src/.clang-format
/src/server/sparkd/cmds/spartan/analysis/.ipynb_checkpoints /src/server/sparkd/cmds/spartan/analysis/.ipynb_checkpoints
/src/server/sparkd/cmds/spartan/analysis/data /src/server/sparkd/cmds/spartan/analysis/data
*.tmp/* .tmp/
/.venv*/* .venv*/
.cache/ .cache/
/src/Spark.Admin.WebApp/tsconfig.*.g.json /src/Spark.Admin.WebApp/tsconfig.*.g.json
/src/Spark.Admin.WebApp/src/bin/ /src/Spark.Admin.WebApp/src/bin/
Submodule
+1
Submodule docker/linux added at 56c61231f3.
+1
Submodule docker/windows added at de7d40c09d.
@@ -15,6 +15,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.57" />
<PackageReference Include="MongoDB.Bson" Version="2.23.1" /> <PackageReference Include="MongoDB.Bson" Version="2.23.1" />
<PackageReference Include="MongoDB.Driver" Version="2.23.1" /> <PackageReference Include="MongoDB.Driver" Version="2.23.1" />
</ItemGroup> </ItemGroup>
@@ -1,32 +0,0 @@
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);
}
}
}
@@ -9,23 +9,20 @@ using System.Threading.Tasks;
using Bts.DataStreamExpressions; using Bts.DataStreamExpressions;
using System.Collections.Generic; using System.Collections.Generic;
using BCG.Utilities.General; using BCG.Utilities.General;
using bts;
namespace BCG namespace BCG {
{
// listens to the requests posted on "cloud_streams" request table, and // listens to the requests posted on "cloud_streams" request table, and
// if unfulfilled starts a ViewPubsliher // if unfulfilled starts a ViewPubsliher
public class CloudStreamManager : IWorker public class RemoteQueryManager : IWorker {
{ public class StreamPubUnit {
public class StreamPubUnit
{
public string name; public string name;
public string stream_expression; public string stream_expression;
public ViewStream stream; public ViewStream stream;
public bool persist; public bool persist;
public ViewPublisher view_publisher; public ViewPublisher view_publisher;
public StreamPubUnit(string name_, string stream_expression_, ViewStream stream_, bool persist_, ViewPublisher view_publisher_) public StreamPubUnit(string name_, string stream_expression_, ViewStream stream_, bool persist_, ViewPublisher view_publisher_) {
{
name = name_; name = name_;
stream_expression = stream_expression_; stream_expression = stream_expression_;
stream = stream_; stream = stream_;
@@ -33,17 +30,13 @@ namespace BCG
view_publisher = view_publisher_; view_publisher = view_publisher_;
} }
} }
static ViewStream build_stream(string stream_expression) static ViewStream build_stream(string stream_expression) {
{ try {
try
{
var exp = DataStreamExpressionsInterpreter.Evaluate(stream_expression); var exp = DataStreamExpressionsInterpreter.Evaluate(stream_expression);
var rv = exp.getView(new Dictionary<string, StatementExpression>(0)); var rv = exp.getView(new Dictionary<string, StatementExpression>(0));
return rv; return rv;
} } catch (Exception ex) {
catch (Exception ex)
{
bts.Log.assert(false, $"Could not build stream: {stream_expression} ex: {ex}"); bts.Log.assert(false, $"Could not build stream: {stream_expression} ex: {ex}");
return null; return null;
} }
@@ -52,34 +45,34 @@ namespace BCG
_stream_pub_map = new Dictionary<string, StreamPubUnit>(); _stream_pub_map = new Dictionary<string, StreamPubUnit>();
private ViewStream _stream = new TableStream("cloud_streams"); private ViewStream _stream = new TableStream("cloud_streams");
private PubTableBroker _broker = new PubTableBroker(); private PubTableBroker _broker = new PubTableBroker();
private ManagedSubscriber _sub = ManagedSubscriber.instance;
public CloudStreamManager()
{ public RemoteQueryManager() {
_stream.onChange += _on_str; _stream.onChange += _on_str;
_sub.subscribe("RemoteRequest", (string tag, byte[] data) => {
RemoteRequest req = RemoteRequest.construct_from_bytes(data);
_spawn_remote_stream(req.published_table_name, req.stream_expression, false);
});
} }
private void _on_str(object obj) // add a RemoteQuery sub, additionally and subscribe to it
{ private void _on_str(object obj) {
DataPacket dp = obj as DataPacket; DataPacket dp = obj as DataPacket;
foreach (IBlueRow r in dp.newRows) foreach (IBlueRow r in dp.newRows) {
{
string name = r.get<string>("name"); string name = r.get<string>("name");
bool persist = r.get<bool>("persist"); bool persist = r.get<bool>("persist");
string stream_exp = r.get<string>("stream_exp"); string stream_exp = r.get<string>("stream_exp");
if (!_stream_pub_map.ContainsKey(name)) if (!_stream_pub_map.ContainsKey(name)) {
{ _spawn_remote_stream(name, stream_exp, persist);
_assign(name, stream_exp, persist);
} }
} }
} }
private void _assign(string name, string stream_expression, bool persist) private void _spawn_remote_stream(string name, string stream_expression, bool persist) {
{
bts.Log.Gen.info($"CloudStreamManager.assign name: {name} stream_expression: {stream_expression}"); bts.Log.Gen.info($"CloudStreamManager.assign name: {name} stream_expression: {stream_expression}");
ViewStream stream = build_stream(stream_expression); ViewStream stream = build_stream(stream_expression);
_expose_to_ws(name, stream); _expose_to_ws(name, stream);
if (persist) if (persist) {
{
stream = new PersistorStream(stream, name, "C:\\Temp\\", 1000000); // 10MBs stream = new PersistorStream(stream, name, "C:\\Temp\\", 1000000); // 10MBs
} }
ViewPublisher view_pub = new ViewPublisher(name, _broker, stream); ViewPublisher view_pub = new ViewPublisher(name, _broker, stream);
@@ -87,13 +80,11 @@ namespace BCG
_stream_pub_map.Add(name, u); _stream_pub_map.Add(name, u);
} }
private void _expose_to_ws(string name, ViewStream stream) private void _expose_to_ws(string name, ViewStream stream) {
{
// TODO: john // TODO: john
} }
public void doWork() public void doWork() {
{
} }
} }
@@ -0,0 +1,48 @@
using BCG;
using bts;
using System;
namespace BCG {
// this is a stream so we can run it from the DSQA (since dsqa can only load streams)
[DataStreamUserRespresentation("remoteQuery")]
public class RemoteQueryStream : ViewStream {
private readonly string _name, _stream_exp;
private PublisherCore _publisher_core = new PublisherCore();
private ViewStream _source_str;
public RemoteQueryStream(params string[] lines) {
_stream_exp = get_expression(lines);
_name = Guid.NewGuid().ToString();
_name = $"remotereq_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString()}";
//_name.Replace("-", "_");
}
protected override void myOnFirstSubscriber() {
RemoteRequest rem_req = new RemoteRequest(_stream_exp, _name);
byte[] rem_req_bytes = rem_req.serialize();
_publisher_core.publish("System", "RemoteRequest", rem_req_bytes);
_source_str = new TableStream(_name);
_source_str.onChange += new ChangeDelegate(_handle_data);
}
protected override void myOnLastSubscriber() {
//maybe there should be a way to turn remote requests off ?
_source_str.onChange -= new ChangeDelegate(_handle_data);
}
static string get_expression(params string[] lines) {
for (int i = 0; i < lines.Length; i++) {
// unescape quotes
lines[i] = lines[i].Replace("\\\"", "\"");
}
return string.Join("\n", lines);
}
private void _handle_data(object o) {
myFireEvent(o);
}
}
}
@@ -0,0 +1,31 @@
namespace bts {
using System.IO;
using BCG;
using System.IO;
using System.Threading.Tasks.Dataflow;
public class RemoteRequest {
public readonly string stream_expression;
public readonly string published_table_name;
public RemoteRequest(string stream_expression_, string published_table_name_) {
stream_expression = stream_expression_;
published_table_name = published_table_name_;
}
public byte[] serialize() {
var str = new MemoryStream();
var bw = new BinaryWriter(str);
bw.write_string_cpp(stream_expression);
bw.write_string_cpp(published_table_name);
return str.ToArray();
}
public static RemoteRequest construct_from_bytes(byte[] ser_bytes) {
BinaryReader br = new BinaryReader(new MemoryStream(ser_bytes));
string stream_expression_ = br.read_string_cpp();
string published_table_name_ = br.read_string_cpp();
return new RemoteRequest(stream_expression_, published_table_name_);
}
}
}
@@ -1,59 +1,54 @@
using BCG; // using BCG;
using System.Linq; // using bts;
namespace BCG // using System.Linq;
{
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) // namespace BCG {
{ // // used on the client
return _rows.to_ienum().Where(r => name == r.get<string>("name")).Count() > 0; // 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.create_table(_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.create_table(table);
// // create table
// } else {
// if (exists(name))
// return;
// IBlueRow nr = new BlueRow(_schema, _rows.Count, name, persist, stream_exp);
// // TODO: use make_batch_changes instead
// Log.assert(false, "Fix addRow");
// //_broker.addRow(nr);
// }
// }
// bool exists(string name) {
// return _rows.to_ienum().Where(r => name == r.get<string>("name")).Count() > 0;
// }
// }
// }
@@ -1,17 +1,14 @@
using System; using System;
using System.Collections; using System.Collections;
namespace BCG namespace BCG {
{ internal class AddColumnsRow : IBlueRow {
internal class AddColumnsRow : IBlueRow
{
private IBlueTableSchema mySchema; private IBlueTableSchema mySchema;
private IBlueRow myRow; private IBlueRow myRow;
//private object[] myCachedValues; //private object[] myCachedValues;
#region Constructors #region Constructors
public AddColumnsRow (IBlueTableSchema schema, IBlueRow row) public AddColumnsRow(IBlueTableSchema schema, IBlueRow row) {
{
mySchema = schema; mySchema = schema;
myRow = row; myRow = row;
//myCachedValues = new object[schema.columnNames.Length]; //myCachedValues = new object[schema.columnNames.Length];
@@ -19,85 +16,78 @@ namespace BCG
#endregion #endregion
#region IBlueRow members #region IBlueRow members
public IBlueTableSchema schema{get{return mySchema;}} public IBlueTableSchema schema { get { return mySchema; } }
#endregion #endregion
#region ICollection members #region ICollection members
public int Count {get{return mySchema.columnNames.Length;}} public int Count { get { return mySchema.columnNames.Length; } }
public bool IsSynchronized {get{return false;}} public bool IsSynchronized { get { return false; } }
public object SyncRoot {get{return this;}} public object SyncRoot { get { return this; } }
public void CopyTo (Array array, int index) public void CopyTo(Array array, int index) {
{
int i = index; int i = index;
foreach (object o in this as IEnumerable) foreach (object o in this as IEnumerable)
array.SetValue (o, i++); array.SetValue(o, i++);
} }
#endregion #endregion
#region IDictionary members #region IDictionary members
public bool IsFixedSize {get{return true;}} public bool IsFixedSize { get { return true; } }
public bool IsReadOnly {get{return true;}} public bool IsReadOnly { get { return true; } }
/// <summary> /// <summary>
/// The key can either be the string corrsponding to the column name or /// The key can either be the string corrsponding to the column name or
/// the order of the column /// the order of the column
/// </summary> /// </summary>
public object this [object key] public object this[object key] {
{ get {
get
{
if (key is string) if (key is string)
return this[(string)key]; return this[(string)key];
return this[(int)key]; return this[(int)key];
} }
set {throw new NotSupportedException ("The IBlueRow is readonly");} set { throw new NotSupportedException("The IBlueRow is readonly"); }
} }
public object this[int index] public object this[int index] {
{ get {
get
{
//if (myCachedValues[index] == null) //if (myCachedValues[index] == null)
// myCachedValues[index] = mySchema[index].isConstant ? mySchema[index].colValue : myRow[index]; // myCachedValues[index] = mySchema[index].isConstant ? mySchema[index].colValue : myRow[index];
//return myCachedValues[index]; //return myCachedValues[index];
return mySchema[index].isConstant ? mySchema[index].colValue : myRow[index]; return mySchema[index].isConstant ? DBNull.Value : myRow[index];
} }
} }
public object this[string colName] {get{return this[mySchema[colName].colNo];}} public object this[string colName] { get { return this[mySchema[colName].colNo]; } }
public ICollection Keys{get{return mySchema.columnNames;}} public ICollection Keys { get { return mySchema.columnNames; } }
public ICollection Values public ICollection Values {
{ get {
get
{
object[] retVal = new object[mySchema.columnNames.Length]; object[] retVal = new object[mySchema.columnNames.Length];
CopyTo (retVal, 0); CopyTo(retVal, 0);
return retVal; return retVal;
} }
} }
public void Add (object key, object value) {throw new NotSupportedException ("The IBlueRow is readonly");} public void Add(object key, object value) { throw new NotSupportedException("The IBlueRow is readonly"); }
public void Clear () {throw new NotSupportedException ("The IBlueRow is readonly");} public void Clear() { throw new NotSupportedException("The IBlueRow is readonly"); }
public bool Contains (object key){return mySchema[(string)key] != null;} public bool Contains(object key) { return mySchema[(string)key] != null; }
/// <summary> /// <summary>
/// Note, the default enumerator is the IDictionary's enumerator, so if user needs to /// Note, the default enumerator is the IDictionary's enumerator, so if user needs to
/// iterate through the values, typecast this into an IEnumerable /// iterate through the values, typecast this into an IEnumerable
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public IDictionaryEnumerator GetEnumerator() {return new BlueRowDictionaryEnumerator(this);} public IDictionaryEnumerator GetEnumerator() { return new BlueRowDictionaryEnumerator(this); }
IEnumerator IEnumerable.GetEnumerator () {return new BlueRowEnumerator(this);}
public void Remove (object key) {throw new NotSupportedException ("The IBlueRow is readonly");} IEnumerator IEnumerable.GetEnumerator() { return new BlueRowEnumerator(this); }
public void Remove(object key) { throw new NotSupportedException("The IBlueRow is readonly"); }
#endregion #endregion
} }
@@ -1,11 +1,38 @@
// using System; using System;
// using System.Data; using System.Data;
// using System.Collections; using System.Collections;
// using BCG.Utilities; using BCG.Utilities;
// using BCG.Utilities.General; using BCG.Utilities.General;
// namespace BCG { namespace BCG {
// public class AddColumnsStream : MapStream { public class AddColumnsStream : ViewStream {
// public AddColumnsStream(ViewStream vs, string columnDef) : base(vs, new ColumnAdder(columnDef)) { } public static Tuple<string, Type, object> parse_exp(string exp) {
// } string[] toks = exp.Split(':');
// } string col_name = toks[0];
string col_value = toks[1];
Tuple<Type, object> tup = BlueDataUtility.guess_type(col_value);
return Tuple.Create(col_name, tup.Item1, tup.Item2);
}
private Tuple<string, Type, object> _new_col;
private IBlueTableSchema _out_schema;
public AddColumnsStream(ViewStream vs, string col_def) {
_new_col = parse_exp(col_def);
ViewStream rs = new MapStream(vs, (IBlueTableSchema s) => _get_schema(s), (IBlueRow r) => _map(r));
mySetRealSource(rs);
}
private IBlueTableSchema _get_schema(IBlueTableSchema input_schema) {
if (_out_schema == null)
_out_schema = BlueDataUtility.add_column(input_schema, _new_col.Item1, _new_col.Item2);
return _out_schema;
}
private IBlueRow _map(IBlueRow r) {
MutableBlueRow rv = new MutableBlueRow(_get_schema(r.schema), r);
rv.setValue(_new_col.Item1, _new_col.Item3);
return rv;
}
}
}
@@ -1,48 +1,24 @@
using System; using BCG;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary; namespace bts {
namespace BCG
{
[DataStreamUserRespresentation("loader")] [DataStreamUserRespresentation("loader")]
public class LoaderStream : ViewStream, ISideEffectStream public class LoaderStream : ViewStream {
{
public class Exception : System.Exception
{public Exception(string msg) : base(msg) { }}
public LoaderStream(string fileName, int secondsBetweenPolls) private string _filename;
{ private IStreamMsgDeserilizer _deser = new StreamIODeserializationController();
mySetRealSource(
new PollStream(() => new LoaderStream(fileName).rows, secondsBetweenPolls,
ViewStreamDatabase.instance)); public LoaderStream(string filename) {
_filename = filename;
} }
public LoaderStream(string fileName) protected override void myOnFirstSubscriber() {
{ byte[] ser_msg = StreamSerializationUtils.read_from_file(_filename);
if (fileName == null) StreamIOMessage msg = _deser.deserialize(ser_msg);
throw new LoaderStream.Exception("File name cannot be null"); Log.assert(msg.op == StreamIOMessage.StreamOp.CREATE);
IBlueRowCollection rows = msg.create_message.rows;
for (int i = 0; i < 5; i++) DataPacket dp = BlueDataUtility.build_dp_inc(rows, myLastValue as DataPacket);
try myFireEvent(dp);
{
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
BinaryFormatter bf = new BinaryFormatter();
#pragma warning disable SYSLIB0011
BlueTable bt = (BlueTable)bf.Deserialize(fs);
#pragma warning restore SYSLIB0011
mySetRealSource(new BlueRowCollectionStaticStream(bt));
}
break;
}
catch (IOException)
{
System.Threading.Thread.Sleep(50);
}
} }
} }
} }
@@ -5,6 +5,7 @@ using System.Text;
using System.IO; using System.IO;
using Google.Protobuf; using Google.Protobuf;
using System.Globalization; using System.Globalization;
using bts;
namespace BCG { namespace BCG {
// Writes all the udpates to a stream in a file. // Writes all the udpates to a stream in a file.
@@ -19,7 +20,7 @@ namespace BCG {
private ViewStream _source_stream; private ViewStream _source_stream;
private string _token; private string _token;
private FileStream _out_fs; private FileStream _out_fs;
private IBlueDataSerializer _serializer; private IStreamIOMsgSerializer _serializer;// = new UniversalStreamIOSerializer();
private string _file_name = String.Empty; private string _file_name = String.Empty;
private long _rollover_size; private long _rollover_size;
private readonly string _directory_path; private readonly string _directory_path;
@@ -89,13 +90,12 @@ namespace BCG {
DataPacket dp = new_value as DataPacket; DataPacket dp = new_value as DataPacket;
byte[] serialized_update = null; byte[] serialized_update = null;
bool _write_create = _serializer == null || _n_updates_in_current_file == 0; bool _write_create = _serializer == null || _n_updates_in_current_file == 0;
_serializer = _serializer ?? new UniversalSerializer(dp.schema); _serializer = _serializer ?? new UniversalStreamIOSerializer();
if (_write_create) { if (_write_create) {
// new files always starts with create // new files always starts with create
_serializer.serialize(StreamOpCode.create, new IBlueRowCollection[] { dp.newRows }, out serialized_update); serialized_update = _serializer.serialize(new bts.StreamIOMessage(new bts.StreamIOMessage.CreateMessage(dp.newRows)));
} else } else
_serializer.serialize(StreamOpCode.multipleRemoveAdd, new IBlueRowCollection[] { dp.deletedRows, dp.addedRows }, out serialized_update); serialized_update = _serializer.serialize(new bts.StreamIOMessage(new bts.StreamIOMessage.MultipleRemoveAddMessage(dp.deletedRows, dp.addedRows)));
BinaryWriter bw = new BinaryWriter(_out_fs); BinaryWriter bw = new BinaryWriter(_out_fs);
long utc_epoch = epoch_now(); long utc_epoch = epoch_now();
@@ -1,68 +1,68 @@
using System; // using System;
using System.Collections.Generic; // using System.Collections.Generic;
using System.Linq; // using System.Linq;
using System.Text; // using System.Text;
using System.IO; // using System.IO;
namespace BCG // namespace BCG
{ // {
public class RecorderStream : ViewStream // public class RecorderStream : ViewStream
{ // {
private ViewStream mySource; // private ViewStream mySource;
private DateTime myStartTime; // private DateTime myStartTime;
private FileStream myOutFile; // private FileStream myOutFile;
private string myFileName; // private string myFileName;
private IBlueDataSerializer mySerializer; // private IBlueDataSerializer mySerializer;
public RecorderStream(ViewStream src, string recordFile)
{
mySource = src;
myFileName = recordFile;
myFileName = myFileName.Replace("%DATE%", DateTime.Now.ToString("yyyyMMdd_HHmmss")); // public RecorderStream(ViewStream src, string recordFile)
} // {
// mySource = src;
// myFileName = recordFile;
protected override void myOnFirstSubscriber() // myFileName = myFileName.Replace("%DATE%", DateTime.Now.ToString("yyyyMMdd_HHmmss"));
{ // }
myStartTime = DateTime.Now;
mySource.onChange += new ChangeDelegate(mySource_onChange);
myOutFile = new FileStream(myFileName, FileMode.OpenOrCreate);
}
protected override void myOnLastSubscriber()
{
mySource.onChange -= mySource_onChange;
myOutFile.Close();
}
void mySource_onChange(object newValue) // protected override void myOnFirstSubscriber()
{ // {
DataPacket dp = (DataPacket)newValue; // myStartTime = DateTime.Now;
// mySource.onChange += new ChangeDelegate(mySource_onChange);
BlueTable toWrite = new BlueTable(dp.schema); // myOutFile = new FileStream(myFileName, FileMode.OpenOrCreate);
// }
if (mySerializer == null) // protected override void myOnLastSubscriber()
{ // {
mySerializer = new UniversalSerializer(dp.schema); // mySource.onChange -= mySource_onChange;
} // myOutFile.Close();
foreach (IBlueRow r in dp.newRows) // }
toWrite.addRow(r);
byte[] result;
if (myLastValue == null) // void mySource_onChange(object newValue)
mySerializer.serialize(StreamOpCode.create, new IBlueRowCollection[] { dp.newRows }, out result); // {
else // DataPacket dp = (DataPacket)newValue;
mySerializer.serialize(StreamOpCode.multipleRemoveAdd, new IBlueRowCollection[] { dp.deletedRows, dp.addedRows }, out result);
BinaryWriter bw = new BinaryWriter(myOutFile); // BlueTable toWrite = new BlueTable(dp.schema);
//write down what time this happened
bw.Write((DateTime.Now - myStartTime).TotalSeconds);
bw.Write(result.Length);
bw.Write(result);
myOutFile.Flush();
myFireEvent(dp); // if (mySerializer == null)
} // {
} // mySerializer = new UniversalSerializer(dp.schema);
} // }
// foreach (IBlueRow r in dp.newRows)
// toWrite.addRow(r);
// byte[] result;
// if (myLastValue == null)
// mySerializer.serialize(StreamOpCode.create, new IBlueRowCollection[] { dp.newRows }, out result);
// else
// mySerializer.serialize(StreamOpCode.multipleRemoveAdd, new IBlueRowCollection[] { dp.deletedRows, dp.addedRows }, out result);
// BinaryWriter bw = new BinaryWriter(myOutFile);
// //write down what time this happened
// bw.Write((DateTime.Now - myStartTime).TotalSeconds);
// bw.Write(result.Length);
// bw.Write(result);
// myOutFile.Flush();
// myFireEvent(dp);
// }
// }
// }
@@ -1,64 +1,37 @@
// using System; using System;
// using System.Collections.Generic; using System.Collections.Generic;
// using System.Text; using System.Text;
// using System.IO; using System.IO;
using BCG;
// using System.Runtime.Serialization.Formatters.Binary; namespace bts {
// this saves the total state in the filr provided in the cons
[DataStreamUserRespresentation("saver")]
public class SaverStream : ViewStream {
private ViewStream _stream;
private string _filename;
private IStreamIOMsgSerializer _serializer = new StreamIOSerializationController();
// namespace BCG public SaverStream(ViewStream vs, string filename) {
// { _stream = vs;
// [DataStreamUserRespresentation("saver")] _filename = filename;
// public class SaverStream : ViewStream, ISideEffectStream }
// {
// private ViewStream myStream;
// private string myFileName;
// public class Exception : System.Exception protected override void myOnFirstSubscriber() { _stream.onChange += new ChangeDelegate(_handle_changes); }
// {
// public Exception(string msg) : base(msg) { }
// }
// public SaverStream(ViewStream vs, string fileName) void _handle_changes(object dp_obj) {
// { DataPacket dp = dp_obj as DataPacket;
// if (fileName == null) _save(dp);
// throw new SaverStream.Exception("File name cannot be null"); myFireEvent(dp_obj);
// myStream = vs; }
// myFileName = fileName;
// } protected override void myOnLastSubscriber() { _stream.onChange -= new ChangeDelegate(_handle_changes); }
// protected override void myOnFirstSubscriber() protected void _save(DataPacket dp) {
// { myStream.onChange += new ChangeDelegate(myHandleChanges); } StreamIOMessage.CreateMessage cr_msg = new StreamIOMessage.CreateMessage(dp.newRows);
byte[] str_bytes = _serializer.serialize(new StreamIOMessage(cr_msg));
StreamSerializationUtils.write_to_file(str_bytes, _filename);
// void myHandleChanges(object newValue) }
// { }
// DataPacket dp = newValue as DataPacket; }
// mySave(dp);
// myFireEvent(newValue);
// }
// protected override void myOnLastSubscriber()
// { myStream.onChange -= new ChangeDelegate(myHandleChanges); }
// protected void mySave(DataPacket dp)
// {
// for (int i = 0; i < 5 ; i++)
// try
// {
// using (FileStream fs = new FileStream(myFileName, FileMode.Create, FileAccess.Write))
// {
// BinaryFormatter bf = new BinaryFormatter();
// BlueTable t = new BlueTable(dp.schema);
// foreach (IBlueRow r in dp.newRows) // to guarantee table is serializable
// t.addRow(new BlueRow(r));
// bf.Serialize(fs, t);
// }
// break;
// }
// catch (IOException)
// {
// System.Threading.Thread.Sleep(5);
// }
// }
// }
// }
@@ -1,115 +1,115 @@
using System; // using System;
using System.Collections.Generic; // using System.Collections.Generic;
using System.Linq; // using System.Linq;
using System.Text; // using System.Text;
using System.IO; // using System.IO;
using System.Runtime.Serialization.Formatters.Binary; // using System.Runtime.Serialization.Formatters.Binary;
using BCG.Utilities.General; // using BCG.Utilities.General;
using bts.collections; // using bts.collections;
using System.Reflection.Metadata; // using System.Reflection.Metadata;
namespace BCG { // namespace BCG {
public class SnapshotStream : ViewStream { // public class SnapshotStream : ViewStream {
private BlueTable _current_table; // private BlueTable _current_table;
private IClientDeserializer _deserilializer = new ClientUniversalDeserializer(); // private IClientDeserializer _deserilializer = new ClientUniversalDeserializer();
public DateTime _snapshot_time; // public DateTime _snapshot_time;
public string _snapshot_file; // public string _snapshot_file;
public IEnumerable<PlaybackPacket> _packets; // public IEnumerable<PlaybackPacket> _packets;
public SnapshotStream(string snapshot_dt, string directory_name, string token) { // public SnapshotStream(string snapshot_dt, string directory_name, string token) {
_snapshot_time = PersistorStream.parse_datetime(snapshot_dt); // _snapshot_time = PersistorStream.parse_datetime(snapshot_dt);
string token_directory_name = $"{directory_name}\\{token}"; // string token_directory_name = $"{directory_name}\\{token}";
_snapshot_file = StreamPersistorUtils.find_snapshot_file(token_directory_name, _snapshot_time); // _snapshot_file = StreamPersistorUtils.find_snapshot_file(token_directory_name, _snapshot_time);
} // }
protected override void myOnFirstSubscriber() { // protected override void myOnFirstSubscriber() {
FileStream fs = new FileStream(_snapshot_file, FileMode.Open, FileAccess.Read); // FileStream fs = new FileStream(_snapshot_file, FileMode.Open, FileAccess.Read);
_packets = StreamPersistorUtils.load_packets_from_file(fs); // _packets = StreamPersistorUtils.load_packets_from_file(fs);
PlaybackPacket snapshot_packet = StreamPersistorUtils.find_packet_at_time(_packets, _snapshot_time); // PlaybackPacket snapshot_packet = StreamPersistorUtils.find_packet_at_time(_packets, _snapshot_time);
if (snapshot_packet != null) { // if (snapshot_packet != null) {
foreach (PlaybackPacket p in _packets) { // foreach (PlaybackPacket p in _packets) {
byte[] ops; // byte[] ops;
Array row_array; // Array row_array;
_deserilializer.deserialize(new Stream[] { new MemoryStream(p.data) }, out ops, out row_array); // _deserilializer.deserialize(new Stream[] { new MemoryStream(p.data) }, out ops, out row_array);
for (int i = 0; i < ops.Length; i++) { // for (int i = 0; i < ops.Length; i++) {
IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[]; // IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[];
byte op = ops[i]; // byte op = ops[i];
if (op == StreamOpCode.create) { // if (op == StreamOpCode.create) {
IBlueRowCollection full_table = rows_args[0]; // IBlueRowCollection full_table = rows_args[0];
_current_table = new BlueTable(full_table); // _current_table = new BlueTable(full_table);
} else if (op == StreamOpCode.multipleRemoveAdd) { // } else if (op == StreamOpCode.multipleRemoveAdd) {
//IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[]; // //IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[];
IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection; // IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection;
IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection; // IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection;
BlueDataUtility.absorbChanges(_current_table, dels, adds); // BlueDataUtility.absorbChanges(_current_table, dels, adds);
} else { // } else {
bts.Log.assert(false, $"Oprator: {op} is not expected"); // bts.Log.assert(false, $"Oprator: {op} is not expected");
} // }
if (p.idx == snapshot_packet.idx) { // if (p.idx == snapshot_packet.idx) {
myFireEvent(new DataPacket(_current_table, _current_table, new BlueTable(_current_table.schema))); // myFireEvent(new DataPacket(_current_table, _current_table, new BlueTable(_current_table.schema)));
break; // break;
} // }
} // }
} // }
} // }
} // }
private void _absorb_packet(byte[] ops, Array row_array) { // private void _absorb_packet(byte[] ops, Array row_array) {
for (int i = 0; i < ops.Length; i++) { // for (int i = 0; i < ops.Length; i++) {
IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[]; // IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[];
byte op = ops[i]; // byte op = ops[i];
if (op == StreamOpCode.create) { // if (op == StreamOpCode.create) {
IBlueRowCollection full_table = rows_args[0]; // IBlueRowCollection full_table = rows_args[0];
_current_table = new BlueTable(full_table); // _current_table = new BlueTable(full_table);
} else if (op == StreamOpCode.multipleRemoveAdd) { // } else if (op == StreamOpCode.multipleRemoveAdd) {
//IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[]; // //IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[];
IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection; // IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection;
IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection; // IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection;
BlueDataUtility.absorbChanges(_current_table, dels, adds); // BlueDataUtility.absorbChanges(_current_table, dels, adds);
} else { // } else {
bts.Log.assert(false, $"Operator: {op} is not expected"); // bts.Log.assert(false, $"Operator: {op} is not expected");
} // }
} // }
} // }
protected override void myOnLastSubscriber() { // protected override void myOnLastSubscriber() {
} // }
// public event SnapshotStream.Progress onProgress; // // public event SnapshotStream.Progress onProgress;
// public event Action onFileExhausted; // // public event Action onFileExhausted;
private PlaybackPacket _locate_packet_to_replay() { // private PlaybackPacket _locate_packet_to_replay() {
foreach (var p in _packets) { // foreach (var p in _packets) {
// returns the first non replayed packet // // returns the first non replayed packet
if (!p.replayed) // if (!p.replayed)
return p; // return p;
} // }
return null; // return null;
} // }
private void _fire_packet(byte[] ops, Array row_array) { // private void _fire_packet(byte[] ops, Array row_array) {
for (int i = 0; i < ops.Length; i++) { // for (int i = 0; i < ops.Length; i++) {
IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[]; // IBlueRowCollection[] rows_args = row_array.GetValue(i) as IBlueRowCollection[];
byte op = ops[i]; // byte op = ops[i];
if (op == StreamOpCode.create) { // if (op == StreamOpCode.create) {
IBlueRowCollection full_table = rows_args[0]; // IBlueRowCollection full_table = rows_args[0];
_current_table = new BlueTable(full_table); // _current_table = new BlueTable(full_table);
//_current_table.addRows(full_table); // //_current_table.addRows(full_table);
myFireEvent(new DataPacket(full_table, full_table, myLastValue == null ? new BlueTable(full_table.schema) : // myFireEvent(new DataPacket(full_table, full_table, myLastValue == null ? new BlueTable(full_table.schema) :
(myLastValue as DataPacket).newRows)); // (myLastValue as DataPacket).newRows));
} else if (op == StreamOpCode.multipleRemoveAdd) { // } else if (op == StreamOpCode.multipleRemoveAdd) {
//IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[]; // //IBlueRowCollection[] del_added = rows_args.GetValue(0) as IBlueRowCollection[];
IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection; // IBlueRowCollection dels = rows_args.GetValue(0) as IBlueRowCollection;
IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection; // IBlueRowCollection adds = rows_args.GetValue(1) as IBlueRowCollection;
BlueDataUtility.absorbChanges(_current_table, dels, adds); // BlueDataUtility.absorbChanges(_current_table, dels, adds);
myFireEvent(new DataPacket(_current_table, adds, dels)); // myFireEvent(new DataPacket(_current_table, adds, dels));
} else { // } else {
bts.Log.assert(false, $"Oprator: {op} is not expected"); // bts.Log.assert(false, $"Oprator: {op} is not expected");
} // }
} // }
} // }
} // }
} // }
@@ -1,37 +1,66 @@
using System; using System;
using System.Collections.Generic; using System.Text.RegularExpressions;
using System.Linq;
using System.Text;
using BCG.Utilities.General; using BCG.Utilities.General;
namespace BCG namespace BCG {
{ public class TimeBasedFilter : IDynamicStreamFilter, IWorker, IDisposable {
public class TimeBasedFilter : IDynamicStreamFilter, IWorker, IDisposable
{ public static TimeSpan parse_duration(string input) {
int days = 0, hours = 0, minutes = 0, seconds = 0;
// Regular expression to match the pattern (e.g., "1d", "1h", "15m", "45s")
Regex regex = new Regex(@"(\d+)([dhms])");
MatchCollection matches = regex.Matches(input);
foreach (Match match in matches) {
int value = int.Parse(match.Groups[1].Value);
string unit = match.Groups[2].Value;
switch (unit) {
case "d":
days = value;
break;
case "h":
hours = value;
break;
case "m":
minutes = value;
break;
case "s":
seconds = value;
break;
}
}
return new TimeSpan(days, hours, minutes, seconds);
}
#region constructors #region constructors
public TimeBasedFilter(string col_name, string row_time_to_live)
: this(col_name, parse_duration(row_time_to_live)) {
}
public TimeBasedFilter(string rowTimeColumnName, TimeSpan rowTimeToLive) public TimeBasedFilter(string rowTimeColumnName, TimeSpan rowTimeToLive)
: this (ViewStreamDatabase.instance, rowTimeColumnName, rowTimeToLive, new TimeSpan(0, 1, 0) /* 1 minute */) : this(ViewStreamDatabase.instance, rowTimeColumnName, rowTimeToLive, new TimeSpan(0, 1, 0) /* 1 minute */) {
{
} }
public TimeBasedFilter(string rowTimeColumnName, TimeSpan rowTimeToLive, TimeSpan filterFrequency) public TimeBasedFilter(string rowTimeColumnName, TimeSpan rowTimeToLive, TimeSpan filterFrequency)
: this (ViewStreamDatabase.instance, rowTimeColumnName, rowTimeToLive, filterFrequency) : this(ViewStreamDatabase.instance, rowTimeColumnName, rowTimeToLive, filterFrequency) {
{
} }
public TimeBasedFilter(ViewStreamDatabase vsd, string rowTimeColumnName, TimeSpan rowTimeToLive) public TimeBasedFilter(ViewStreamDatabase vsd, string rowTimeColumnName, TimeSpan rowTimeToLive)
: this (vsd, rowTimeColumnName, rowTimeToLive, new TimeSpan(0, 1, 0) /* 1 minute */) : this(vsd, rowTimeColumnName, rowTimeToLive, new TimeSpan(0, 1, 0) /* 1 minute */) {
{
} }
public TimeBasedFilter(ViewStreamDatabase vsd, string rowTimeColumnName, TimeSpan rowTimeToLive, TimeSpan filterFrequency) public TimeBasedFilter(ViewStreamDatabase vsd, string rowTimeColumnName, TimeSpan rowTimeToLive, TimeSpan filterFrequency) {
{ myVsd = vsd;
myVsd = vsd; _time_col = rowTimeColumnName;
myRowTimeColumnName = rowTimeColumnName; _ttl = rowTimeToLive;
myRowTimeToLive = rowTimeToLive; myFilterFrequency = filterFrequency;
myFilterFrequency = filterFrequency; myNextFilter = DateTime.MinValue;
myNextFilter = DateTime.MinValue;
// add worker // add worker
myVsd.addWorker(this); myVsd.addWorker(this);
@@ -41,32 +70,25 @@ namespace BCG
public event FilterChangeDelegate onFilterChange; public event FilterChangeDelegate onFilterChange;
#region IStreamFilter #region IStreamFilter
public bool filter(IBlueRow row) public bool filter(IBlueRow row) {
{ DateTime now = DateTime.Now;
DateTime now = DateTime.Now;
DateTime timeStamp = (DateTime)row[myRowTimeColumnName];
if (now > timeStamp) DateTime row_time = row.get_datetime(_time_col, DateTime.Now);
{ if (now > row_time) {
TimeSpan span = now - timeStamp; TimeSpan span = now - row_time;
if (span >= _ttl) {
if (span >= myRowTimeToLive)
{
return (false); return (false);
} }
} }
return (true); return (true);
} }
#endregion #endregion
#region IWorker #region IWorker
public void doWork() public void doWork() {
{
DateTime now = DateTime.Now; DateTime now = DateTime.Now;
if (now > myNextFilter) if (now > myNextFilter) {
{
// fire event // fire event
onFilterChange(); onFilterChange();
@@ -76,8 +98,7 @@ namespace BCG
#endregion #endregion
#region IDisposable #region IDisposable
public void Dispose() public void Dispose() {
{
// remove worker // remove worker
myVsd.removeWorker(this); myVsd.removeWorker(this);
} }
@@ -85,10 +106,20 @@ namespace BCG
#region state #region state
private ViewStreamDatabase myVsd; private ViewStreamDatabase myVsd;
private string myRowTimeColumnName; private string _time_col;
private TimeSpan myRowTimeToLive; private TimeSpan _ttl;
private TimeSpan myFilterFrequency; private TimeSpan myFilterFrequency;
private DateTime myNextFilter; private DateTime myNextFilter;
#endregion #endregion
} }
[DataStreamUserRespresentation("timefilter")]
public class TimeBasedFilterStream : ViewStream {
public TimeBasedFilterStream(ViewStream base_stream, string time_col, string time_span)
:
this(ViewStreamDatabase.instance, base_stream, time_col, TimeBasedFilter.parse_duration(time_span)) { }
public TimeBasedFilterStream(ViewStreamDatabase vsd, ViewStream base_stream, string time_col, TimeSpan time_span) {
TimeBasedFilter filter = new TimeBasedFilter(vsd, time_col, time_span);
mySetRealSource(new FilterStream(base_stream, filter));
}
}
} }
@@ -4,18 +4,14 @@ using BCG.Utilities;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace BCG namespace BCG {
{ public class GroupByStream : MethodDrivenStream {
public class GroupByStream : MethodDrivenStream private class MyFuncGroupByEvaluator : IGroupByEvaluator {
{
private class MyFuncGroupByEvaluator : IGroupByEvaluator
{
private string[] _groupby_cols; private string[] _groupby_cols;
private Func<DataPacket, IBlueRow> _groupby_func; private Func<DataPacket, IBlueRow> _groupby_func;
public MyFuncGroupByEvaluator(IEnumerable<string> groupby_cols, Func<DataPacket, IBlueRow> groupby_func) public MyFuncGroupByEvaluator(IEnumerable<string> groupby_cols, Func<DataPacket, IBlueRow> groupby_func) {
{
_groupby_cols = groupby_cols.ToArray(); _groupby_cols = groupby_cols.ToArray();
_groupby_func = groupby_func; _groupby_func = groupby_func;
} }
public IBlueRow evaluate(DataPacket packet) { return _groupby_func(packet); } public IBlueRow evaluate(DataPacket packet) { return _groupby_func(packet); }
@@ -29,7 +25,7 @@ namespace BCG
/// Serves as a quick way to access all rows belonging to the same group /// Serves as a quick way to access all rows belonging to the same group
/// </summary> /// </summary>
private bool myIdGuard = true; private bool myIdGuard = true;
private RowDictionaryTable myBookKeepingTable ; private RowDictionaryTable myBookKeepingTable;
private IGroupByEvaluator myGroupByEvaluator; private IGroupByEvaluator myGroupByEvaluator;
private IBlueTableSchema mySchema; //input schema, as output schema can differ (IGroupByEvaluator's private IBlueTableSchema mySchema; //input schema, as output schema can differ (IGroupByEvaluator's
//can map a schema to another //can map a schema to another
@@ -37,112 +33,98 @@ namespace BCG
private int myIdGenerator = 0; private int myIdGenerator = 0;
public GroupByStream(ViewStream stream, IEnumerable<string> groupby_cols, Func<DataPacket, IBlueRow> groupby_func) public GroupByStream(ViewStream stream, IEnumerable<string> groupby_cols, Func<DataPacket, IBlueRow> groupby_func)
: this(stream, new MyFuncGroupByEvaluator(groupby_cols, groupby_func)) : this(stream, new MyFuncGroupByEvaluator(groupby_cols, groupby_func)) { }
{ }
public GroupByStream (ViewStream stream, IGroupByEvaluator groupByEvaluator) public GroupByStream(ViewStream stream, IGroupByEvaluator groupByEvaluator)
: this (stream, groupByEvaluator, true) : this(stream, groupByEvaluator, true) { }
{}
public GroupByStream (ViewStream stream, IGroupByEvaluator groupbyEvaluator, bool idGuard) public GroupByStream(ViewStream stream, IGroupByEvaluator groupbyEvaluator, bool idGuard)
: base (stream) : base(stream) {
{
myGroupByEvaluator = groupbyEvaluator; myGroupByEvaluator = groupbyEvaluator;
myIdGuard = idGuard; myIdGuard = idGuard;
} }
protected override void myHandleFirstCall () protected override void myHandleFirstCall() {
{
mySchema = myLastArrivedPacket.schema; mySchema = myLastArrivedPacket.schema;
myOutputSchema = myGroupByEvaluator.getOutputSchema (mySchema); myOutputSchema = myGroupByEvaluator.getOutputSchema(mySchema);
myBookKeepingTable = new RowDictionaryTable (myLastArrivedPacket.newRows, myBookKeepingTable = new RowDictionaryTable(myLastArrivedPacket.newRows,
myGroupByEvaluator.groupByColumns); myGroupByEvaluator.groupByColumns);
GroupByOutputTable temp = new GroupByOutputTable (myOutputSchema); GroupByOutputTable temp = new GroupByOutputTable(myOutputSchema);
foreach (IBlueRowCollection rowGroup in myBookKeepingTable.getGroups()) foreach (IBlueRowCollection rowGroup in myBookKeepingTable.getGroups()) {
{ IBlueRow newRow = myEvaluate(new DataPacket(rowGroup,
IBlueRow newRow = myEvaluate (new DataPacket (rowGroup, rowGroup, new BlueTable(mySchema)));
rowGroup, new BlueTable (mySchema)));
if (newRow != null) if (newRow != null)
temp.addRow (newRow, myGetGroupString (rowGroup)); temp.addRow(newRow, myGetGroupString(rowGroup));
} }
myLastFiredPacket = new DataPacket (temp, new BlueTable(temp), new BlueTable (temp.schema)); myLastFiredPacket = new DataPacket(temp, new BlueTable(temp), new BlueTable(temp.schema));
} }
/// <summary> /// <summary>
/// Adding need not to anything as deletion already takes care /// Adding need not to anything as deletion already takes care
/// of addition /// of addition
/// </summary> /// </summary>
protected override void myHandleIncrementalAdd() {} protected override void myHandleIncrementalAdd() { }
/// <summary> /// <summary>
/// Both deletes and adds are handled here to make the intermediate results not /// Both deletes and adds are handled here to make the intermediate results not
/// appear in the spitted fired DataPacket (note this is done only in GroupByStream /// appear in the spitted fired DataPacket (note this is done only in GroupByStream
/// because of the nature of it) /// because of the nature of it)
/// </summary> /// </summary>
protected override void myHandleIncrementalDelete() protected override void myHandleIncrementalDelete() {
{
myFireSwitch = false; myFireSwitch = false;
RowDictionaryTable delGroups, addGroups; RowDictionaryTable delGroups, addGroups;
//form groups for deleted and added rows //form groups for deleted and added rows
myInitIncrementalChangeData (out delGroups, out addGroups); myInitIncrementalChangeData(out delGroups, out addGroups);
ArrayList handledAddGroups = new ArrayList (); ArrayList handledAddGroups = new ArrayList();
string groupRepString; string groupRepString;
foreach (IBlueRowCollection delGroup in delGroups.getGroups ()) foreach (IBlueRowCollection delGroup in delGroups.getGroups()) {
{
// BlueEventLog.logAssert (delGroup.Count > 0); // BlueEventLog.logAssert (delGroup.Count > 0);
groupRepString = myGetGroupString (delGroup); groupRepString = myGetGroupString(delGroup);
IBlueRowCollection addGroup = addGroups.getGroup (groupRepString) == null ? IBlueRowCollection addGroup = addGroups.getGroup(groupRepString) == null ?
new BlueTable (mySchema) : addGroups.getGroup (groupRepString); new BlueTable(mySchema) : addGroups.getGroup(groupRepString);
handledAddGroups.Add (addGroup); handledAddGroups.Add(addGroup);
IBlueRowCollection aggGroup = myBookKeepingTable.getGroup (groupRepString) == null ? IBlueRowCollection aggGroup = myBookKeepingTable.getGroup(groupRepString) == null ?
new BlueTable (mySchema) : myBookKeepingTable.getGroup (groupRepString); new BlueTable(mySchema) : myBookKeepingTable.getGroup(groupRepString);
IBlueRow newRow = myEvaluate (new DataPacket (aggGroup, addGroup, delGroup)); IBlueRow newRow = myEvaluate(new DataPacket(aggGroup, addGroup, delGroup));
myFireSwitch |= myMergeRow (newRow, groupRepString); myFireSwitch |= myMergeRow(newRow, groupRepString);
} }
foreach (IBlueRowCollection addGroup in addGroups.getGroups ()) foreach (IBlueRowCollection addGroup in addGroups.getGroups()) {
{
// BlueEventLog.logAssert (addGroup.Count > 0); // BlueEventLog.logAssert (addGroup.Count > 0);
if (!handledAddGroups.Contains (addGroup)) if (!handledAddGroups.Contains(addGroup)) {
{
//this is the case when there are rows added to a group and none //this is the case when there are rows added to a group and none
//have been removed, hence it 'escapes' from being dealt with in //have been removed, hence it 'escapes' from being dealt with in
//the loop above //the loop above
groupRepString = myGetGroupString (addGroup); groupRepString = myGetGroupString(addGroup);
IBlueRowCollection aggGroup = myBookKeepingTable.getGroup (groupRepString); IBlueRowCollection aggGroup = myBookKeepingTable.getGroup(groupRepString);
// BlueEventLog.logAssert (aggGroup != null && aggGroup.Count > 0); // BlueEventLog.logAssert (aggGroup != null && aggGroup.Count > 0);
IBlueRow newRow = myEvaluate (new DataPacket (aggGroup, addGroup, IBlueRow newRow = myEvaluate(new DataPacket(aggGroup, addGroup,
new BlueTable (aggGroup.schema))); new BlueTable(aggGroup.schema)));
myFireSwitch |= myMergeRow (newRow, groupRepString); myFireSwitch |= myMergeRow(newRow, groupRepString);
} }
} }
} }
private bool myMergeRow (IBlueRow newRow, string groupRepString) private bool myMergeRow(IBlueRow newRow, string groupRepString) {
{ IBlueRow existingRow = ((GroupByOutputTable)myLastFiredPacket.newRows).getRow(groupRepString);
IBlueRow existingRow = ((GroupByOutputTable) myLastFiredPacket.newRows).getRow (groupRepString);
//BlueEventLog.logAssert (newRow != null || existingRow != null); //BlueEventLog.logAssert (newRow != null || existingRow != null);
if (existingRow == null && newRow == null) if (existingRow == null && newRow == null)
return false; return false;
else if (existingRow != null && newRow != null && BlueDataUtility.computeRowEquality (existingRow, newRow)) else if (existingRow != null && newRow != null && BlueDataUtility.compute_equality(existingRow, newRow))
return false; return false;
else if (existingRow == null) else if (existingRow == null) {
{
//row added for the first time //row added for the first time
((GroupByOutputTable) myLastFiredPacket.newRows).addRow (newRow, groupRepString); ((GroupByOutputTable)myLastFiredPacket.newRows).addRow(newRow, groupRepString);
((BlueTable) myLastFiredPacket.addedRows).addRow (newRow); ((BlueTable)myLastFiredPacket.addedRows).addRow(newRow);
return true; return true;
} } else {
else ((GroupByOutputTable)myLastFiredPacket.newRows).removeRow(groupRepString);
{ ((BlueTable)myLastFiredPacket.deletedRows).addRow(existingRow);
((GroupByOutputTable) myLastFiredPacket.newRows).removeRow (groupRepString); if (newRow != null) {
((BlueTable) myLastFiredPacket.deletedRows).addRow (existingRow); ((GroupByOutputTable)myLastFiredPacket.newRows).addRow(newRow, groupRepString);
if (newRow != null) ((BlueTable)myLastFiredPacket.addedRows).addRow(newRow);
{
((GroupByOutputTable) myLastFiredPacket.newRows).addRow (newRow, groupRepString);
((BlueTable) myLastFiredPacket.addedRows).addRow (newRow);
} }
return true; return true;
} }
@@ -154,77 +136,68 @@ namespace BCG
/// </summary> /// </summary>
/// <param name="delGroups"></param> /// <param name="delGroups"></param>
/// <param name="addGroups"></param> /// <param name="addGroups"></param>
private void myInitIncrementalChangeData (out RowDictionaryTable delGroups, out RowDictionaryTable addGroups) private void myInitIncrementalChangeData(out RowDictionaryTable delGroups, out RowDictionaryTable addGroups) {
{
delGroups = delGroups =
new RowDictionaryTable (myLastArrivedPacket.deletedRows, myGroupByEvaluator.groupByColumns); new RowDictionaryTable(myLastArrivedPacket.deletedRows, myGroupByEvaluator.groupByColumns);
addGroups = addGroups =
new RowDictionaryTable (myLastArrivedPacket.addedRows, myGroupByEvaluator.groupByColumns); new RowDictionaryTable(myLastArrivedPacket.addedRows, myGroupByEvaluator.groupByColumns);
foreach (IBlueRow deletedRow in myLastArrivedPacket.deletedRows) foreach (IBlueRow deletedRow in myLastArrivedPacket.deletedRows)
myBookKeepingTable.removeRow (deletedRow); myBookKeepingTable.removeRow(deletedRow);
foreach (IBlueRow addedRow in myLastArrivedPacket.addedRows) foreach (IBlueRow addedRow in myLastArrivedPacket.addedRows)
myBookKeepingTable.addRow (addedRow); myBookKeepingTable.addRow(addedRow);
myLastFiredPacket.addedRows = new BlueTable (myOutputSchema); myLastFiredPacket.addedRows = new BlueTable(myOutputSchema);
myLastFiredPacket.deletedRows = new BlueTable (myOutputSchema); myLastFiredPacket.deletedRows = new BlueTable(myOutputSchema);
} }
protected override void myOnTableClear () protected override void myOnTableClear() {
{
if (myBookKeepingTable.Count == 0) if (myBookKeepingTable.Count == 0)
return; //ie there arent any rows, so no need to optimize the 'cleansing' process return; //ie there arent any rows, so no need to optimize the 'cleansing' process
myLastFiredPacket.deletedRows = new BlueTable (myLastFiredPacket.newRows); myLastFiredPacket.deletedRows = new BlueTable(myLastFiredPacket.newRows);
myLastFiredPacket.addedRows = new BlueTable (myLastFiredPacket.deletedRows.schema); myLastFiredPacket.addedRows = new BlueTable(myLastFiredPacket.deletedRows.schema);
(myLastFiredPacket.newRows as GroupByOutputTable).clear (); (myLastFiredPacket.newRows as GroupByOutputTable).clear();
myBookKeepingTable.clear (); myBookKeepingTable.clear();
myGroupByEvaluator.clear (); myGroupByEvaluator.clear();
} }
private IBlueRow myEvaluate (DataPacket dp) private IBlueRow myEvaluate(DataPacket dp) {
{ IBlueRow evalRow = myGroupByEvaluator.evaluate(dp);
IBlueRow evalRow = myGroupByEvaluator.evaluate (dp); return evalRow == null ? null :
return evalRow == null ? null :
myIdGuard ? myIdGuard ?
BlueDataUtility.getNewReplacedRow (evalRow, myIdGenerator++, "id") : evalRow; BlueDataUtility.getNewReplacedRow(evalRow, myIdGenerator++, "id") : evalRow;
} }
private string myGetGroupString (IBlueRowCollection group) private string myGetGroupString(IBlueRowCollection group) {
{ return BlueDataUtility.rowToString(BlueDataUtility.extractRow(group, 0), myGroupByEvaluator.groupByColumns);
return BlueDataUtility.rowToString(BlueDataUtility.extractRow (group, 0), myGroupByEvaluator.groupByColumns);
} }
protected override void myOnLastSubscriber () protected override void myOnLastSubscriber() {
{
//the packets are initialzed to null, so that if the subscription count goes to 0, and then this stream //the packets are initialzed to null, so that if the subscription count goes to 0, and then this stream
//gets resubscribed, we start the process of building data again, and treat the callback as the first //gets resubscribed, we start the process of building data again, and treat the callback as the first
//callback. //callback.
myInit (); myInit();
myStream.onChange -= new DataStream.ChangeDelegate (myChangeHandler); myStream.onChange -= new DataStream.ChangeDelegate(myChangeHandler);
} }
protected override void myInit () protected override void myInit() {
{ base.myInit();
base.myInit (); if (myBookKeepingTable != null) {
if (myBookKeepingTable != null)
{
//to avoid calling init before the first callback //to avoid calling init before the first callback
myBookKeepingTable.clear (); myBookKeepingTable.clear();
myGroupByEvaluator.clear (); myGroupByEvaluator.clear();
} }
} }
public static string getRepString (DataPacket dp, string[] colNames) public static string getRepString(DataPacket dp, string[] colNames) {
{ return BlueDataUtility.rowToString(getRepRow(dp), colNames);
return BlueDataUtility.rowToString (getRepRow (dp), colNames);
} }
public static IBlueRow getRepRow (DataPacket dp) public static IBlueRow getRepRow(DataPacket dp) {
{
if (dp.newRows.Count > 0) if (dp.newRows.Count > 0)
return BlueDataUtility.extractRow (dp.newRows, 0); return BlueDataUtility.extractRow(dp.newRows, 0);
else if (dp.addedRows.Count > 0) else if (dp.addedRows.Count > 0)
return BlueDataUtility.extractRow (dp.addedRows, 0); return BlueDataUtility.extractRow(dp.addedRows, 0);
else if (dp.deletedRows.Count > 0) else if (dp.deletedRows.Count > 0)
return BlueDataUtility.extractRow (dp.deletedRows, 0); return BlueDataUtility.extractRow(dp.deletedRows, 0);
// BlueEventLog.logAssert (false, "Illegal Data Packet"); // BlueEventLog.logAssert (false, "Illegal Data Packet");
return null; return null;
} }
@@ -237,22 +210,21 @@ namespace BCG
/// <param name="newValue"></param> /// <param name="newValue"></param>
/// <param name="isAdd"></param> /// <param name="isAdd"></param>
/// <returns></returns> /// <returns></returns>
public static object incrementalAdd (object lastValue, object newValue, bool isAdd) public static object incrementalAdd(object lastValue, object newValue, bool isAdd) {
{ if (lastValue == null || lastValue.Equals(DBNull.Value))
if (lastValue == null || lastValue.Equals (DBNull.Value))
return newValue; return newValue;
// BlueEventLog.logAssert (lastValue.GetType().Equals (typeof(Int32)) && newValue.GetType().Equals (typeof(Int32)) || // BlueEventLog.logAssert (lastValue.GetType().Equals (typeof(Int32)) && newValue.GetType().Equals (typeof(Int32)) ||
// lastValue.GetType().Equals (typeof(Double)) && newValue.GetType().Equals (typeof(Double)) || // lastValue.GetType().Equals (typeof(Double)) && newValue.GetType().Equals (typeof(Double)) ||
// lastValue.GetType().Equals (typeof(Decimal)) && newValue.GetType().Equals (typeof(Decimal))); // lastValue.GetType().Equals (typeof(Decimal)) && newValue.GetType().Equals (typeof(Decimal)));
Object retVal = null; Object retVal = null;
if (newValue.GetType().Equals (typeof(int))) if (newValue.GetType().Equals(typeof(int)))
retVal = isAdd ? (int)lastValue + (int)newValue : (int)lastValue - (int)newValue; retVal = isAdd ? (int)lastValue + (int)newValue : (int)lastValue - (int)newValue;
else if (newValue.GetType().Equals (typeof(Double))) else if (newValue.GetType().Equals(typeof(Double)))
retVal = isAdd ? (Double)lastValue + (Double)newValue : (Double)lastValue - (Double)newValue; retVal = isAdd ? (Double)lastValue + (Double)newValue : (Double)lastValue - (Double)newValue;
else if (lastValue.GetType().Equals (typeof(Decimal))) else if (lastValue.GetType().Equals(typeof(Decimal)))
retVal = isAdd ? (Decimal)lastValue + (Decimal)newValue : (Decimal)lastValue - (Decimal)newValue; retVal = isAdd ? (Decimal)lastValue + (Decimal)newValue : (Decimal)lastValue - (Decimal)newValue;
else{} else { }
// BlueEventLog.logAssert (false, "Illegal type"); // BlueEventLog.logAssert (false, "Illegal type");
return retVal; return retVal;
} }
@@ -0,0 +1,31 @@
namespace BCG {
using System.Collections.Generic;
public class KeyValueToRelationalStream : ViewStream {
private readonly ViewStream _kv_str;
private readonly string _doc_id_col, _key_col, _val_col;
public KeyValueToRelationalStream(ViewStream kv_str, string doc_id_col, string key_col, string val_col) {
_kv_str = kv_str;
_doc_id_col = doc_id_col;
_key_col = key_col;
_val_col = val_col;
}
protected override void myOnFirstSubscriber() {
_kv_str.onChange += _on_str_update;
}
protected override void myOnLastSubscriber() {
_kv_str.onChange -= _on_str_update;
}
private void _on_str_update(object dp_obj) {
DataPacket dp = dp_obj as DataPacket;
var rows = dp.newRows;
var rv = BlueDataUtility.keyvalue_to_relational<string>(rows, _doc_id_col, _key_col, _val_col);
var dp_out = BlueDataUtility.build_dp_inc(rv, myLastValue as DataPacket, true);
myFireEvent(dp_out);
}
}
}
@@ -1,51 +1,64 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using BCG; using BCG;
using BCG.Utilities; using BCG.Utilities;
namespace BCG namespace BCG {
{ public class LiteralStream : ViewStream {
public class LiteralStream : ViewStream
{ public static List<Tuple<ColumnInfo, object>> parse_columns(string key_value_pairs) {
public LiteralStream(string tableName, string schema, string value) List<Tuple<ColumnInfo, object>> rv = new List<Tuple<ColumnInfo, object>>();
{ string[] pairs = key_value_pairs.Split(' ');
string [] columns = schema.Split(' '); foreach (string p in pairs) {
string[] kvp = p.Split(':');
string col_name = kvp[0];
string val = kvp[1];
var tup = BlueDataUtility.guess_type(val);
var ci = new ColumnInfo(col_name, rv.Count, tup.Item1);
rv.Add(Tuple.Create(ci, tup.Item2));
}
return rv;
}
public LiteralStream(string tableName, string schema, string value) {
string[] columns = schema.Split(' ');
ColumnInfo [] ci = new ColumnInfo[columns.Length + 1]; ColumnInfo[] ci = new ColumnInfo[columns.Length + 1];
ci[0] = new ColumnInfo("id",0,typeof(int)); ci[0] = new ColumnInfo("id", 0, typeof(int));
int n = 1; int n = 1;
foreach (string c in columns) foreach (string c in columns) {
{ string[] columnAndType = c.Split('/');
string [] columnAndType = c.Split('/');
if (columnAndType.Length == 1) if (columnAndType.Length == 1)
ci[n] = new ColumnInfo(c,n,typeof(double)); ci[n] = new ColumnInfo(c, n, typeof(double));
else else
ci[n] = new ColumnInfo(columnAndType[0],n,Type.GetType("System." + columnAndType[1],true)); ci[n] = new ColumnInfo(columnAndType[0], n, Type.GetType("System." + columnAndType[1], true));
n++; n++;
} }
BlueTable t = new BlueTable(new BlueTableSchema(tableName,ci)); BlueTable t = new BlueTable(new BlueTableSchema(tableName, ci));
string [] rows = value.Split(';'); string[] rows = value.Split(';');
n = 0; n = 0;
foreach (string r in rows) foreach (string r in rows)
try try {
{ if (r == string.Empty)
if(r == string.Empty)
continue; continue;
t.addRow( t.addRow(
BlueDataUtility.createRowFromCSVFileRow (r, t.schema,++n)); BlueDataUtility.createRowFromCSVFileRow(r, t.schema, ++n));
} } catch (Exception e) {
catch (Exception e)
{
throw (new Exception("Error occured at line: " + n.ToString() + " " + e.Message)); throw (new Exception("Error occured at line: " + n.ToString() + " " + e.Message));
} }
mySetRealSource(new BlueRowCollectionStaticStream(t)); mySetRealSource(new BlueRowCollectionStaticStream(t));
} }
public LiteralStream(string schema, string value) : this ("literal",schema, value) public LiteralStream(string schema, string value) : this("literal", schema, value) { }
{}
// public LiteralStream(string value) {
// }
} }
} }
@@ -1,24 +1,24 @@
using System; // using System;
namespace BCG // namespace BCG
{ // {
public class DynamicUntypedToTypedMapper : IDynamicStreamMapper // public class DynamicUntypedToTypedMapper : IDynamicStreamMapper
{ // {
IBlueTableSchema mySchema; // IBlueTableSchema mySchema;
public IBlueRow map (IBlueRow row) // public IBlueRow map (IBlueRow row)
{ // {
if (mySchema == null) // if (mySchema == null)
{ // {
ColumnInfo[] cis = new ColumnInfo [row.schema.columnInfo.Length]; // ColumnInfo[] cis = new ColumnInfo [row.schema.columnInfo.Length];
int i = 0; // int i = 0;
foreach (ColumnInfo ci in row.schema.columnInfo) // foreach (ColumnInfo ci in row.schema.columnInfo)
cis[i++] = ci.colType == null ? // cis[i++] = ci.colType == null ?
new ColumnInfo (ci.colName, ci.colNo, row[ci.colNo].GetType()) : // new ColumnInfo (ci.colName, ci.colNo, row[ci.colNo].GetType()) :
new ColumnInfo (ci.colName, ci.colNo, row[ci.colNo].GetType(), ci.colValue); // new ColumnInfo (ci.colName, ci.colNo, row[ci.colNo].GetType(), ci.colValue);
mySchema = new BlueTableSchema (row.schema.tableName, cis); // mySchema = new BlueTableSchema (row.schema.tableName, cis);
} // }
return new BlueRow (mySchema, row); // return new BlueRow (mySchema, row);
} // }
} // }
} // }
@@ -8,8 +8,7 @@ using mbts;
using mbts.spark; using mbts.spark;
using mbts.config; using mbts.config;
namespace BCG namespace BCG {
{
/// <summary> /// <summary>
@@ -18,27 +17,48 @@ namespace BCG
/// desired row ie newRow = f(row), where f is the mapping fucntion. Note that the id /// desired row ie newRow = f(row), where f is the mapping fucntion. Note that the id
/// is preserved across the rows, ie row["id"] = f(row)["id"] /// is preserved across the rows, ie row["id"] = f(row)["id"]
/// </summary> /// </summary>
[DataStreamUserRespresentation (false)] [DataStreamUserRespresentation(false)]
public class MapStream : MethodDrivenStream public class MapStream : MethodDrivenStream {
{ private HighPerformanceTimer t = new HighPerformanceTimer();
private HighPerformanceTimer t = new HighPerformanceTimer ();
protected IStreamMapper myMapper; protected IStreamMapper myMapper;
protected IChangeableStreamMapper myChangeableMapper = null; protected IChangeableStreamMapper myChangeableMapper = null;
private bool myUseNewMap = Configuration.get<DataStreamConfig>().UseNewMap; private bool myUseNewMap = Configuration.get<DataStreamConfig>().UseNewMap;
public MapStream(ViewStream vs, IStreamMapper mapper) : base (vs) public class FuncWrapper : IStreamMapper {
{ private Func<IBlueTableSchema, IBlueTableSchema> _schema_map_func;
if (myUseNewMap) Func<IBlueRow, IBlueRow> _row_map_func;
mySetRealSource (new SuperMapStream (vs, mapper));
else public FuncWrapper(Func<IBlueTableSchema, IBlueTableSchema> schema_map_func,
myMapper = mapper; Func<IBlueRow, IBlueRow> row_map_func) {
_schema_map_func = schema_map_func;
_row_map_func = row_map_func;
}
public IBlueTableSchema getOutputSchema(IBlueTableSchema input_schema) {
return _schema_map_func(input_schema);
}
public IBlueRow map(IBlueRow row) {
return _row_map_func(row);
}
} }
public MapStream(ViewStream vs, IChangeableStreamMapper mapper) : this (vs,(IStreamMapper)mapper)
{ public MapStream(ViewStream vs, IStreamMapper mapper) : base(vs) {
if (myUseNewMap) if (myUseNewMap)
mySetRealSource(new SuperMapStream(vs, mapper)); mySetRealSource(new SuperMapStream(vs, mapper));
else else
{ myMapper = mapper;
}
public MapStream(ViewStream vs, Func<IBlueTableSchema, IBlueTableSchema> schema_map_func,
Func<IBlueRow, IBlueRow> row_map_func)
:
this(vs, new FuncWrapper(schema_map_func, row_map_func)) {
}
public MapStream(ViewStream vs, IChangeableStreamMapper mapper) : this(vs, (IStreamMapper)mapper) {
if (myUseNewMap)
mySetRealSource(new SuperMapStream(vs, mapper));
else {
mapper.onMapperChange += new MapperChangeDelegate(myMapperChanged); mapper.onMapperChange += new MapperChangeDelegate(myMapperChanged);
myChangeableMapper = mapper; myChangeableMapper = mapper;
} }
@@ -47,77 +67,68 @@ namespace BCG
/// <summary> /// <summary>
/// Gets or sets the value of the mapper. Setting the value will result in re /// Gets or sets the value of the mapper. Setting the value will result in re
/// </summary> /// </summary>
private void myMapperChanged () private void myMapperChanged() {
{
if (myLastArrivedPacket != null) if (myLastArrivedPacket != null)
myChangeHandler (new DataPacket (myLastArrivedPacket.newRows, myChangeHandler(new DataPacket(myLastArrivedPacket.newRows,
myLastArrivedPacket.newRows, myLastArrivedPacket.newRows,
myLastArrivedPacket.newRows)); myLastArrivedPacket.newRows));
} }
protected override void myHandleFirstCall () protected override void myHandleFirstCall() {
{
IBlueTableSchema outputSchema = myMapper.getOutputSchema(myLastArrivedPacket.newRows.schema);
IBlueTableSchema outputSchema = myMapper.getOutputSchema (myLastArrivedPacket.newRows.schema); myLastFiredPacket = new DataPacket();
myLastFiredPacket = new DataPacket (); myLastFiredPacket.newRows = new BlueTable(outputSchema);
myLastFiredPacket.newRows = new BlueTable (outputSchema); myLastFiredPacket.deletedRows = new BlueTable(outputSchema);
myLastFiredPacket.deletedRows = new BlueTable (outputSchema);
foreach (IBlueRow row in myLastArrivedPacket.newRows) foreach (IBlueRow row in myLastArrivedPacket.newRows)
((BlueTable)(myLastFiredPacket.newRows)).addRow (myMapper.map(row)); ((BlueTable)(myLastFiredPacket.newRows)).addRow(myMapper.map(row));
myLastFiredPacket.addedRows = new BlueTable(myLastFiredPacket.newRows); myLastFiredPacket.addedRows = new BlueTable(myLastFiredPacket.newRows);
} }
protected override void myHandleIncrementalAdd() protected override void myHandleIncrementalAdd() {
{
//t.start (); //t.start ();
myLastFiredPacket.addedRows = new BlueTable (myLastFiredPacket.newRows.schema); myLastFiredPacket.addedRows = new BlueTable(myLastFiredPacket.newRows.schema);
foreach (IBlueRow row in myLastArrivedPacket.addedRows) foreach (IBlueRow row in myLastArrivedPacket.addedRows) {
{ IBlueRow newRow = myMapper.map(row);
IBlueRow newRow = myMapper.map (row); (myLastFiredPacket.newRows as BlueTable).addRow(newRow);
(myLastFiredPacket.newRows as BlueTable).addRow (newRow); (myLastFiredPacket.addedRows as BlueTable).addRow(newRow);
(myLastFiredPacket.addedRows as BlueTable).addRow (newRow);
} }
//t.stop (); //t.stop ();
//System.Diagnostics.Trace.WriteLine ("adding " + myLastFiredPacket.addedRows.Count.ToString () + " : " + t.lastIntervalTime); //System.Diagnostics.Trace.WriteLine ("adding " + myLastFiredPacket.addedRows.Count.ToString () + " : " + t.lastIntervalTime);
//System.Diagnostics.Trace.WriteLine (" "); //System.Diagnostics.Trace.WriteLine (" ");
} }
protected override void myHandleIncrementalDelete() protected override void myHandleIncrementalDelete() {
{
//t.start (); //t.start ();
myLastFiredPacket.deletedRows = new BlueTable (myLastFiredPacket.newRows.schema); myLastFiredPacket.deletedRows = new BlueTable(myLastFiredPacket.newRows.schema);
foreach (IBlueRow row in myLastArrivedPacket.deletedRows) foreach (IBlueRow row in myLastArrivedPacket.deletedRows) {
{
IBlueRow delRow = (myLastFiredPacket.newRows as BlueTable)[(int)row["id"]]; IBlueRow delRow = (myLastFiredPacket.newRows as BlueTable)[(int)row["id"]];
(myLastFiredPacket.deletedRows as BlueTable).addRow (delRow); (myLastFiredPacket.deletedRows as BlueTable).addRow(delRow);
(myLastFiredPacket.newRows as BlueTable).deleteRow (row); (myLastFiredPacket.newRows as BlueTable).deleteRow(row);
} }
//t.stop (); //t.stop ();
//System.Diagnostics.Trace.WriteLine ("deleting " + myLastFiredPacket.deletedRows.Count.ToString () + " : " + t.lastIntervalTime); //System.Diagnostics.Trace.WriteLine ("deleting " + myLastFiredPacket.deletedRows.Count.ToString () + " : " + t.lastIntervalTime);
} }
protected override void myOnFirstSubscriber()
{ protected override void myOnFirstSubscriber() {
myStream.onChange += new DataStream.ChangeDelegate (myChangeHandler); myStream.onChange += new DataStream.ChangeDelegate(myChangeHandler);
} }
protected override void myOnLastSubscriber () protected override void myOnLastSubscriber() {
{ myInit();
myInit ();
if (myStream != null) if (myStream != null)
myStream.onChange -= new DataStream.ChangeDelegate (myChangeHandler); myStream.onChange -= new DataStream.ChangeDelegate(myChangeHandler);
} }
protected override void myOnTableClear () protected override void myOnTableClear() {
{
myLastFiredPacket.deletedRows = myLastFiredPacket.newRows; myLastFiredPacket.deletedRows = myLastFiredPacket.newRows;
myLastFiredPacket.newRows = new BlueTable (myLastFiredPacket.deletedRows.schema); myLastFiredPacket.newRows = new BlueTable(myLastFiredPacket.deletedRows.schema);
myLastFiredPacket.addedRows = new BlueTable (myLastFiredPacket.deletedRows.schema); myLastFiredPacket.addedRows = new BlueTable(myLastFiredPacket.deletedRows.schema);
} }
} }
/* /*
@@ -1,12 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using BCG.Utilities; using BCG.Utilities;
using BCG.Utilities.General; using BCG.Utilities.General;
using mbts; using mbts;
namespace BCG namespace BCG {
{
/// <summary> /// <summary>
/// SuperMap gives the user the ability /// SuperMap gives the user the ability
/// to map one row to one or more rows /// to map one row to one or more rows
@@ -17,13 +18,11 @@ namespace BCG
/// can chage itself and raise an event causing /// can chage itself and raise an event causing
/// a remapping to happen /// a remapping to happen
/// </summary> /// </summary>
public class SuperMapStream : ViewStream public class SuperMapStream : ViewStream {
{
#region super mapper that wraps around stream mapper #region super mapper that wraps around stream mapper
private class MyMappingWrapper : ISuperStreamMapper private class MyMappingWrapper : ISuperStreamMapper {
{
private IStreamMapper myMapper; private IStreamMapper myMapper;
public MyMappingWrapper(IStreamMapper mapper) { myMapper = mapper; } public MyMappingWrapper(IStreamMapper mapper) { myMapper = mapper; }
#region ISuperStreamMapper Members #region ISuperStreamMapper Members
@@ -32,8 +31,7 @@ namespace BCG
public IBlueRow[] map(IBlueRow inputRow) { return new IBlueRow[] { myMapper.map(inputRow) }; } public IBlueRow[] map(IBlueRow inputRow) { return new IBlueRow[] { myMapper.map(inputRow) }; }
public event MapperChangeDelegate onMapperChange public event MapperChangeDelegate onMapperChange {
{
add { } add { }
remove { } remove { }
} }
@@ -42,21 +40,18 @@ namespace BCG
} }
#endregion #endregion
private class MyFuncWrapper : ISuperStreamMapper private class MyFuncWrapper : ISuperStreamMapper {
{
private Func<IBlueTableSchema, IBlueTableSchema> _get_schema; private Func<IBlueTableSchema, IBlueTableSchema> _get_schema;
private Func<IBlueRow, IEnumerable<IBlueRow>> _map_rows; private Func<IBlueRow, IEnumerable<IBlueRow>> _map_rows;
public MyFuncWrapper(Func<IBlueTableSchema, IBlueTableSchema> get_schema, public MyFuncWrapper(Func<IBlueTableSchema, IBlueTableSchema> get_schema,
Func<IBlueRow, IEnumerable<IBlueRow>> map_rows) Func<IBlueRow, IEnumerable<IBlueRow>> map_rows) {
{
_get_schema = get_schema; _get_schema = get_schema;
_map_rows = map_rows; _map_rows = map_rows;
} }
public IBlueTableSchema getOutputSchema(IBlueTableSchema schema) { return _get_schema(schema); } public IBlueTableSchema getOutputSchema(IBlueTableSchema schema) { return _get_schema(schema); }
public IBlueRow[] map(IBlueRow r) public IBlueRow[] map(IBlueRow r) {
{
IEnumerable<IBlueRow> rows = _map_rows(r); IEnumerable<IBlueRow> rows = _map_rows(r);
return rows == null ? new IBlueRow[] { } : new List<IBlueRow>(rows).ToArray(); return rows == null ? new IBlueRow[] { } : new List<IBlueRow>(rows).ToArray();
} }
@@ -76,19 +71,15 @@ namespace BCG
public SuperMapStream(ViewStream vs, Func<IBlueTableSchema, IBlueTableSchema> get_schema, public SuperMapStream(ViewStream vs, Func<IBlueTableSchema, IBlueTableSchema> get_schema,
Func<IBlueRow, IEnumerable<IBlueRow>> map_rows) Func<IBlueRow, IEnumerable<IBlueRow>> map_rows)
: this(vs, new MyFuncWrapper(get_schema, map_rows)) : this(vs, new MyFuncWrapper(get_schema, map_rows)) { }
{ }
public SuperMapStream(ViewStream vs, IBlueTableSchema out_schema, Func<IBlueRow, IEnumerable<IBlueRow>> map_rows) public SuperMapStream(ViewStream vs, IBlueTableSchema out_schema, Func<IBlueRow, IEnumerable<IBlueRow>> map_rows)
: this(vs, s => out_schema, map_rows) : this(vs, s => out_schema, map_rows) { }
{ }
public SuperMapStream(ViewStream vs, IStreamMapper mapper) public SuperMapStream(ViewStream vs, IStreamMapper mapper)
: this(vs, new MyMappingWrapper(mapper)) : this(vs, new MyMappingWrapper(mapper)) { }
{ }
public SuperMapStream(ViewStream vs, ISuperStreamMapper mapper) public SuperMapStream(ViewStream vs, ISuperStreamMapper mapper) {
{
myStream = vs; myStream = vs;
myMapper = mapper; myMapper = mapper;
myMapper.onMapperChange += new MapperChangeDelegate(myHandleMapChange); myMapper.onMapperChange += new MapperChangeDelegate(myHandleMapChange);
@@ -96,8 +87,7 @@ namespace BCG
protected override void myOnFirstSubscriber() { myStream.onChange += new ChangeDelegate(myHandleData); } protected override void myOnFirstSubscriber() { myStream.onChange += new ChangeDelegate(myHandleData); }
protected override void myOnLastSubscriber() protected override void myOnLastSubscriber() {
{
myStream.onChange -= new ChangeDelegate(myHandleData); myStream.onChange -= new ChangeDelegate(myHandleData);
myRows = null; myRows = null;
myBaseRows = null; myBaseRows = null;
@@ -105,8 +95,7 @@ namespace BCG
//myMapper.onMapperChange -= new MapperChangeDelegate(myHandleMapChange); //myMapper.onMapperChange -= new MapperChangeDelegate(myHandleMapChange);
} }
private void myHandleData(object newValue) private void myHandleData(object newValue) {
{
DataPacket idp = newValue as DataPacket; DataPacket idp = newValue as DataPacket;
//HighPerformanceTimer timer = new HighPerformanceTimer(); //HighPerformanceTimer timer = new HighPerformanceTimer();
//timer.start(); //timer.start();
@@ -117,24 +106,19 @@ namespace BCG
BlueTable dels = new BlueTable(myRows.schema), BlueTable dels = new BlueTable(myRows.schema),
adds = new BlueTable(myRows.schema); adds = new BlueTable(myRows.schema);
foreach (IBlueRow r in dp.deletedRows) foreach (IBlueRow r in dp.deletedRows) {
{
List<IBlueRow> mappedRows = myMap[(int)r["id"]]; List<IBlueRow> mappedRows = myMap[(int)r["id"]];
foreach (IBlueRow mr in mappedRows) foreach (IBlueRow mr in mappedRows) {
{
dels.addRow(mr); dels.addRow(mr);
myRows.deleteRow(mr); myRows.deleteRow(mr);
} }
myMap.Remove((int)r["id"]); myMap.Remove((int)r["id"]);
} }
foreach (IBlueRow r in dp.addedRows) foreach (IBlueRow r in dp.addedRows) {
{
IBlueRow[] mappedRows = myMapper.map(r); IBlueRow[] mappedRows = myMapper.map(r);
foreach (IBlueRow mr in mappedRows) foreach (IBlueRow mr in mappedRows) {
{
IBlueRow idChangedMapRow = generate_ids ? BlueDataUtility.getNewReplacedRow(mr, myID++, "id") : mr; IBlueRow idChangedMapRow = generate_ids ? BlueDataUtility.getNewReplacedRow(mr, myID++, "id") : mr;
if (!myMap.ContainsKey((int)r["id"])) if (!myMap.ContainsKey((int)r["id"])) {
{
myMap.Add((int)r["id"], new List<IBlueRow>()); myMap.Add((int)r["id"], new List<IBlueRow>());
} }
myMap[(int)r["id"]].Add(idChangedMapRow); myMap[(int)r["id"]].Add(idChangedMapRow);
@@ -145,13 +129,12 @@ namespace BCG
//timer.stop(); //timer.stop();
// if (timer.lastIntervalTime > 20) // if (timer.lastIntervalTime > 20)
// {}//mbts.Logger.log(bts.log.Level.Info, bts.log.Subsystem.gen, String.Format("SuperMapper:myHandlerData for mapper {0} took {1} msecs", myMapper.GetType().ToString(), timer.lastIntervalTime)); // {}//mbts.Logger.log(bts.log.Level.Info, bts.log.Subsystem.gen, String.Format("SuperMapper:myHandlerData for mapper {0} took {1} msecs", myMapper.GetType().ToString(), timer.lastIntervalTime));
// myFireEvent(new DataPacket(myRows, adds, dels)); myFireEvent(new DataPacket(myRows, adds, dels));
} }
private void myHandleMapChange() private void myHandleMapChange() {
{
if (myBaseRows != null) if (myBaseRows != null)
myHandleData(new DataPacket(myBaseRows, new BlueTable (myBaseRows), new BlueTable (myBaseRows))); myHandleData(new DataPacket(myBaseRows, new BlueTable(myBaseRows), new BlueTable(myBaseRows)));
} }
} }
} }
@@ -0,0 +1,142 @@
using BCG;
using System;
using System.IO;
using MongoDB.Bson;
using BCG.Utilities.General;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.Intrinsics.X86;
namespace bts {
// listens to the underlying stream, and writes each seriialized packet in a
// seperate file
[DataStreamUserRespresentation("dp_recorder")]
public class DataPacketRecorderStream : ViewStream {
private ViewStream _base_stream;
private readonly string _folder;
StreamIOSerializationController _serializer = new StreamIOSerializationController();
private UInt32 _n_updates = 0;
public DataPacketRecorderStream(ViewStream base_stream, string folder) {
_base_stream = base_stream;
_folder = folder;
}
protected override void myOnFirstSubscriber() {
_base_stream.onChange += _handle_update;
}
protected override void myOnLastSubscriber() {
_base_stream.onChange -= _handle_update;
}
private void _handle_update(object dp_obj) {
DataPacket dp = dp_obj as DataPacket;
byte[] ser_data = null;
if (_n_updates == 0) {
StreamIOMessage.CreateMessage cr_msg = new StreamIOMessage.CreateMessage(dp.newRows);
ser_data = _serializer.serialize(new StreamIOMessage(cr_msg));
} else {
StreamIOMessage.MultipleRemoveAddMessage mra = new StreamIOMessage.MultipleRemoveAddMessage(dp.deletedRows, dp.addedRows);
ser_data = _serializer.serialize(new StreamIOMessage(mra));
}
Log.assert(ser_data != null);
_n_updates++;
string file_name = $"{_folder}\\{_n_updates}.bin";
_write_to_file(ser_data, file_name);
myFireEvent(dp);
}
private static void _write_to_file(byte[] data, string file_name) {
using (FileStream fs = new FileStream(file_name, FileMode.Create)) {
// Write the byte array to the file
fs.Write(data, 0, data.Length);
}
}
}
[DataStreamUserRespresentation("dp_replay")]
public class DataPacketReplayStream : ViewStream, IWorker {
private ViewStreamDatabase _vsd;
private readonly string _folder_path;
private readonly TimeSpan _fire_period;
IStreamMsgDeserilizer _deser = new StreamIODeserializationController();
private int _file_ptr = 0;
private List<Tuple<string, byte[]>> _file_data = new List<Tuple<string, byte[]>>();
private BlueTable _state = null;
public DataPacketReplayStream(string folder_path, string fire_period)
:
this(ViewStreamDatabase.instance, folder_path, TimeBasedFilter.parse_duration(fire_period)) {
}
public DataPacketReplayStream(ViewStreamDatabase vsd, string folder_path, TimeSpan fire_period) {
_vsd = vsd;
_folder_path = folder_path;
_fire_period = fire_period;
}
protected override void myOnFirstSubscriber() {
MasterWorker.getInstance(false).addWorker(this, _fire_period);
_load_all_files();
}
protected override void myOnLastSubscriber() {
MasterWorker.getInstance(false).removeWorker(this);
}
public void doWork() {
if (_file_ptr >= _file_data.Count())
// we can set _file_ptr to 0 and keep going as well
return;
var curr_d = _file_data[_file_ptr++];
var hext_txt = StreamSerializationUtils.to_hex(curr_d.Item2);
StreamIOMessage msg = _deser.deserialize(curr_d.Item2);
Log.Gen.info($"DataPacketReplayStream.doWork packet no : {_file_ptr} file : {curr_d.Item1} data: {hext_txt}");
switch (msg.op) {
case StreamIOMessage.StreamOp.CREATE: {
_state = new BlueTable(msg.create_message.rows);
break;
}
case StreamIOMessage.StreamOp.MULTIPLE_REMOVE_ADD: {
var mra = msg.multiple_remove_add_message;
foreach (IBlueRow r in mra.removed_rows)
_state.deleteRow(r);
foreach (IBlueRow r in mra.added_rows)
_state.addRow(r);
break;
}
}
var dp = BlueDataUtility.build_dp_inc(_state, myLastValue == null ? null : myLastValue as DataPacket, false);
myFireEvent(dp);
}
private void _load_all_files() {
Func<string, string> extract_file_name = (string full_path) => {
string fn = full_path.Split("\\").Last();
fn = fn.Split(".").First();
return fn;
};
string[] bin_files = Directory.GetFiles(_folder_path, "*.bin");
// Iterate over the .bin files and perform an action
foreach (string file in bin_files) {
byte[] file_data = File.ReadAllBytes(file);
_file_data.Add(Tuple.Create(file, file_data));
}
_file_data.Sort((Tuple<string, byte[]> t1, Tuple<string, byte[]> t2) => {
string fn1 = extract_file_name(t1.Item1);
string fn2 = extract_file_name(t2.Item1);
int fn_i1 = Int32.Parse(fn1);
int fn_i2 = Int32.Parse(fn2);
if (fn_i1 < fn_i2)
return -1;
else if (fn_i1 == fn_i2)
return 0;
else if (fn_i1 > fn_i2)
return 1;
return 0;
});
}
}
}
@@ -0,0 +1,195 @@
using BCG;
using BCG.Utilities.General;
using System.Collections.Generic;
//using MongoDB.Driver;
using System;
using System.IO;
using System.Linq;
namespace bts {
public class PubSubTestingStream : ViewStream, IWorker {
public class PayloadMessage {
public int msg_id = 0;
public string guid;
public Int64 travel_epoch_ms = 0;
public byte[] payload = null;
public PayloadMessage(int msg_id_args, Int64 send_epoch_args, int payload_size, byte payload_byte) {
msg_id = msg_id_args;
travel_epoch_ms = send_epoch_args;
payload = new byte[payload_size];
for (int i = 0; i < payload_size; i++) {
payload[i] = payload_byte;
}
}
private PayloadMessage() { }
public PayloadMessage(int msg_id, int payload_size, byte payload_byte) :
this(msg_id, PubSubTestingStream.epoch_now(), payload_size, payload_byte) { }
public byte[] serialize() {
var str = new MemoryStream();
BinaryWriter bw = new BinaryWriter(str);
bw.Write(msg_id);
bw.Write(guid);
bw.Write(travel_epoch_ms);
bw.Write(payload.Length);
bw.Write(payload);
str.Position = 0;
var bytes = str.ToArray();
return bytes;
}
public static PayloadMessage deserialize(byte[] ser_bytes) {
var str = new MemoryStream(ser_bytes);
BinaryReader br = new BinaryReader(str);
int msg_id = br.ReadInt32();
string guid = br.ReadString();
Int64 epoch = br.ReadInt64();
int len = br.ReadInt32();
var payload = br.ReadBytes(len);
return new PayloadMessage() {
msg_id = msg_id,
guid = guid,
travel_epoch_ms = epoch,
payload = payload
};
}
}
//public void
private readonly int _msg_size;
private readonly TimeSpan _publish_period;
private DateTime _last_publish_time = DateTime.MinValue;
private PublisherCore _pub_core = new PublisherCore();
private BlueTable _table;
private int _n_pubs = 0;
private readonly int _max_pubs;
private int _n_updates = 0;
private bool _continue_sub_thread = true;
private ViewStreamDatabase _vsd;
private bool _fire_dirty = false;
private PayloadMessage _last_sent_msg, _last_recvd_msg;
private readonly int _payload_sz;
private const byte _payload_byte = (byte)'A';
private readonly string _tag_name;
public PubSubTestingStream(int publish_period_msecs, int max_pubs, int payload_size, string tag_name, ViewStreamDatabase vsd) {
_vsd = vsd;
_payload_sz = payload_size;
var schema = BlueDataUtility.form_schema("PubSubTest",
Tuple.Create("id", TypeCode.Int32),
Tuple.Create("n_pubs", TypeCode.Int32),
Tuple.Create("n_recvs", TypeCode.Int32),
Tuple.Create("last_sent_id", TypeCode.Int32),
Tuple.Create("last_recv_id", TypeCode.Int32),
Tuple.Create("last_sent_guid", TypeCode.String),
Tuple.Create("last_recv_guid", TypeCode.String),
Tuple.Create("match", TypeCode.Boolean),
Tuple.Create("echo_time", TypeCode.Int32));
_table = new BlueTable(schema);
_publish_period = TimeSpan.FromMilliseconds(publish_period_msecs);
_msg_size = payload_size;
_max_pubs = max_pubs;
_tag_name = tag_name;
}
public PubSubTestingStream(int publish_period_seconds, int max_pubs, int msg_size, string tag_name)
: this(publish_period_seconds, max_pubs, msg_size, tag_name, ViewStreamDatabase.instance) { }
protected override void myOnFirstSubscriber() {
_vsd.addWorker(this);
System.Threading.Thread th = new System.Threading.Thread(_subscribe_thread_func);
th.IsBackground = true;
th.Start();
}
protected override void myOnLastSubscriber() {
_vsd.removeWorker(this);
_continue_sub_thread = false;
}
void _log_updates(IEnumerable<PubSubServerMessage> updates) {
var idx = 0;
foreach (var msg in updates) {
bts.Log.Gen.info($"PubSubTesStream._subscribe_thread_func idx: {idx} msg: {msg}");
idx++;
}
}
private void _subscribe_thread_func() {
// subscription is done in another thread
SubscriberCore sub_core = new SubscriberCore();
sub_core.subscribe(_tag_name);
while (_continue_sub_thread) {
// TODO recv_id
var updates = sub_core.get_updates(TimeSpan.FromMilliseconds(250));
if (updates == null || updates.Count() == 0)
continue;
_log_updates(updates);
_n_updates += updates.Count();
if (updates.Count() > 0) {
var server_msg = updates.Last();
if (server_msg.data != null && server_msg.data.Length > 0) {
_last_recvd_msg = PayloadMessage.deserialize(server_msg.data);
_last_recvd_msg.travel_epoch_ms = epoch_now();
} else {
// why are we getting empty or null data ? (server is sending data regardless?)
}
_fire_dirty = true;
}
}
}
private void _publish_next_packet() {
if (_last_sent_msg == null) {
_last_sent_msg = new PayloadMessage(0, _payload_sz, _payload_byte) {
guid = Guid.NewGuid().ToString()
};
} else {
_last_sent_msg.msg_id++;
_last_sent_msg.guid = Guid.NewGuid().ToString();
_last_sent_msg.travel_epoch_ms = epoch_now();
}
var ser_bytes = _last_sent_msg.serialize();
_n_pubs++;
_pub_core.publish(String.Empty, _tag_name, ser_bytes);
}
private void _fire_dp() {
object last_sent_id = _last_sent_msg == null ? (object)DBNull.Value : (object)_last_sent_msg.msg_id;
object last_recv_id = _last_recvd_msg == null ? (object)DBNull.Value : (object)_last_recvd_msg.msg_id;
object echo_time = DBNull.Value;
object last_sent_guid = _last_sent_msg == null ? (object)DBNull.Value : (object)_last_sent_msg.guid;
object last_recv_guid = _last_recvd_msg == null ? (object)DBNull.Value : (object)_last_recvd_msg.guid;
if (_last_sent_msg != null && _last_recvd_msg != null) {
echo_time = _last_recvd_msg.travel_epoch_ms - _last_sent_msg.travel_epoch_ms;
}
var match = last_sent_id.Equals(last_recv_id) && last_sent_guid.Equals(last_recv_guid);
IBlueRow nr = new BlueRow(_table.schema, 0, _n_pubs, _n_updates,
last_sent_id, last_recv_id, last_sent_guid, last_recv_guid, match, echo_time);
BlueTable table = new BlueTable(_table.schema);
table.addRow(nr);
var dp = BlueDataUtility.build_dp_inc(table, myLastValue as DataPacket, true);
myFireEvent(dp);
}
public void doWork() {
if (DateTime.Now - _last_publish_time > _publish_period)
if (_n_pubs <= _max_pubs) {
_publish_next_packet();
_last_publish_time = DateTime.Now;
}
// publish
// TODO: send id
if (_fire_dirty) {
_fire_dirty = false;
_fire_dp();
}
}
public static long epoch_now() {
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
}
}
}
@@ -0,0 +1,55 @@
namespace bts {
using BCG;
using BCG.Utilities.General;
using System;
public class SimpleTCPEchoStream : ViewStream, IWorker {
private string _ip;
private int _port;
private SimpleTCPClient _tcp_client;
private IBlueTableSchema _schema = BlueDataUtility.form_schema("SimpleTCPEchoStream",
Tuple.Create("id", TypeCode.Int32),
Tuple.Create("event", TypeCode.String));
private BlueTable _table;
private SyncQueue<string> _action_queue = new SyncQueue<string>();
public SimpleTCPEchoStream(string ip, int port, int msg_sz, int send_wait_period_ms) {
_ip = ip;
_port = port;
_table = new BlueTable(_schema);
_tcp_client = new SimpleTCPClient(_ip, _port, Convert.ToUInt32(msg_sz), send_wait_period_ms);
}
protected override void myOnFirstSubscriber() {
ViewStreamDatabase.instance.addWorker(this);
_tcp_client.register_listener((msg) => { _on_msg(msg); });
_tcp_client.start();
}
private void _on_msg(string msg) {
_action_queue.enqueue(msg);
}
public void doWork() {
if (_action_queue.getCount() == 0)
return;
BlueTable added_rows = new BlueTable(_schema);
var sz = _action_queue.getCount();
for (int i = 0; i < sz; i++) {
string msg = _action_queue.dequeue();
if (msg == null)
break;
IBlueRow nr = new BlueRow(_schema, _table.Count, msg);
_table.addRow(nr);
added_rows.addRow(nr);
}
if (added_rows.Count == 0)
return;
DataPacket dp = new DataPacket(_table, added_rows, new BlueTable(_schema));
myFireEvent(dp);
}
}
}
@@ -0,0 +1,77 @@
using System.Net.Sockets;
using System.Net;
using BCG;
using System;
using System.Collections.Generic;
using MongoDB.Bson;
using BCG.Utilities.General;
using System.Linq;
namespace bts {
// this class, a little specialized, takes the first snapshot thats fired
// from the base stream sorts them by a given column, and fires one row at a time
public class SnapshotReplayStream : ViewStream, IWorker {
private ViewStreamDatabase _vsd;
private ViewStream _snapshot_stream;
private readonly string _sort_col;
private readonly int _buffer_size;
private TimeSpan _fire_period;
private int _in_row_ptr = 0;
private List<IBlueRow> _in_rows = new List<IBlueRow>();
private CircularBufferTable _out_table;
public SnapshotReplayStream(ViewStream base_str, string sort_col, int buffer_size, string fire_period)
: this(ViewStreamDatabase.instance, base_str, sort_col, buffer_size, TimeBasedFilter.parse_duration(fire_period)) { }
public SnapshotReplayStream(ViewStreamDatabase vsd, ViewStream base_str, string sort_col, int buffer_size, TimeSpan fire_period) {
_vsd = vsd;
_snapshot_stream = base_str;
_sort_col = sort_col;
_buffer_size = buffer_size;
_fire_period = fire_period;
}
protected override void myOnFirstSubscriber() {
_snapshot_stream.onChange += _handle_stream_update;
MasterWorker.getInstance(false).addWorker(this, _fire_period);
}
protected override void myOnLastSubscriber() {
base.myOnLastSubscriber();
}
private void _handle_stream_update(object dp_obj) {
DataPacket dp = dp_obj as DataPacket;
if (_in_rows.Count > 0)
return;
_out_table = new CircularBufferTable(dp.schema, _buffer_size);
// _in_rows is filled up only once
foreach (IBlueRow r in dp.newRows) {
_in_rows.Add(r);
}
_in_rows.Sort((IBlueRow r1, IBlueRow r2) => {
return BlueDataUtility.compare_rows(r1, r2, _sort_col);
});
}
public void doWork() {
if (_in_row_ptr >= _in_rows.Count) {
// we can loop around or not here
return;
}
if (_in_rows.Count > 0) {
// fire row
IBlueRow curr_row = _in_rows.ElementAt(_in_row_ptr++);
_out_table.add_row(curr_row);
DataPacket dp = BlueDataUtility.build_dp_inc(_out_table,
myLastValue == null ? null : myLastValue as DataPacket, false);
myFireEvent(dp);
}
}
}
}
@@ -0,0 +1,817 @@
using Amazon.Runtime.Internal;
using bts;
using DnsClient.Protocol;
using System;
using System.Collections.Generic;
using System.IO;
using System;
using Microsoft.VisualBasic;
using Spark.Core.Collections;
using System.Reflection;
namespace BCG {
/// <summary>
/// This stream (not for prod) provides a way to run tests - that could otherwise be run in NUnits.
/// (truth is stream rpovide a RDE for quickly coding and running, so it was eaiser to run tests here)
/// </summary>
[DataStreamUserRespresentation("tests")]
public class TesStream : ViewStream {
static byte[] create_byte_array() {
Random random = new Random();
var sz = random.Next(1, 1000);// % 1000;
// Generate a random byte
byte randomByte = (byte)random.Next(byte.MinValue, byte.MaxValue + 1);
byte[] rv = new byte[sz];
for (int i = 0; i < sz; i++) {
rv[i] = (byte)random.Next(byte.MinValue, byte.MaxValue + 1);
}
return rv;
}
private IBlueTableSchema _schema;
class TestResult {
public string test_name = MethodBase.GetCurrentMethod().Name;
public bool test_result;
}
private List<Func<TestResult>> _tests = new
List<Func<TestResult>>();
public TesStream() {
_schema = BlueDataUtility.form_schema("Tests",
Tuple.Create("id", TypeCode.Int32),
Tuple.Create("test", TypeCode.String),
Tuple.Create("result", TypeCode.Boolean),
Tuple.Create("exception", TypeCode.String)
);
// register tests here
// _tests.Add(new Func<TestResult>(_run_sub_msg_test));
// _tests.Add(new Func<TestResult>(_run_pub_msg_test));
// _tests.Add(new Func<TestResult>(_run_pubsub_server_msg_test));
// _tests.Add(new Func<TestResult>(_run_pubsub_client_msg_test));
// _tests.Add(new Func<TestResult>(_run_columninfo_serialization_test));
// _tests.Add(new Func<TestResult>(_run_schema_serialization_test));
// _tests.Add(new Func<TestResult>(_row_serialization_tests_no_dbnulls));
// _tests.Add(new Func<TestResult>(_row_serialization_tests_with_dbnulls));
//_tests.Add(new Func<TestResult>(_row_serialization_tests_all_types));
// _tests.Add(new Func<TestResult>(_run_full_stream_serialization_test));
// _tests.Add(new Func<TestResult>(_run_full_stream_serialization_with_controller_test));
// _tests.Add(new Func<TestResult>(_run_pubsub_server_stream_tag_handler_test));
// _tests.Add(new Func<TestResult>(_run_single_tag_data_test_clean));
//_tests.Add(new Func<TestResult>(_cpp_data_test));
//_tests.Add(new Func<TestResult>(_write_stream_updates_to_files));
_tests.Add(new Func<TestResult>(_deserialize_pub_msg_test));
}
protected override void myOnFirstSubscriber() {
BlueTable rows = new BlueTable(_schema);
// u the tests here
foreach (var test in _tests) {
string ex_msg = String.Empty;
TestResult tr = new TestResult() {
test_name = test.Method.Name,
test_result = false
};
try {
tr = test();
} catch (Exception ex) {
ex_msg = ex.Message + "\n" + ex.StackTrace;
}
IBlueRow r = new BlueRow(_schema, rows.Count, tr.test_name, tr.test_result, ex_msg);
rows.addRow(r);
}
var dp = BlueDataUtility.build_dp_inc(rows, myLastValue as DataPacket, true);
myFireEvent(dp);
}
protected override void myOnLastSubscriber() {
}
private TestResult _run_sub_msg_test() {
bts.SubscribeMsg sub_msg = new bts.SubscribeMsg() {
connection = Guid.NewGuid().ToString(),
subscribing_app = Guid.NewGuid().ToString(),
tags = new string[] { "one", "two", "three" }
};
MemoryStream str = new MemoryStream();
sub_msg.serialize_into_str(str);
str.Position = 0;
bts.SubscribeMsg sub_msg_ = new bts.SubscribeMsg();
sub_msg_.consruct_deserialize(str);
bool res = sub_msg.Equals(sub_msg_);
return new TestResult {
test_name = "SubscribeMsg",
test_result = res
};
}
private TestResult _run_pub_msg_test() {
var pub_msg = new bts.PublishMsg() {
connection = Guid.NewGuid().ToString(),
publishing_app = Guid.NewGuid().ToString(),
tag = Guid.NewGuid().ToString(),
tag_type = "DS_",
is_compressed = false,
publish_time_epoch_ms = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
data_to_publish = create_byte_array(),
};
MemoryStream str = new MemoryStream();
pub_msg.serialize_into_str(str);
str.Position = 0;
var pub_msg_ = new bts.PublishMsg();
pub_msg_.consruct_deserialize(str);
bool res = pub_msg.Equals(pub_msg_);
return new TestResult {
test_name = "PublishMsg",
test_result = res
};
}
private TestResult _run_pubsub_server_msg_test() {
var msg = new bts.PubSubServerMessage() {
tag = Guid.NewGuid().ToString(),
tag_type = Guid.NewGuid().ToString(),
data = create_byte_array()
};
MemoryStream str = new MemoryStream();
msg.serialize_into_str(str);
str.Position = 0;
var msg_ = new bts.PubSubServerMessage();
msg_.consruct_deserialize(str);
bool res = msg.Equals(msg_);
return new TestResult {
test_name = "PubSubServerMessage",
test_result = res
};
}
private TestResult _run_pubsub_client_msg_test() {
PubSubClientMessage msg = new PubSubClientMessage() {
msg_type = PubSubMessageType.SUBSCRIBE,
sub_msg = new bts.SubscribeMsg() {
connection = Guid.NewGuid().ToString(),
subscribing_app = Guid.NewGuid().ToString(),
tags = new string[] { "one", "two", "three" }
}
};
var str = new MemoryStream();
msg.serialize_into_str(str);
str.Position = 0;
var msg_ = new PubSubClientMessage();
msg_.consruct_deserialize(str);
var res = msg.Equals(msg_);
return new TestResult {
test_name = "PubSubClientMessage",
test_result = res
};
}
private TestResult _run_columninfo_serialization_test() {
Func<ColumnInfo, bool> test_ci = (ci) => {
MemoryStream str = new MemoryStream();
BinaryWriter bw = new BinaryWriter(str);
StreamSerializationUtils.serialize_column_info(ci, ref bw);
str.Position = 0;
//var ci_txt = BlueDataUtility.to_string(ci);
//var ci_ser =
//bts.Log.Gen.info("ci: {}")
BinaryReader br = new BinaryReader(str);
var ci_prime = StreamSerializationUtils.deserialize_column_info(ref br);
return BlueDataUtility.compute_equality(ci, ci_prime);
};
int i = 0;
foreach (Type t in BlueDataUtility.valid_column_types()) {
ColumnInfo ci = new ColumnInfo(Guid.NewGuid().ToString(),
i++, t);
var res = test_ci(ci);
if (!res) {
return new TestResult {
test_name = "ColumnInfoSerialization",
test_result = false
};
}
}
return new TestResult {
test_name = "ColumnInfoSerialization",
test_result = true
};
}
private TestResult _run_schema_serialization_test() {
var table_name = "test_table";
var excluded_types = new HashSet<Type>() { typeof(DateTime), typeof(Decimal) };
IBlueTableSchema schema = create_schema_with_all_types(excluded_types);
MemoryStream str = new MemoryStream();
BinaryWriter bw = new BinaryWriter(str);
StreamSerializationUtils.serialize_schema(schema, ref bw);
_write_to_file(str, @"c:\Temp\tests\schema.bin");
var hex_txt = StreamSerializationUtils.to_hex(str);
bts.Log.Gen.info($"_run_schema_serialization_test ser: {hex_txt}");
str.Position = 0;
BinaryReader br = new BinaryReader(str);
var schema_prime = StreamSerializationUtils.deserialize_schema(ref br);
var res = BlueDataUtility.compute_equality(schema, schema_prime);
return new TestResult {
test_name = "SchemaSerialization",
test_result = res
};
}
private TestResult _run_datetime_seriliaztion_test() {
DateTime dt = DateTime.Now;
DateTimeOffset dt_off = new DateTimeOffset(dt);
long dt_epoch_ms = dt_off.ToUnixTimeMilliseconds();
DateTimeOffset dt_off_pr = DateTimeOffset.FromUnixTimeMilliseconds(dt_epoch_ms);
DateTime dt_p = dt_off_pr.DateTime;
var passes = dt.Equals(dt_p);
return new TestResult {
test_name = "_run_datetime_seriliaztion_test",
test_result = false
};
}
private TestResult _run_full_stream_serialization_test() {
// create message
var schema = create_schema_with_all_types();
BlueTable cr_rows = new BlueTable(schema);
// 100 rows
int n_rows = 100;
for (int i = 0; i < n_rows; i++) {
var nr = generate_random_row(schema, i);
cr_rows.addRow(nr);
}
MemoryStream str = new MemoryStream();
BinaryWriter bw = new BinaryWriter(str);
bts.StreamIOMessage.CreateMessage cr_msg = new bts.StreamIOMessage.CreateMessage(cr_rows);
bts.StreamIOMessage stream_io_msg = new bts.StreamIOMessage(cr_msg);
UniversalStreamIOSerializer ser = new UniversalStreamIOSerializer();
ser.serialize(stream_io_msg, ref bw);
str.Position = 0;
BinaryReader br = new System.IO.BinaryReader(str);
UniversalStreamIODeserializer deser = new bts.UniversalStreamIODeserializer();
var stream_io_msg_prime = deser.deserialize(ref br);
bool passes = stream_io_msg.Equals(stream_io_msg_prime);
var n_dels = 50;
BlueTable del_rows = new BlueTable(cr_rows.schema);
foreach (IBlueRow r in cr_rows) {
del_rows.addRow(r);
if (del_rows.Count == n_dels)
break;
}
IBlueRowCollection added_rows = del_rows;
bts.StreamIOMessage.MultipleRemoveAddMessage mra_msg = new bts.StreamIOMessage.MultipleRemoveAddMessage(del_rows, added_rows);
str = new MemoryStream();
bw = new BinaryWriter(str);
stream_io_msg = new bts.StreamIOMessage(mra_msg);
ser.serialize(stream_io_msg, ref bw);
bw.BaseStream.Position = 0;
br = new BinaryReader(str);
//deser = new UniversalStreamIODeserializer();
stream_io_msg_prime = deser.deserialize(ref br);
passes = passes && stream_io_msg.Equals(stream_io_msg_prime);
return new TestResult {
test_name = "UniversalSerialization",
test_result = passes
};
}
private TestResult _run_full_stream_serialization_with_controller_test() {
// create message
var schema = create_schema_with_all_types();
BlueTable cr_rows = new BlueTable(schema);
// 100 rows
int n_rows = 100;
for (int i = 0; i < n_rows; i++) {
var nr = generate_random_row(schema, i);
cr_rows.addRow(nr);
}
bts.StreamIOMessage.CreateMessage cr_msg = new bts.StreamIOMessage.CreateMessage(cr_rows);
bts.StreamIOMessage stream_io_msg = new bts.StreamIOMessage(cr_msg);
IStreamIOMsgSerializer ser = new StreamIOSerializationController();
var ser_bytes = ser.serialize(stream_io_msg);
IStreamMsgDeserilizer deser = new bts.StreamIODeserializationController();
var stream_io_msg_prime = deser.deserialize(ser_bytes);
bool passes = stream_io_msg.Equals(stream_io_msg_prime);
//mult remove adds
// remove all rows and add 50 more
BlueTable del_rows = new BlueTable(cr_rows);
BlueTable added_rows = new BlueTable(cr_rows.schema);
var n_adds = 50;
for (int i = 0; i < n_adds; i++) {
var nr = generate_random_row(schema, i);
added_rows.addRow(nr);
}
bts.StreamIOMessage.MultipleRemoveAddMessage mra_msg = new bts.StreamIOMessage.MultipleRemoveAddMessage(del_rows, added_rows);
stream_io_msg = new bts.StreamIOMessage(mra_msg);
ser_bytes = ser.serialize(stream_io_msg);
var ser_bytes_hex = StreamSerializationUtils.to_hex(ser_bytes);
Log.Gen.info($"ser_bytes: {ser_bytes_hex}");
stream_io_msg_prime = deser.deserialize(ser_bytes);
passes = passes && stream_io_msg.Equals(stream_io_msg_prime);
return new TestResult {
test_name = "UniversalSerializationController",
test_result = passes
};
}
private TestResult _row_serialization_tests_no_dbnulls() {
// IBlueTableSchema schema = BlueDataUtility.form_schema("test_table",
// new Tuple<string, TypeCode>("id", TypeCode.Int32),
// new Tuple<string, TypeCode>("i1", TypeCode.Int32),
// new Tuple<string, TypeCode>("d1", TypeCode.Double),
// new Tuple<string, TypeCode>("string_1", TypeCode.String));
// bts.UniversalRowSerializer row_ser = new bts.UniversalRowSerializer(schema);
// IBlueRow r = new BlueRow(schema, 0, 100, 123.45, "test_string");
var schema = create_schema_with_all_types(new HashSet<Type>() { typeof(DateTime), typeof(Decimal) });
bts.UniversalRowSerializer row_ser = new bts.UniversalRowSerializer(schema);
MemoryStream str = new MemoryStream();
IBlueRow r = generate_random_row(schema, 0, false);
BinaryWriter bw = new BinaryWriter(str);
row_ser.serialize_row(r, 0, ref bw);
_write_to_file(str, @"C:\Temp\tests\row.bin");
str.Position = 0;
byte[] raw_byte_array = str.ToArray();
var hex_txt = StreamSerializationUtils.to_hex(raw_byte_array);
Log.Gen.info($"TestStream._row_serialization_tests_no_dbnulls Row bytes: {hex_txt}");
BinaryReader br = new BinaryReader(str);
bts.UniversalRowDeserializer des = new UniversalRowDeserializer(schema);
IBlueRow r_prime = des.deserialize_row(ref br);
string row_str = r_prime.to_string();
Log.Gen.info($"TestStream._row_serialization_tests_no_dbnulls r_prime: {row_str}");
var passes = BlueDataUtility.compute_equality(r, r_prime);
return new TestResult {
test_name = "UniversalRowSerialization_NonNull",
test_result = passes
};
}
private TestResult _deserialize_pub_msg_test() {
var pub_msg_ser = _read_from_file(@"C:\Temp\tests\pubsub_raw_msgs\publish_msg.bin");
PubSubClientMessage ps_client_msg = new PubSubClientMessage();
ps_client_msg.consruct_deserialize(pub_msg_ser);
bool passes = ps_client_msg.msg_type == PubSubMessageType.PUBLISH;
return new TestResult {
test_name = "_deserialize_pub_msg_test",
test_result = passes
};
}
private TestResult _cpp_data_test() {
//create and write schema
IBlueTableSchema schema = BlueDataUtility.form_schema("test_table",
new Tuple<string, TypeCode>("id", TypeCode.Int32),
new Tuple<string, TypeCode>("i_1", TypeCode.Int32),
new Tuple<string, TypeCode>("i_2", TypeCode.Int32),
new Tuple<string, TypeCode>("d_1", TypeCode.Double),
new Tuple<string, TypeCode>("string_1", TypeCode.String)
);
bts.UniversalRowSerializer row_ser = new bts.UniversalRowSerializer(schema);
UniversalRowDeserializer row_deser = new UniversalRowDeserializer(schema);
StreamIOSerializationController ser_controller = new StreamIOSerializationController();
StreamIODeserializationController deser_controller = new StreamIODeserializationController();
IBlueTableSchema schema_p = null;
var schema_file = @"c:\Temp\tests\schema.bin";
var row_file = @"C:\Temp\tests\row.bin";
var create_op_file = @"C:\Temp\tests\create_op.bin";
var mra_op_file = @"C:\Temp\tests\mra_op.bin";
IBlueRow row = new BlueRow(schema, 0, 100, 200, 123.45, "test_string");
//serialize schema, write it to a file, read it back, deserialize it and match schemas
byte[] ser_schema_bytes = StreamSerializationUtils.serialize_schema(schema);
_write_to_file(ser_schema_bytes, schema_file);
byte[] schema_file_bytes = _read_from_file(schema_file);
schema_p = StreamSerializationUtils.deserialize_schema(schema_file_bytes);
bool passes = BlueDataUtility.compute_equality(schema, schema_p);
//serialize row, write it to a file, read it back, deserialize it and match schemas
byte[] ser_row_bytes = row_ser.serialize_row(row);
_write_to_file(ser_row_bytes, row_file);
byte[] row_file_bytes = _read_from_file(row_file);
var row_file_bytes_txt = StreamSerializationUtils.to_hex(row_file_bytes);
Log.Gen.info($"TestsStream._cpp_data_test row_file_bytes_txt: {row_file_bytes_txt}");
IBlueRow row_p = row_deser.deserialize_row(row_file_bytes);
passes = passes && BlueDataUtility.compute_equality(row, row_p);
{
// serialize a create operation
int n_rows = 100;
BlueTable table = new BlueTable(schema);
for (int i = 0; i < n_rows; i++) {
IBlueRow nr = new BlueRow(schema, i, 100, 200, 123.45, "test_string");
table.addRow(nr);
}
StreamIOMessage cr_msg = new StreamIOMessage(new StreamIOMessage.CreateMessage(table));
//StreamIOSerializationController ser_controller = new StreamIOSerializationController();
byte[] create_ser_bytes = ser_controller.serialize(cr_msg);
_write_to_file(create_ser_bytes, create_op_file);
// read it and make sure its right
byte[] create_op_file_bytes = _read_from_file(create_op_file);
//StreamIODeserializationController deser_controller = new StreamIODeserializationController();
var cr_msg_p = deser_controller.deserialize(create_op_file_bytes);
_write_to_file(create_ser_bytes, mra_op_file);
passes = passes && cr_msg.Equals(cr_msg_p);
}
//multiple remove adds
{
// remove all rows and add them again
int n_rows = 100;
BlueTable table = new BlueTable(schema);
for (int i = 0; i < n_rows; i++) {
IBlueRow nr = new BlueRow(schema, i, 100, 200, 123.45, "test_string");
table.addRow(nr);
}
StreamIOMessage mra_msg = new StreamIOMessage(new StreamIOMessage.MultipleRemoveAddMessage(table, table));
//StreamIOSerializationController ser_controller = new StreamIOSerializationController();
byte[] mra_ser_bytes = ser_controller.serialize(mra_msg);
_write_to_file(mra_ser_bytes, mra_op_file);
// reasd it and make sure it matches
byte[] mra_op_file_bytes = _read_from_file(mra_op_file);
//StreamIODeserializationController deser_controller = new StreamIODeserializationController();
StreamIOMessage mra_msg_p = deser_controller.deserialize(mra_op_file_bytes);
passes = passes && mra_msg.Equals(mra_msg_p);
}
return new TestResult {
test_name = "_cpp_data_test",
test_result = passes
};
}
private TestResult _write_stream_updates_to_files() {
IBlueTableSchema schema = BlueDataUtility.form_schema("test_table",
new Tuple<string, TypeCode>("id", TypeCode.Int32),
new Tuple<string, TypeCode>("i_1", TypeCode.Int32),
new Tuple<string, TypeCode>("i_2", TypeCode.Int32),
new Tuple<string, TypeCode>("d_1", TypeCode.Double),
new Tuple<string, TypeCode>("string_1", TypeCode.String)
);
var packets_path = @"C:\Temp\tests\stream_packets\";
Func<long> now_epochs = () => {
DateTimeOffset now = DateTimeOffset.UtcNow;
// Convert to Unix time in milliseconds
long unix_time_milliseconds = now.ToUnixTimeMilliseconds();
return unix_time_milliseconds;
};
Func<int, bool, string> curr_file_path = (id, create) => {
//var epoch_ms = now_epochs();
var file_path = $"{packets_path}{id}.bin";
if (create)
file_path = $"{packets_path}create_{id}.bin";
return file_path;
};
// write 1000 stream updates
{
int init_sz = 100;
BlueTable table = new BlueTable(schema);
StreamIOSerializationController ser_controller = new StreamIOSerializationController();
// create table of 100 rows
for (int i = 0; i < init_sz; i++) {
IBlueRow nr = new BlueRow(schema, i, i * 100, i * 200, i * 123.45, "test_string");
table.addRow(nr);
}
// write create msg
StreamIOMessage cr_msg = new StreamIOMessage(new StreamIOMessage.CreateMessage(table));
byte[] create_ser_bytes = ser_controller.serialize(cr_msg);
var create_file_path = curr_file_path(table.Count, true);
_write_to_file(create_ser_bytes, create_file_path);
// add 1000 rows and write an io msg for each update and write it to a file
int n_updates = 1000;
int period_ms = 50;
// write a create
for (int i = 0; i < n_updates; i++) {
// addition
BlueTable adds = new BlueTable(schema);
int id = table.Count;
IBlueRow nr = new BlueRow(schema, id, i * 100, i * 200, i * 123.45, "test_string");
adds.addRow(nr);
BlueTable dels = new BlueTable(schema);
table.addRow(nr);
StreamIOMessage mra_msg = new StreamIOMessage(new StreamIOMessage.MultipleRemoveAddMessage(dels, adds));
byte[] mra_ser_bytes = ser_controller.serialize(mra_msg);
var mra_file_path = curr_file_path(id, false);
_write_to_file(mra_ser_bytes, mra_file_path);
System.Threading.Thread.Sleep(TimeSpan.FromMilliseconds(period_ms));
}
// now start writing increments and add 1 row at a time
}
return new TestResult {
test_name = "_write_updates_as_files",
test_result = true
};
}
private TestResult _row_serialization_tests_with_dbnulls() {
IBlueTableSchema schema = BlueDataUtility.form_schema("test_table",
new Tuple<string, TypeCode>("id", TypeCode.Int32),
new Tuple<string, TypeCode>("i1", TypeCode.Int32),
new Tuple<string, TypeCode>("d1", TypeCode.Double),
new Tuple<string, TypeCode>("string_1", TypeCode.String));
bts.UniversalRowSerializer row_ser = new bts.UniversalRowSerializer(schema);
IBlueRow r = new BlueRow(schema, 0, DBNull.Value, 123.45, "test_string");
MemoryStream str = new MemoryStream();
BinaryWriter bw = new BinaryWriter(str);
row_ser.serialize_row(r, 0, ref bw);
str.Position = 0;
BinaryReader br = new BinaryReader(str);
bts.UniversalRowDeserializer des = new UniversalRowDeserializer(schema);
IBlueRow r_prime = des.deserialize_row(ref br);
var passes = BlueDataUtility.compute_equality(r, r_prime);
return new TestResult {
test_name = "UniversalRowSerialization_WithDBNulls",
test_result = passes
};
}
private TestResult _row_serialization_tests_all_types() {
var schema = create_schema_with_all_types();
bts.UniversalRowSerializer row_ser = new bts.UniversalRowSerializer(schema);
IBlueRow r = generate_random_row(schema, 0, false);
MemoryStream str = new MemoryStream();
BinaryWriter bw = new BinaryWriter(str);
row_ser.serialize_row(r, 0, ref bw);
_write_to_file(str, @"C:\Temp\tests\row.bin");
str.Position = 0;
BinaryReader br = new BinaryReader(str);
bts.UniversalRowDeserializer des = new UniversalRowDeserializer(schema);
IBlueRow r_prime = des.deserialize_row(ref br);
var passes = BlueDataUtility.compute_equality(r, r_prime);
return new TestResult {
test_name = "UniversalRowSerialization_AllTypes",
test_result = passes
};
}
private static TestResult _run_pubsub_server_stream_tag_handler_test() {
// create message
var schema = create_schema_with_all_types();
var tag = "DS_" + schema.tableName;
BlueTable cr_rows = new BlueTable(schema);
// 100 rows
int n_rows = 100;
for (int i = 0; i < n_rows; i++) {
var nr = generate_random_row(schema, i);
cr_rows.addRow(nr);
}
PubsubServerSingleStreamTagHandler handler = new PubsubServerSingleStreamTagHandler();
bts.StreamIOMessage.CreateMessage cr_msg = new bts.StreamIOMessage.CreateMessage(cr_rows);
bts.StreamIOMessage str_io_msg = new bts.StreamIOMessage(cr_msg);
IStreamIOMsgSerializer ser = new StreamIOSerializationController();
byte[] msg_bytes = ser.serialize(str_io_msg);
handler.update(tag, msg_bytes);
//now get it back for the handler
byte[] content = handler.get_content(tag);
IStreamMsgDeserilizer deser = new StreamIODeserializationController();
bts.StreamIOMessage str_io_msg_p = deser.deserialize(content);
// test here
var passes = str_io_msg.Equals(str_io_msg_p);
// delete all rows
BlueTable del_rows = new BlueTable(cr_rows);
cr_rows.clear();
// added 50 new rows
BlueTable added_rows = new BlueTable(del_rows.schema);
int new_state_sz = 50;
for (int i = 0; i < new_state_sz; i++) {
var nr = generate_random_row(schema, i);
added_rows.addRow(nr);
}
cr_rows.addRows(added_rows);
// the sequence of operations are ops, ser, update, get_content, deser, maake sure the get_content state is good
// 1. generate op
bts.StreamIOMessage.MultipleRemoveAddMessage mra = new bts.StreamIOMessage.MultipleRemoveAddMessage(del_rows, added_rows);
str_io_msg = new bts.StreamIOMessage(mra);
// 2. serialize it into bytes
msg_bytes = ser.serialize(str_io_msg);
// 3. send it to handler
handler.update(tag, msg_bytes);
// 4. get the state from the handler
byte[] content_p = handler.get_content(tag);
// 5. deserialize the state into a stream op
str_io_msg_p = deser.deserialize(content_p);
// 6. check to make sure the state's rows are good
passes = passes && str_io_msg_p.op == bts.StreamIOMessage.StreamOp.CREATE &&
BlueDataUtility.compute_equality(cr_rows, str_io_msg_p.create_message.rows);
return new TestResult {
test_result = passes,
test_name = "run_pubsub_server_stream_tag_handler_test"
};
}
private static TestResult _run_single_tag_data_test_clean() {
// create message
var test_name = MethodBase.GetCurrentMethod().Name;
var schema = create_schema_with_all_types();
var tag = "DS_" + schema.tableName;
BlueTable table = new BlueTable(schema);
IStreamIOMsgSerializer serializer = new StreamIOSerializationController();
IStreamMsgDeserilizer deser = new StreamIODeserializationController();
bts.SingleTagData st_data = new bts.SingleTagData(tag, DSTagManager.DataStreamTagType);
// create with 100 rows
int n_rows = 100;
bool is_succ = true;
for (int i = 0; i < n_rows; i++) {
var nr = generate_random_row(schema, i);
// perform the same action SingletagData, and verify the states match
PublishMsg pub_msg = build_pub_msg(nr, null, table.Count == 0, ref serializer);
table.addRow(nr);
st_data.handle_publish(pub_msg);
var table_p = get_rows_from_single_tag_state(ref st_data, ref deser);
is_succ = is_succ && BlueDataUtility.compute_equality(table, table_p);
}
// change all rows
for (int i = 0; i < n_rows; i++) {
var nr = generate_random_row(schema, i);
var dr = table[i];
table.deleteRow(dr);
table.addRow(nr);
PublishMsg pub_msg = build_pub_msg(nr, dr, false, ref serializer);
st_data.handle_publish(pub_msg);
var table_p = get_rows_from_single_tag_state(ref st_data, ref deser);
is_succ = is_succ && BlueDataUtility.compute_equality(table, table_p);
}
// delete all rows
var aux_table = new BlueTable(table);
foreach (IBlueRow r in aux_table) {
table.deleteRow(r);
PublishMsg pub_msg = build_pub_msg(null, r, false, ref serializer);
st_data.handle_publish(pub_msg);
var table_p = get_rows_from_single_tag_state(ref st_data, ref deser);
is_succ = is_succ && BlueDataUtility.compute_equality(table, table_p);
}
return new TestResult() {
test_result = is_succ,
test_name = test_name
};
}
#region Helper functions
private static void _write_to_file(byte[] ser_bytes, string file_name) {
_write_to_file(new MemoryStream(ser_bytes), file_name);
}
private static void _write_to_file(MemoryStream str, string file_name) {
if (String.IsNullOrEmpty(file_name))
return;
byte[] str_bytes = str.ToArray();
using (FileStream fs = new FileStream(file_name, FileMode.Create)) {
// Write the byte array to the file
fs.Write(str_bytes, 0, str_bytes.Length);
}
}
private static byte[] _read_from_file(string file_path) {
var rv = File.ReadAllBytes(file_path);
return rv;
}
public static IBlueRowCollection get_rows_from_single_tag_state(ref SingleTagData st_data, ref IStreamMsgDeserilizer deser) {
var content = st_data.get_current_content();
var msg_p = deser.deserialize(content);
Log.assert(msg_p.op == bts.StreamIOMessage.StreamOp.CREATE);
return msg_p.create_message.rows;
}
public static PublishMsg build_pub_msg(IBlueRow added_row, IBlueRow removed_row, bool is_create,
ref IStreamIOMsgSerializer serializer) {
Func<IBlueTableSchema> get_schema = () => {
return (added_row != null ? added_row : removed_row).schema;
};
bts.StreamIOMessage str_io_msg = null;
if (is_create) {
Log.assert(added_row != null);
var aux_new = new BlueTable(added_row.schema);
aux_new.addRow(added_row);
var cr_msg = new bts.StreamIOMessage.CreateMessage(aux_new);
str_io_msg = new bts.StreamIOMessage(cr_msg);
} else {
var schema = get_schema();
BlueTable added_table = new BlueTable(schema);
if (added_row != null)
added_table.addRow(added_row);
BlueTable rem_table = new BlueTable(schema);
if (removed_row != null)
rem_table.addRow(removed_row);
bts.StreamIOMessage.MultipleRemoveAddMessage mra_msg =
new bts.StreamIOMessage.MultipleRemoveAddMessage(rem_table, added_table);
str_io_msg = new bts.StreamIOMessage(mra_msg);
}
byte[] msg_bytes = serializer.serialize(str_io_msg);
PublishMsg pub_msg = new PublishMsg() {
connection = "test_connection",
tag = $"DS_{get_schema()}",
tag_type = "DS",
data_to_publish = msg_bytes
};
return pub_msg;
}
public static IBlueTableSchema create_schema_with_all_types(HashSet<Type> excluded_col_map = null) {
excluded_col_map = excluded_col_map == null ? new HashSet<Type>() : excluded_col_map;
var table_name = "test_table";
BlueTableSchema schema = new BlueTableSchema();
List<ColumnInfo> cis = new List<ColumnInfo>();
foreach (Type t in BlueDataUtility.valid_column_types()) {
if (t == null || t == typeof(DateTime) || excluded_col_map.Contains(t))
continue;
var col_name = t.ToString() + "_" + cis.Count.ToString(); // Guid.NewGuid().ToString();
ColumnInfo ci = new ColumnInfo(col_name, cis.Count, t);
cis.Add(ci);
}
cis.Add(new ColumnInfo("id", cis.Count, typeof(int)));
schema = new BlueTableSchema(table_name, cis.ToArray());
return schema;
}
public static IBlueRow generate_random_row(IBlueTableSchema schema, int id, bool include_dbnulls = true) {
Random rnd = new Random();
object[] row_vals = new object[schema.columnInfo.Length];
foreach (ColumnInfo ci in schema.columnInfo) {
if (ci.colName == "id") {
row_vals[ci.colNo] = id;
continue;
}
object v = get_random_object(ci.type_code());
if (include_dbnulls && rnd.NextSingle() % 4 == 0)
v = DBNull.Value;
row_vals[ci.colNo] = v;
}
return new BlueRow(schema, row_vals);
}
public static object get_random_object(TypeCode type_code) {
Random random = new Random();
switch (type_code) {
case TypeCode.Boolean:
return random.Next(2) == 0; // Random boolean value (true or false)
case TypeCode.Byte:
return (byte)random.Next(byte.MinValue, byte.MaxValue + 1); // Random byte value
case TypeCode.Char:
return (char)random.Next(65, 65 + 27); // Random char value
case TypeCode.Decimal:
Decimal dec = 100.123M;
return dec;
case TypeCode.DateTime:
return DateTime.Now;
case TypeCode.Double:
return random.NextDouble() * (double.MaxValue - double.MinValue) + double.MinValue; // Random double value
case TypeCode.Int16:
return (short)random.Next(short.MinValue, short.MaxValue + 1); // Random short value
case TypeCode.Int32:
return random.Next(int.MinValue, int.MaxValue); // Random int value
case TypeCode.Int64:
return random.NextInt64(long.MinValue, long.MaxValue); // Random long value
case TypeCode.SByte:
return (sbyte)random.Next(sbyte.MinValue, sbyte.MaxValue + 1); // Random sbyte value
case TypeCode.Single:
return (float)(random.NextDouble() * (float.MaxValue - float.MinValue) + float.MinValue); // Random float value
case TypeCode.String:
return Guid.NewGuid().ToString();
case TypeCode.UInt16:
return (ushort)random.Next(ushort.MinValue, ushort.MaxValue + 1); // Random ushort value
case TypeCode.UInt32:
return (uint)random.Next(int.MinValue, int.MaxValue) + (uint)int.MaxValue; // Random uint value
case TypeCode.UInt64:
byte[] ulongBuffer = new byte[8];
random.NextBytes(ulongBuffer);
return BitConverter.ToUInt64(ulongBuffer, 0);
default:
throw new ArgumentException($"Unsupported TypeCode: {type_code}");
return null;
}
}
#endregion
}
}
@@ -0,0 +1,121 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using BCG;
using BCG.Utilities.General;
using HtmlAgilityPack;
namespace BCG {
class Program {
static void Main() {
string url = "http://quotes.toscrape.com";
List<string> quotes = ScrapeQuotes(url);
Console.WriteLine("Quotes from http://quotes.toscrape.com:");
foreach (var quote in quotes) {
Console.WriteLine(quote);
}
}
static List<string> ScrapeQuotes(string url) {
List<string> quotes = new List<string>();
// Create a new HtmlWeb instance
HtmlWeb web = new HtmlWeb();
try {
// Load the HTML document from the specified URL
HtmlDocument document = web.Load(url);
// Extract quotes from the HTML document
var quoteNodes = document.DocumentNode.SelectNodes("//span[@class='text']");
if (quoteNodes != null) {
foreach (var quoteNode in quoteNodes) {
string quote = quoteNode.InnerText.Trim();
quotes.Add(quote);
}
}
} catch (Exception ex) {
Console.WriteLine($"Error: {ex.Message}");
}
return quotes;
}
}
public class WebScapperStream : ViewStream, IWorker {
private readonly string _url;
private readonly string _xpath;
private readonly ViewStreamDatabase _vsd;
private IDictionary<string, int> _line_id_map = new Dictionary<string, int>();
private readonly IBlueTableSchema _schema;
public WebScapperStream()
:
this("http://quotes.toscrape.com", "//span[@class='text']", ViewStreamDatabase.instance) { }
public WebScapperStream(string url, string xpath)
: this(url, xpath, ViewStreamDatabase.instance) { }
public WebScapperStream(string url, string xpath, ViewStreamDatabase vsd) {
bts.Log.Gen.info($"WebScapperStream cons url: {url} xpath: {xpath}");
_schema = BlueDataUtility.form_schema($"{url}_{xpath}",
Tuple.Create("id", TypeCode.Int32),
Tuple.Create("url", TypeCode.UInt32),
Tuple.Create("line", TypeCode.String));
_url = url;
_xpath = xpath;
_vsd = vsd;
}
protected override void myOnFirstSubscriber() {
MasterWorker.getInstance(false).addWorker(this, TimeSpan.FromSeconds(1));
}
protected override void myOnLastSubscriber() {
MasterWorker.getInstance(false).removeWorker(this);
}
public void doWork() {
var lines = scrape_lines(_url, _xpath);
Func<string, int> get_id = (line) => {
int rv = 0;
if (!_line_id_map.TryGetValue(line, out rv))
_line_id_map.Add(line, _line_id_map.Count);
return rv;
};
BlueTable nrows = new BlueTable(_schema);
foreach (var l in lines) {
bts.Log.Gen.info($"line: {l}");
var id = get_id(l);
BlueRow nr = new BlueRow(_schema, get_id(l), _url, l);
nrows.addRow(nr);
}
var dp = BlueDataUtility.build_dp_inc(nrows, myLastValue as DataPacket, true);
myFireEvent(dp);
}
static List<string> scrape_lines(string url, string xpath) {
List<string> quotes = new List<string>();
// Create a new HtmlWeb instance
HtmlWeb web = new HtmlWeb();
try {
// Load the HTML document from the specified URL
HtmlDocument document = web.Load(url);
// Extract quotes from the HTML document
var quote_nodes = document.DocumentNode.SelectNodes(xpath);
if (quote_nodes != null) {
foreach (var qn in quote_nodes) {
string quote = qn.InnerText.Trim();
quotes.Add(quote);
}
}
} catch (Exception ex) {
Console.WriteLine($"Error: {ex.Message}");
}
return quotes;
}
}
}
@@ -0,0 +1,66 @@
namespace bts {
using BCG;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text.Json;
using System.Text.Json.Nodes;
[DataStreamUserRespresentation("benzingaNews")]
public class BenzingaNewStream : ViewStream {
private IBlueTableSchema _schema = null;
private int _id = 0;
// constructor takes in the raw mongo db stream, and the time to live (ttl), "7d" for example
public BenzingaNewStream(ViewStream mongodb_raw_stream, string ttl) {
// Hiding body (with project, columns can be hidden, or renamed)
ViewStream output_stream = new ProjectStream(mongodb_raw_stream, "!body");
// add column news_source = 'Benzinga', so we can append other news sources
output_stream = new AddColumnsStream(output_stream, @"news_source : Benzinga");
// now SuperMapStream is used to map one row into multiple, one per symbol,
// (SuperMapStream takes 2 lambdas, one to get the enw schema and another to
// return an array of rows, per one row)
output_stream = new SuperMapStream(mongodb_raw_stream,
(IBlueTableSchema s) => {
// this lambda returns the new schema (ie with extra cols symbol, exchange, is_primary_exchange)
if (_schema == null) {
var out_schema = s;
out_schema = BlueDataUtility.remove_columns(out_schema, "securities");
out_schema = BlueDataUtility.add_column(s, "doc_id_internal", typeof(string));
out_schema = BlueDataUtility.add_column(out_schema, "symbol", typeof(string));
out_schema = BlueDataUtility.add_column(out_schema, "exchange", typeof(string));
out_schema = BlueDataUtility.add_column(out_schema, "is_primary_exchange", typeof(bool));
_schema = out_schema;
}
return _schema;
},
(IBlueRow r) => {
var json_objs = BlueDataUtility.json_to_json_node_list(r.get<string>("securities"));
List<IBlueRow> expanded_rows = new List<IBlueRow>();
if (json_objs.Count == 0) {
MutableBlueRow nr = new MutableBlueRow(_schema, r);
nr.setValue("id", _id++);
expanded_rows.Add(nr);
}
foreach (JsonNode jnode in json_objs) {
if (jnode is JsonObject json_object) {
MutableBlueRow nr = new MutableBlueRow(_schema, r);
nr.setValue("id", _id++);
nr.setValue("doc_id_internal", $"{r["doc_id"]}_{jnode["symbol"]}");
nr.setValue("symbol", jnode["symbol"]);
nr.setValue("exchange", jnode["exchange"]);
nr.setValue("is_primary_exchange", Boolean.Parse(jnode["primary"].ToString()));
expanded_rows.Add(nr);
}
}
return expanded_rows;
});
// now we creaate a TimeFilter stream to keep the table as a circular buffer of the last N days
// passed A an argument in the constructor above
// time_filter is a string like 7d 1h 30 m 45s
output_stream = new TimeBasedFilterStream(output_stream, "created_at", ttl);
mySetRealSource(output_stream);
}
}
}
@@ -1,37 +1,256 @@
using System; using System;
using System.Collections.Generic;
using MongoDB.Driver; using MongoDB.Driver;
using MongoDB.Bson; using MongoDB.Bson;
using BCG;
using BCG.Utilities.General;
using BCG;
using mbts.spark;
class Program { namespace bts {
static void Main() { [DataStreamUserRespresentation("mongodb_sql")]
// Set the connection string and database name public class MongoDBSQLStream : ViewStream, IWorker {
string connectionString = "mongodb://localhost:27017"; private ViewStreamDatabase _vsd;
string databaseName = "your_database_name"; private readonly string _connection_string, _db_name, _collection_name;
string collectionName = "your_collection_name"; private MongoClient _client;
// make this a sorted table
private BlueTable _table;
// Create a MongoClient
MongoClient client = new MongoClient(connectionString);
// Access the database // Access the database
IMongoDatabase database = client.GetDatabase(databaseName); private IMongoDatabase _database;
private IDictionary<string, int> _id_map = new Dictionary<string, int>();
// mongodb://192.168.1.80:27017
// Access the collection public MongoDBSQLStream(string connection_string, string db_name, string collection_name)
IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>(collectionName); : this(connection_string, db_name, collection_name, ViewStreamDatabase.instance) {
// Fetch all documents from the collection }
var documents = collection.Find(Builders<BsonDocument>.Filter.Empty).ToCursor(); public MongoDBSQLStream(string connection_string, string db_name, string collection_name, ViewStreamDatabase vsd) {
bts.Log.Gen.info($"MongoDBStream constructed connection_string: {connection_string} " +
$"db_name: {db_name}");
_connection_string = connection_string;
_db_name = db_name;
_collection_name = collection_name;
_vsd = vsd;
_client = new MongoClient(_connection_string);
_database = _client.GetDatabase(_db_name);
}
// Iterate through the documents and print values protected override void myOnFirstSubscriber() {
foreach (var document in documents.ToEnumerable()) { MasterWorker.getInstance(false).addWorker(this, TimeSpan.FromSeconds(10));
// Assuming your document structure has fields named "Field1", "Field2", etc. }
Console.WriteLine("Field1: " + document["Field1"]);
Console.WriteLine("Field2: " + document["Field2"]);
// Add more fields as needed
// Print a separator between documents protected override void myOnLastSubscriber() {
Console.WriteLine(new string('-', 20)); MasterWorker.getInstance(false).removeWorker(this);
}
public void doWork() {
_read_mogodb();
}
private void _read_mogodb() {
HighPerformanceTimer timer = new HighPerformanceTimer();
timer.start();
// Access the collection
IMongoCollection<BsonDocument> collection = _database.GetCollection<BsonDocument>(name: _collection_name);
// Fetch all documents from the collection
var documents = collection.Find(Builders<BsonDocument>.Filter.Empty).ToCursor();
_table = _table == null ? null : new BlueTable(_table.schema);
// Iterate through the documents and print values
foreach (var document in documents.ToEnumerable()) {
bts.Log.Gen.info($"document: {document} json: {document.ToJson()}");
if (_table == null) {
_init_table(document);
}
_add_row(document);
}
timer.stop();
bts.Log.Gen.info($"MongoDBStream time to read {_collection_name} {timer.lastIntervalTime} msecs");
timer.start();
var dp = BlueDataUtility.build_dp_inc(_table, myLastValue == null ? null : myLastValue as DataPacket, true);
timer.stop();
bts.Log.Gen.info($"MongoDBStream time to compare tables: {timer.lastIntervalTime} msecs");
if (dp.addedRows.Count == 0 && dp.deletedRows.Count == 0)
return;
myFireEvent(dp);
}
private void _init_table(BsonDocument doc_row) {
bts.Log.assert(_table == null);
List<ColumnInfo> cis = new List<ColumnInfo>();
cis.Add((new ColumnInfo("id", 0, typeof(Int32))));
foreach (var n in doc_row.Names) {
cis.Add(new ColumnInfo(n, cis.Count, typeof(string)));
}
IBlueTableSchema schema = new BlueTableSchema(cis.ToArray(), _collection_name);
_table = new BlueTable(schema);
}
private void _add_row(BsonDocument doc) {
var key_val = doc["_id"];
var key = key_val.ToString();
int id;
if (!_id_map.TryGetValue(key, out id)) {
id = _id_map.Count;
_id_map.Add(key, id);
}
MutableBlueRow nr = new MutableBlueRow(_table.schema);
nr.setValue("id", id);
foreach (var n in doc.Names) {
var val = doc[n].ToString();
nr.setValue(n, val);
}
_table.addRow(nr);
} }
} }
}
[DataStreamUserRespresentation("mongodb")]
public class MongoDBStream : ViewStream, IWorker {
private ViewStreamDatabase _vsd;
private readonly string _connection_string, _db_name, _collection_name;
private MongoClient _client;
private BlueTable _table;
// Access the database
private IMongoDatabase _database;
private IDictionary<string, int> _id_map = new Dictionary<string, int>();
// mongodb://192.168.1.80:27017
public MongoDBStream(string connection_string, string db_name, string collection_name)
: this(connection_string, db_name, collection_name, ViewStreamDatabase.instance) {
}
public MongoDBStream(string connection_string, string db_name, string collection_name, ViewStreamDatabase vsd) {
bts.Log.Gen.info($"MongoDBStream constructed connection_string: {connection_string} " +
$"db_name: {db_name}");
_connection_string = connection_string;
_db_name = db_name;
_collection_name = collection_name;
_vsd = vsd;
_client = new MongoClient(_connection_string);
_database = _client.GetDatabase(_db_name);
}
protected override void myOnFirstSubscriber() {
MasterWorker.getInstance(false).addWorker(this, TimeSpan.FromSeconds(10));
}
protected override void myOnLastSubscriber() {
MasterWorker.getInstance(false).removeWorker(this);
}
public void doWork() {
_read_mogodb();
}
private void _read_mogodb() {
HighPerformanceTimer timer = new HighPerformanceTimer();
timer.start();
// Access the collection
IMongoCollection<BsonDocument> collection = _database.GetCollection<BsonDocument>(name: _collection_name);
// Fetch all documents from the collection
var documents = collection.Find(Builders<BsonDocument>.Filter.Empty).ToCursor();
_table = _table == null ? null : new BlueTable(_table.schema);
// Iterate through the documents and print values
foreach (var document in documents.ToEnumerable()) {
//bts.Log.Gen.info($"document: {document} json: {document.ToJson()}");
if (_table == null) {
_init_table(document);
}
_add_doc(document);
}
timer.stop();
bts.Log.Gen.info($"MongoDBStream time to read {_collection_name} {timer.lastIntervalTime} msecs");
timer.start();
var dp = BlueDataUtility.build_dp_inc(_table, myLastValue == null ? null : myLastValue as DataPacket, true);
timer.stop();
bts.Log.Gen.info($"MongoDBStream time to compare tables :{timer.lastIntervalTime} msecs");
if (dp.addedRows.Count == 0 && dp.deletedRows.Count == 0)
return;
myFireEvent(dp);
}
private void _init_table(BsonDocument doc_row) {
bts.Log.assert(_table == null);
var schema = BlueDataUtility.form_schema($"{_database}_{_table}",
Tuple.Create("id", TypeCode.Int32),
Tuple.Create("doc_id", TypeCode.String),
Tuple.Create("key", TypeCode.String),
Tuple.Create("value", TypeCode.String));
_table = new BlueTable(schema);
}
private void _add_doc(BsonDocument doc) {
var doc_id_bson = doc["_id"];
var doc_id = doc_id_bson.ToString();
Func<string, string, int> get_id = (string doc_id, string key) => {
string hash_key = $"{doc_id}_{key}";
int id = 0;
if (!_id_map.TryGetValue(hash_key, out id)) {
id = _id_map.Count;
_id_map.Add(hash_key, id);
}
return id;
};
foreach (var n in doc.Names) {
string key = n;
var id = get_id(doc_id, key);
MutableBlueRow nr = new MutableBlueRow(_table.schema);
var val = doc[n].ToString();
nr.setValue("id", id);
nr.setValue("doc_id", doc_id);
nr.setValue("key", key);
nr.setValue("value", val);
_table.addRow(nr);
}
}
}
[DataStreamUserRespresentation("mongodb_flat")]
public class MongoDBFlatStream : ViewStream {
public MongoDBFlatStream(string connection_string, string db_name, string collection_name, string timestamp_col, string ttl_duration)
:
this(ViewStreamDatabase.instance, connection_string, db_name, collection_name, timestamp_col, TimeBasedFilter.parse_duration(ttl_duration)) { }
public MongoDBFlatStream(ViewStreamDatabase vsd, string connection_string, string db_name, string collection_name, string timestamp_col, TimeSpan ttl_duration) {
ViewStream rs = new MongoDBStream(connection_string, db_name, collection_name, vsd);
rs = new KeyValueToRelationalStream(rs, "doc_id", "key", "val");
rs = new DateStandardizationStream(rs, timestamp_col, DateConversion.ISO8601);
//rs = new TimeBasedFilterStream(vsd, rs, timestamp_col, ttl_duration);
mySetRealSource(rs);
}
}
[DataStreamUserRespresentation("newsreplay")]
public class NewsReplayStream : ViewStream {
public NewsReplayStream(string connection_string, string db_name, string collection_name,
int buffer_sz, string fire_period) :
this(ViewStreamDatabase.instance, connection_string, db_name, collection_name, buffer_sz, TimeBasedFilter.parse_duration(fire_period)) { }
public NewsReplayStream(ViewStreamDatabase vsd, string connection_string, string db_name, string collection_name,
int buffer_sz, TimeSpan fire_period) {
ViewStream r;
r = new MongoDBStream(connection_string, db_name, collection_name, vsd);
r = new KeyValueToRelationalStream(r,
"doc_id",
"key",
"value");
r = new DateStandardizationStream(r,
"created_at",
"ISO8601");
r = new SnapshotReplayStream(vsd, r, "created_at", buffer_sz, fire_period);
mySetRealSource(r);
}
}
}
@@ -0,0 +1,172 @@
namespace bts {
using BCG;
using ProtoBuf;
using System;
using System.Collections;
using System.Collections.Generic;
public class ProjectData {
// schema from the base stream
public readonly IBlueTableSchema in_schema;
// this is the projected schema
public readonly IBlueTableSchema out_schema;
// projected cols to the input cols, for cols who's names are changed
public readonly IDictionary<string, string> mapped_to_orig_col_map = new Dictionary<string, string>();
public ProjectData(IBlueTableSchema in_schema_, IBlueTableSchema out_schema_,
IDictionary<string, string> mapped_to_orig_col_map_) {
in_schema = in_schema_;
out_schema = out_schema_;
mapped_to_orig_col_map = mapped_to_orig_col_map_;
}
}
public class NewProjectRow : IBlueRow {
#region IBlueRow members
private ProjectData _project_data;
private IBlueRow _row;
public NewProjectRow(ProjectData project_data, IBlueRow row) {
_project_data = project_data;
_row = row;
}
public IBlueTableSchema schema { get { return _project_data.out_schema; } }
#endregion
#region ICollection members
public int Count { get { return schema.columnNames.Length; } }
public bool IsSynchronized { get { return false; } }
public object SyncRoot { get { return this; } }
public void CopyTo(Array array, int index) {
int i = index;
foreach (object o in this as IEnumerable)
array.SetValue(o, i++);
}
#endregion
#region IDictionary members
public bool IsFixedSize { get { return true; } }
public bool IsReadOnly { get { return true; } }
public object this[object key] {
get {
if (key is string)
return this[(string)key];
return this[(int)key];
}
set { throw new NotSupportedException("The IBlueRow is readonly"); }
}
public object this[int index] {
get {
return this[schema.columnInfo[index].colName];
}
}
public object this[string col_name] {
get {
string mapped_to_col = null;
if (_project_data.mapped_to_orig_col_map.TryGetValue(col_name, out mapped_to_col)) {
return _row[mapped_to_col];
}
return _row[col_name];
}
}
public ICollection Keys { get { return schema.columnNames; } }
public ICollection Values {
get {
object[] retVal = new object[schema.columnNames.Length];
CopyTo(retVal, 0);
return retVal;
}
}
public void Add(object key, object value) { throw new NotSupportedException("The IBlueRow is readonly"); }
public void Clear() { throw new NotSupportedException("The IBlueRow is readonly"); }
public bool Contains(object key) { return schema[(string)key] != null; }
/// <summary>
/// Note, the default enumerator is the IDictionary's enumerator, so if user needs to
/// iterate through the values, typecast this into an IEnumerable
/// </summary>
/// <returns></returns>
public IDictionaryEnumerator GetEnumerator() { return new BlueRowDictionaryEnumerator(this); }
IEnumerator IEnumerable.GetEnumerator() { return new BlueRowEnumerator(this); }
public void Remove(object key) { throw new NotSupportedException("The IBlueRow is readonly"); }
#endregion
}
public class NewProjectStream : ViewStream, IStreamMapper {
private ViewStream _stream;
private string _project_expression;
private ProjectData _project_data = null;
//public ProjectData
public NewProjectStream(ViewStream vs, string project_expression) {
_stream = vs;
_project_expression = project_expression;
_stream = new MapStream(vs, this);
mySetRealSource(_stream);
}
public IBlueTableSchema getOutputSchema(IBlueTableSchema input_schema) {
_project_data = _create_project_data(input_schema, _project_expression);
return _project_data.out_schema;
}
public IBlueRow map(IBlueRow row) {
return new NewProjectRow(_project_data, row);
}
private static ProjectData _create_project_data(IBlueTableSchema input_schema,
string project_expression) {
project_expression = project_expression.Trim();
string[] project_toks = project_expression.Split(' ');
HashSet<string> removed_cols = new HashSet<string>();
Dictionary<string, string> mapped_to_orig_map = new Dictionary<string, string>();
Dictionary<string, string> orig_to_mapped = new Dictionary<string, string>();
foreach (string p_tok in project_toks) {
if (p_tok.StartsWith("!")) {
string removed_col = p_tok.Substring(1);
removed_cols.Add(removed_col);
} else if (p_tok.Contains(":")) {
string[] map_toks = p_tok.Split(":");
string orig_col = map_toks[0];
string mapped_col = map_toks[1];
mapped_to_orig_map.Add(mapped_col, orig_col);
orig_to_mapped.Add(orig_col, mapped_col);
} else {
Log.Gen.error($"NewProjectStream unexpecetd token: {p_tok}");
}
}
// make the new schema
List<ColumnInfo> new_cols = new List<ColumnInfo>();
foreach (ColumnInfo ci in input_schema.columnInfo) {
if (removed_cols.Contains(ci.colName)) {
continue;
} else if (orig_to_mapped.ContainsKey(ci.colName)) {
string mapped_name = orig_to_mapped[ci.colName];
ColumnInfo nc = new ColumnInfo(mapped_name, new_cols.Count, ci.colType);
new_cols.Add(nc);
} else {
ColumnInfo nc = new ColumnInfo(ci.colName, new_cols.Count, ci.colType);
new_cols.Add(nc);
}
}
IBlueTableSchema new_schema = new BlueTableSchema(input_schema.tableName, new_cols.ToArray());
return new ProjectData(input_schema, new_schema, mapped_to_orig_map);
}
}
}
@@ -8,8 +8,8 @@ namespace BCG {
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
public class ProjectStream : ViewStream [DataStreamUserRespresentation("oldproject")]
{ public class ProjectStream : ViewStream {
private ProjectHelper myHelper; private ProjectHelper myHelper;
private string myColExp, myTableName; private string myColExp, myTableName;
private ViewStream myVs; private ViewStream myVs;
@@ -19,8 +19,7 @@ namespace BCG {
/// </summary> /// </summary>
/// <param name="vs">stream to susbsribe to as the input stream</param> /// <param name="vs">stream to susbsribe to as the input stream</param>
/// <param name="colExp">expression defining the column mapping</param> /// <param name="colExp">expression defining the column mapping</param>
public ProjectStream (ViewStream vs, string colExp) public ProjectStream(ViewStream vs, string colExp) {
{
myVs = vs; myVs = vs;
myColExp = colExp; myColExp = colExp;
} }
@@ -30,12 +29,10 @@ namespace BCG {
/// <param name="vs">stream to subscribe to as the input stream</param> /// <param name="vs">stream to subscribe to as the input stream</param>
/// <param name="colExp">expression defining the column mapping</param> /// <param name="colExp">expression defining the column mapping</param>
/// <param name="tableName">name of the mapped table</param> /// <param name="tableName">name of the mapped table</param>
public ProjectStream (ViewStream vs, string colExp, string tableName) public ProjectStream(ViewStream vs, string colExp, string tableName) {
{
if (colExp == "!") if (colExp == "!")
mySetRealSource (new ChangeTableNameStream (vs, tableName)); mySetRealSource(new ChangeTableNameStream(vs, tableName));
else else {
{
myVs = vs; myVs = vs;
myColExp = colExp; myColExp = colExp;
myTableName = tableName; myTableName = tableName;
@@ -46,59 +43,51 @@ namespace BCG {
/// </summary> /// </summary>
/// <param name="vs">stream to subscribe to as the input stream</param> /// <param name="vs">stream to subscribe to as the input stream</param>
/// <param name="dic">dictionary mapping the aliased to the original</param> /// <param name="dic">dictionary mapping the aliased to the original</param>
public ProjectStream (ViewStream vs, IDictionary dic) public ProjectStream(ViewStream vs, IDictionary dic)
: this(vs, GenericDictionaryWrapper.Create<string, string>(dic)) {} : this(vs, GenericDictionaryWrapper.Create<string, string>(dic)) { }
public ProjectStream (ViewStream vs, IEnumerable<KeyValuePair<string, string>> dic) public ProjectStream(ViewStream vs, IEnumerable<KeyValuePair<string, string>> dic) {
{
myVs = vs; myVs = vs;
myDic = dic.ToDictionary(kv => kv.Value, kv => kv.Key); myDic = dic.ToDictionary(kv => kv.Value, kv => kv.Key);
} }
protected override void myOnFirstSubscriber() protected override void myOnFirstSubscriber() {
{ myVs.onChange += new BCG.DataStream.ChangeDelegate(myHandleChange);
myVs.onChange += new BCG.DataStream.ChangeDelegate (myHandleChange);
} }
protected override void myOnLastSubscriber() protected override void myOnLastSubscriber() {
{ myVs.onChange -= new BCG.DataStream.ChangeDelegate(myHandleChange); ;
myVs.onChange -= new BCG.DataStream.ChangeDelegate (myHandleChange);;
} }
internal void myHandleChange (object newValue) internal void myHandleChange(object newValue) {
{
DataPacket dp = newValue as DataPacket; DataPacket dp = newValue as DataPacket;
if (myHelper != null) if (myHelper != null) {
{
_timer.start(); _timer.start();
IBlueRowCollection dels, adds; IBlueRowCollection dels, adds;
BlueDataUtility.getTrueDeletesAndAdds (dp.deletedRows, dp.addedRows, out dels, out adds, myHelper.relevantOrigCols); BlueDataUtility.getTrueDeletesAndAdds(dp.deletedRows, dp.addedRows, out dels, out adds, myHelper.relevantOrigCols);
_timer.stop(); _timer.stop();
if (dels.Count + adds.Count > 0) if (dels.Count + adds.Count > 0)
myFireEvent (new DataPacket (new ProjectedTable (dp.newRows, myHelper), myFireEvent(new DataPacket(new ProjectedTable(dp.newRows, myHelper),
new ProjectedTable (adds, myHelper), new ProjectedTable(adds, myHelper),
new ProjectedTable (dels, myHelper) new ProjectedTable(dels, myHelper)
) )
); );
} } else { //first time a callback is received
else
{ //first time a callback is received
myHelper = myDic == null ? myHelper = myDic == null ?
new ProjectHelper (dp.schema, myColExp, myTableName) : new ProjectHelper(dp.schema, myColExp, myTableName) :
new ProjectHelper (dp.schema, myDic, myTableName); new ProjectHelper(dp.schema, myDic, myTableName);
IBlueRowCollection temp; IBlueRowCollection temp;
myFireEvent (new DataPacket (temp = new ProjectedTable (dp.newRows, myHelper), myFireEvent(new DataPacket(temp = new ProjectedTable(dp.newRows, myHelper),
temp, temp,
new BlueTable (temp.schema) new BlueTable(temp.schema)
) )
); );
} }
} }
public void myHandleChangeTest(object newValue) public void myHandleChangeTest(object newValue) {
{ myHandleChange(newValue);
myHandleChange(newValue);
} }
} }
@@ -3,24 +3,23 @@ using System.Collections.Generic;
using System.Text; using System.Text;
namespace BCG namespace BCG {
{
/// <summary> /// <summary>
/// If one adds annother value to this enum, be sure to update _date_conversion_to_type_map below as well /// If one adds annother value to this enum, be sure to update _date_conversion_to_type_map below as well
/// </summary> /// </summary>
public enum DateConversion public enum DateConversion {
{
ConvertDoubleToDateTime = 0, ConvertDoubleToDateTime = 0,
ChopTime, ChopTime,
UTCToCurrent, UTCToCurrent,
ConvertStringToDateTime, ConvertStringToDateTime,
ConvertDateTimeToMilliseconds, ConvertDateTimeToMilliseconds,
SecondsOfDay SecondsOfDay,
ISO8601,
EpochToDatetime
} }
[DataStreamUserRespresentation("dateStandardize")] [DataStreamUserRespresentation("dateStandardize")]
public class DateStandardizationStream : ViewStream, IStreamMapper public class DateStandardizationStream : ViewStream, IStreamMapper {
{
private IBlueTableSchema mySchema; private IBlueTableSchema mySchema;
private DateConversion myConversion; private DateConversion myConversion;
private string myConversionColName; private string myConversionColName;
@@ -31,12 +30,13 @@ namespace BCG
{DateConversion.UTCToCurrent , typeof(DateTime)}, {DateConversion.UTCToCurrent , typeof(DateTime)},
{DateConversion.ConvertStringToDateTime , typeof(DateTime)}, {DateConversion.ConvertStringToDateTime , typeof(DateTime)},
{DateConversion.ConvertDateTimeToMilliseconds, typeof(Double)}, {DateConversion.ConvertDateTimeToMilliseconds, typeof(Double)},
{DateConversion.SecondsOfDay , typeof(Double)} {DateConversion.SecondsOfDay , typeof(Double)},
{DateConversion.ISO8601 , typeof(DateTime)},
{DateConversion.EpochToDatetime , typeof(DateTime)}
}; };
private static DateConversion _parse(string s) private static DateConversion _parse(string s) {
{
DateConversion rv = DateConversion.ChopTime; DateConversion rv = DateConversion.ChopTime;
Enum.TryParse<DateConversion>(s, false, out rv); Enum.TryParse<DateConversion>(s, false, out rv);
return rv; return rv;
@@ -45,11 +45,9 @@ namespace BCG
/// for DSQA /// for DSQA
/// </summary> /// </summary>
public DateStandardizationStream(ViewStream vs, string colName, string conversion) public DateStandardizationStream(ViewStream vs, string colName, string conversion)
: this(vs, colName, _parse(conversion)) : this(vs, colName, _parse(conversion)) { }
{ }
public DateStandardizationStream(ViewStream vs, string colName, DateConversion conversion) public DateStandardizationStream(ViewStream vs, string colName, DateConversion conversion) {
{
myConversionColName = colName; myConversionColName = colName;
myConversion = conversion; myConversion = conversion;
mySetRealSource(new MapStream(vs, this)); mySetRealSource(new MapStream(vs, this));
@@ -57,24 +55,18 @@ namespace BCG
#region IStreamMapper Members #region IStreamMapper Members
public IBlueTableSchema getOutputSchema(IBlueTableSchema inputSchema) public IBlueTableSchema getOutputSchema(IBlueTableSchema inputSchema) {
{ if (mySchema == null) {
if (mySchema == null)
{
List<ColumnInfo> cis = new List<ColumnInfo>(); List<ColumnInfo> cis = new List<ColumnInfo>();
foreach (ColumnInfo c in inputSchema.columnInfo) foreach (ColumnInfo c in inputSchema.columnInfo) {
{ if (c.colName == myConversionColName) {
if (c.colName == myConversionColName)
{
Type convType; Type convType;
if (!_date_conversion_to_type_map.TryGetValue(myConversion, out 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); //BCG.Utilities.BlueEventLog.logEvent("Please update the _date_conversion_to_type_map in DateStandardizationStream.cs.", BCG.Utilities.BlueEventLevel.Error);
convType = typeof(DateTime); convType = typeof(DateTime);
} }
cis.Add(new ColumnInfo(c.colName, c.colNo, convType)); cis.Add(new ColumnInfo(c.colName, c.colNo, convType));
} } else
else
cis.Add(new ColumnInfo(c.colName, c.colNo, c.colType)); cis.Add(new ColumnInfo(c.colName, c.colNo, c.colType));
} }
mySchema = new BlueTableSchema(inputSchema.tableName, cis.ToArray()); mySchema = new BlueTableSchema(inputSchema.tableName, cis.ToArray());
@@ -86,56 +78,59 @@ namespace BCG
#region IDynamicStreamMapper Members #region IDynamicStreamMapper Members
public IBlueRow map(IBlueRow row) public IBlueRow map(IBlueRow row) {
{ MutableBlueRow rv = new MutableBlueRow(getOutputSchema(row.schema), row);
return BlueDataUtility.getNewReplacedRow(row, mapDateTime(row[myConversionColName], myConversion), myConversionColName); rv.setValue(myConversionColName, mapDateTime(row[myConversionColName], myConversion));
return rv;
//return BlueDataUtility.getNewReplacedRow(row, mapDateTime(row[myConversionColName], myConversion), myConversionColName);
} }
#endregion #endregion
public static object mapDateTime(object objIn, DateConversion conv) public static object mapDateTime(object obj_in, DateConversion conv) {
{ if (obj_in == DBNull.Value || obj_in == null) {
if (objIn == DBNull.Value || objIn == null)
{
return DBNull.Value; return DBNull.Value;
} } else {
else switch (conv) {
{ case DateConversion.ChopTime: {
if (conv == DateConversion.ChopTime) DateTime dtIn = (DateTime)obj_in;
{ return dtIn.Date;
DateTime dtIn = (DateTime)objIn; }
return dtIn.Date; case DateConversion.ConvertDoubleToDateTime: {
} double dtIn = (double)obj_in;
else if (conv == DateConversion.ConvertDoubleToDateTime) return DateTime.FromOADate(dtIn);
{ }
double dtIn = (double)objIn; case DateConversion.UTCToCurrent: {
return DateTime.FromOADate(dtIn); DateTime dtIn = (DateTime)obj_in;
} return dtIn.ToLocalTime();
else if (conv == DateConversion.UTCToCurrent) }
{ case DateConversion.ConvertStringToDateTime: {
DateTime dtIn = (DateTime)objIn; return DateTime.Parse((string)obj_in);
return dtIn.ToLocalTime(); }
} case DateConversion.ConvertDateTimeToMilliseconds: {
else if (conv == DateConversion.ConvertStringToDateTime) DateTime dtIn = (DateTime)obj_in;
{ return dtIn.TimeOfDay.TotalMilliseconds;
return DateTime.Parse((string)objIn); }
} case DateConversion.SecondsOfDay: {
else if (conv == DateConversion.ConvertDateTimeToMilliseconds) DateTime dtIn = (DateTime)obj_in;
{ DateTime start_of_day = dtIn.Date;
DateTime dtIn = (DateTime)objIn; TimeSpan day_period = dtIn - start_of_day;
return dtIn.TimeOfDay.TotalMilliseconds; return day_period.TotalSeconds;
} }
else if (conv == DateConversion.SecondsOfDay) case DateConversion.ISO8601: {
{ string iso8601Date = obj_in.ToString();
DateTime dtIn = (DateTime)objIn; return DateTime.Parse(iso8601Date, null, System.Globalization.DateTimeStyles.RoundtripKind);
DateTime start_of_day = dtIn.Date; }
TimeSpan day_period = dtIn - start_of_day; case DateConversion.EpochToDatetime: {
return day_period.TotalSeconds; double d = Convert.ToDouble(obj_in);
} long unix_time_seconds = (long)d;
else DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
{ return epoch.AddSeconds(unix_time_seconds);
bts.Log.Gen.info("incorrect type"); }
return null; default: {
bts.Log.Gen.info("incorrect type");
return DBNull.Value;
}
} }
} }
} }
@@ -8,38 +8,36 @@ namespace BCG {
private ViewStream mySrc; private ViewStream mySrc;
private IBlueTableSchema mySchema = null; private IBlueTableSchema mySchema = null;
public AlphabetizeColumnsStream (ViewStream src) { public AlphabetizeColumnsStream(ViewStream src) {
mySrc = src; mySrc = src;
} }
protected override void myOnFirstSubscriber() protected override void myOnFirstSubscriber() {
{
mySrc.onChange += new ChangeDelegate(mySrc_onChange); mySrc.onChange += new ChangeDelegate(mySrc_onChange);
} }
protected override void myOnLastSubscriber () protected override void myOnLastSubscriber() {
{ mySrc.onChange -= new ChangeDelegate(mySrc_onChange);
mySrc.onChange -= new ChangeDelegate (mySrc_onChange);
} }
private void mySrc_onChange (object newValue) { private void mySrc_onChange(object newValue) {
DataPacket dp = (DataPacket)newValue; DataPacket dp = (DataPacket)newValue;
if (mySchema == null) { if (mySchema == null) {
SortedList alphabetical = new SortedList (); SortedList alphabetical = new SortedList();
foreach (ColumnInfo cinfo in dp.newRows.schema.columnInfo) foreach (ColumnInfo cinfo in dp.newRows.schema.columnInfo)
alphabetical.Add (cinfo.colName,cinfo); alphabetical.Add(cinfo.colName, cinfo);
ColumnInfo[] cinfos = new ColumnInfo[alphabetical.Count]; ColumnInfo[] cinfos = new ColumnInfo[alphabetical.Count];
alphabetical.Values.CopyTo (cinfos,0); alphabetical.Values.CopyTo(cinfos, 0);
for (int i = 0; i < cinfos.Length; ++i) for (int i = 0; i < cinfos.Length; ++i)
cinfos[i] = new ColumnInfo (cinfos[i].colName,i,cinfos[i].colType,cinfos[i].colValue); cinfos[i] = new ColumnInfo(cinfos[i].colName, i, cinfos[i].colType);
mySchema = new BlueTableSchema (cinfos,dp.schema.tableName); mySchema = new BlueTableSchema(cinfos, dp.schema.tableName);
} }
BlueTable BlueTable
deleted = new BlueTable (mySchema), deleted = new BlueTable(mySchema),
added = new BlueTable (mySchema), added = new BlueTable(mySchema),
newrows = new BlueTable (mySchema); newrows = new BlueTable(mySchema);
deleted.addRows (dp.deletedRows); deleted.addRows(dp.deletedRows);
added.addRows (dp.addedRows); added.addRows(dp.addedRows);
newrows.addRows (dp.newRows); newrows.addRows(dp.newRows);
myFireEvent (new DataPacket (newrows,added,deleted)); myFireEvent(new DataPacket(newrows, added, deleted));
} }
} }
} }
@@ -1,71 +1,61 @@
using System; using System;
namespace BCG namespace BCG {
{
/// <summary> /// <summary>
/// Publishes the rows in the form of a circular buffer, ie if the buffer size is n /// Publishes the rows in the form of a circular buffer, ie if the buffer size is n
/// then the n'th row being puclished results in the deletion of the 0th row /// then the n'th row being puclished results in the deletion of the 0th row
/// </summary> /// </summary>
public class CircularPublisher public class CircularPublisher {
{
private CircularRowCollection myBuffer; private CircularRowCollection myBuffer;
private PubTableBroker myBroker; private PubTableBroker myBroker;
private int myBufferSize; private int myBufferSize;
public CircularPublisher (int bufferSize) public CircularPublisher(int bufferSize) {
{
myBufferSize = bufferSize; myBufferSize = bufferSize;
}
public CircularPublisher (int bufferSize, IBlueRowCollection rows)
: this (bufferSize)
{
publishRows (rows);
} }
public void publishRow (IBlueRow nr) public CircularPublisher(int bufferSize, IBlueRowCollection rows)
{ : this(bufferSize) {
if (myBuffer == null) publishRows(rows);
{
myBuffer = new CircularRowCollection (
new BlueTableSchema (nr.schema.tableName, nr.schema.columnInfo),
myBufferSize);
myBroker = new PubTableBroker ();
myBroker.createTable (myBuffer);
}
IBlueRow br = myBuffer.addRowWithReturn (nr);
myBroker.makeBatchChanges (myBuffer,
myReturnCollection (br),
myReturnCollection (nr));
} }
public void publishRows (IBlueRowCollection nrs) public void publishRow(IBlueRow nr) {
{ if (myBuffer == null) {
if (myBuffer == null) myBuffer = new CircularRowCollection(
{ new BlueTableSchema(nr.schema.tableName, nr.schema.columnInfo),
myBuffer = new CircularRowCollection (
new BlueTableSchema (BlueDataUtility.extractRow (nrs, 0).schema.tableName,
BlueDataUtility.extractRow (nrs, 0).schema.columnInfo),
myBufferSize); myBufferSize);
myBroker = new PubTableBroker (); myBroker = new PubTableBroker();
myBroker.createTable (myBuffer); myBroker.create_table(myBuffer);
} }
BlueTable deletes = new BlueTable (myBuffer.schema); IBlueRow br = myBuffer.addRowWithReturn(nr);
foreach (IBlueRow nr in nrs) myBroker.make_batch_changes(myBuffer,
{ myReturnCollection(br),
IBlueRow dr = myBuffer.addRowWithReturn (nr); myReturnCollection(nr));
}
public void publishRows(IBlueRowCollection nrs) {
if (myBuffer == null) {
myBuffer = new CircularRowCollection(
new BlueTableSchema(BlueDataUtility.extractRow(nrs, 0).schema.tableName,
BlueDataUtility.extractRow(nrs, 0).schema.columnInfo),
myBufferSize);
myBroker = new PubTableBroker();
myBroker.create_table(myBuffer);
}
BlueTable deletes = new BlueTable(myBuffer.schema);
foreach (IBlueRow nr in nrs) {
IBlueRow dr = myBuffer.addRowWithReturn(nr);
if (dr != null) if (dr != null)
deletes.addRow (dr); deletes.addRow(dr);
} }
myBroker.makeBatchChanges (myBuffer, deletes, nrs); myBroker.make_batch_changes(myBuffer, deletes, nrs);
} }
private IBlueRowCollection myReturnCollection (IBlueRow r) private IBlueRowCollection myReturnCollection(IBlueRow r) {
{
if (r == null) if (r == null)
return new BlueTable (myBuffer.schema); return new BlueTable(myBuffer.schema);
BlueTable retVal = new BlueTable (r.schema); BlueTable retVal = new BlueTable(r.schema);
retVal.addRow (r); retVal.addRow(r);
return retVal; return retVal;
} }
} }
} }
@@ -1,184 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Xml.Serialization;
using BCG.Utilities;
namespace BCG {
/// <summary>
/// This class will be used by the clients to publish tabular data to the pubsub
/// </summary>
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(PublisherCore publisher) { _publisher_core = publisher; }
public PubTableBroker(IBlueRowCollection[] tablesToPublish)
: this(new PublisherCore(), tablesToPublish) { }
public PubTableBroker(PublisherCore publisher, IBlueRowCollection[] tablesToPublish) {
_publisher_core = publisher;
_publisher_core.beginTransaction();
foreach (IBlueRowCollection table in tablesToPublish)
createTable(table);
_publisher_core.commitTransaction();
}
public void beginTransaction() {
myWaitingForFirstOp = true;
}
public void commitTransaction() {
bts.Log.Gen.info("PubTableBroker.commitTransaction");
if (myWaitingForFirstOp)
myWaitingForFirstOp = false;
else
_publisher_core.commitTransaction();
}
public void rollbackTransaction() {
bts.Log.Gen.info("PubTableBroker.rollbackTransaction");
if (myWaitingForFirstOp)
myWaitingForFirstOp = false;
else
_publisher_core.abortTransaction();
}
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"]}";
}
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>
/// If a table has not been created with the same instance of a PubTableBroker an ApplicationException
/// will be thrown
/// </summary>
/// <param name="r"></param>
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();
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
table_publisher.addRow(r);
}
/// <summary>
/// If a table has not been created with the same instance of a PubTableBroker an ApplicationException
/// will be thrown
/// </summary>
/// <param name="r"></param>
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();
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
table_publisher.deleteRow(r);
}
/// <summary>
/// If a table has not been created with the same instance of a PubTableBroker an ApplicationException
/// will be thrown
/// </summary>
/// <param name="r"></param>
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();
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
table_publisher.changeRow(r);
}
/// <summary>
/// If a table has not been created with the same instance of a PubTableBroker an ApplicationException
/// will be thrown
/// </summary>
/// <param name="r"></param>
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
table_publisher.batchRemoveAdd(deletedRows, addedRows);
}
public virtual void deleteTableRows(string tableName) {
myCheckTransaction();
(_publisher_map[tableName.ToLower()] as IPubTablePublisher).createTable(
new BlueTable(_schema_map[tableName.ToLower()] as IBlueTableSchema));
}
public int getNumberOfWaitingMessages() { return _publisher_core.getNumberOfWaitingMessages(); }
public void clearTable(string tableName) { _publisher_core.clearState(PubStreamPrefixer.prefix(tableName)); }
protected void myCheckTransaction() {
if (myWaitingForFirstOp)
_publisher_core.beginTransaction();
myWaitingForFirstOp = false;
}
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));
}
}
}
}
@@ -0,0 +1,31 @@
namespace BCG {
// this for testing purposes mainly, its wraps a ViewPublisher around a stream,
// and hence epublishes it out to the PS
public class PublisherStream : ViewStream {
private readonly ViewStream _main_stream;
private readonly string _name;
private ViewPublisher _vs_publisher;
private readonly PubTableBroker _broker = new PubTableBroker();
public PublisherStream(ViewStream main_stream, string name) {
_main_stream = main_stream;
_name = name;
}
protected override void myOnFirstSubscriber() {
_vs_publisher = new ViewPublisher(_name, _broker, _main_stream);
_main_stream.onChange += new DataStream.ChangeDelegate(_handle_update);
}
protected override void myOnLastSubscriber() {
_main_stream.onChange -= new DataStream.ChangeDelegate(_handle_update);
_vs_publisher.Dispose();
}
private void _handle_update(object o) {
myFireEvent(o);
}
}
}
@@ -7,48 +7,32 @@ using BCG.Utilities;
namespace BCG { namespace BCG {
public class ViewPublisher : IDisposable { public class ViewPublisher : IDisposable {
protected ViewPublisher() { } protected ViewPublisher() { }
private readonly PubTableBroker _broker;
protected readonly ViewStream _stream;
private int _n_updates = 0;
/// If an name IsNullOrEmpty then it uses the name /// If an name IsNullOrEmpty then it uses the name
/// in the schema (be careful with that because this /// in the schema (be careful with that because this
/// could lead to double publishes if the schema name /// could lead to double publishes if the schema name
/// is not uniquely chosen) /// is not uniquely chosen)
public ViewPublisher(string name, PubTableBroker br, ViewStream vs) { public ViewPublisher(string name, PubTableBroker broker, ViewStream vs) {
myName = name; _stream = String.IsNullOrEmpty(name) ? vs : new ChangeTableNameStream(vs, name);
myView = String.IsNullOrEmpty(name) ? vs : new ChangeTableNameStream(vs, name); _broker = broker;
myBroker = br; _stream.onChange += new DataStream.ChangeDelegate(_handle_update);
myFirstTime = true;
myView.onChange += new DataStream.ChangeDelegate(myChangeHandler);
} }
public void Dispose() { public void Dispose() {
myView.onChange -= new DataStream.ChangeDelegate(myChangeHandler); _stream.onChange -= new DataStream.ChangeDelegate(_handle_update);
if (!String.IsNullOrEmpty(myName))
myBroker.clearTable(myName);
} }
private void myChangeHandler(object o) { private void _handle_update(object o) {
DataPacket dp = (DataPacket)o; DataPacket dp = o as DataPacket;
if (myFirstTime) { if (_n_updates == 0) {
myName = String.IsNullOrEmpty(myName) ? dp.schema.tableName : myName; _broker.create_table(dp.newRows);
myLastRowCount = dp.newRows.Count; _n_updates++;
myBroker.createTable(dp.newRows);
myFirstTime = false;
} else { } else {
if (((dp.addedRows.Count + dp.deletedRows.Count) != 0)) { _broker.make_batch_changes(dp.newRows, dp.deletedRows, dp.addedRows);
myLastRowCount = dp.newRows.Count;
myBroker.makeBatchChanges(dp.newRows, dp.deletedRows, dp.addedRows);
}
} }
} }
public int getLastRowPublishedCount() { return myLastRowCount; }
public bool hasPublished() { return !myFirstTime; }
private int myLastRowCount = -1;
private string myName;
private PubTableBroker myBroker;
protected ViewStream myView;
private bool myFirstTime;
} }
} }
@@ -1,92 +0,0 @@
using System;
using BCG.Utilities;
namespace BCG
{
public class ViewStreamPublisher
{
private IDynamicStreamMapper myMapper;
private PubTableBroker myBroker;
private IBlueRowCollection myOutputTable;
private IBlueRowCollection myInputTable;
public ViewStreamPublisher (PubTableBroker broker)
{
myBroker = broker;
}
public ViewStreamPublisher (PubTableBroker broker, IDynamicStreamMapper mapper)
: this (broker)
{
myMapper = mapper;
}
public ViewStreamPublisher (PubTableBroker broker, IDynamicStreamMapper mapper, ViewStream vs)
: this (broker, mapper)
{
vs.onChange += new BCG.DataStream.ChangeDelegate(myHandleChanges);
}
private void myHandleChanges (object newValue)
{
DataPacket dp = newValue as DataPacket;
if (myMapper == null)
{
if (myOutputTable == null)
{
myBroker.createTable (dp.newRows);
}
else
{
myBroker.makeBatchChanges (dp.newRows, dp.deletedRows, dp.addedRows);
}
myOutputTable = dp.newRows;
}
else
{
if (myOutputTable != null)
{
BlueTable dRows = new BlueTable (myOutputTable.schema),
aRows = new BlueTable (myOutputTable.schema);
foreach (IBlueRow dRow in dp.deletedRows)
{
(myOutputTable as BlueTable).deleteRow ((int)dRow["id"]);
dRows.addRow (myMapper.map (dRow));
}
foreach (IBlueRow aRow in dp.addedRows)
{
IBlueRow r = myMapper.map (aRow);
(myOutputTable as BlueTable).addRow (r);
aRows.addRow (r);
}
myBroker.makeBatchChanges (myOutputTable, dRows, aRows);
}
else
{
if (dp.newRows.Count > 0)
{
myOutputTable = new BlueTable (
myMapper.map (BlueDataUtility.extractRow (dp.newRows, 0)).schema);
myHandleChanges (newValue);
}
}
}
}
public void addRows (IBlueRowCollection aRows)
{
if (myInputTable != null)
(myInputTable as BlueTable).addRows (aRows);
else
myInputTable = new BlueTable (aRows);
myHandleChanges (new DataPacket(myInputTable, aRows, new BlueTable (aRows.schema)));
}
public void deleteRows (IBlueRowCollection dRows)
{
// BlueEventLog.logAssert (myInputTable != null);
(myInputTable as BlueTable).deleteRows (dRows);
myHandleChanges (new DataPacket (myInputTable, new BlueTable (myInputTable.schema), dRows));
}
}
}
File diff suppressed because it is too large. Load diff
@@ -1,45 +1,42 @@
using System; using System;
namespace BCG namespace BCG {
{ /// <summary>
/// <summary> /// Allowed types
/// Allowed types /// </summary>
/// </summary> public class BlueDataValidTypes {
public class BlueDataValidTypes public static readonly Type BOOL = typeof(bool);
{ public static readonly Type BYTE = typeof(byte);
public static readonly Type BOOL = typeof(bool); public static readonly Type CHAR = typeof(char);
public static readonly Type BYTE = typeof(byte); public static readonly Type DECIMAL = typeof(decimal);
public static readonly Type CHAR = typeof(char); public static readonly Type DOUBLE = typeof(double);
public static readonly Type DECIMAL = typeof(decimal); public static readonly Type SHORT = typeof(short);
public static readonly Type DOUBLE = typeof(double); public static readonly Type INT = typeof(int);
public static readonly Type SHORT = typeof(short); public static readonly Type LONG = typeof(long);
public static readonly Type INT = typeof(int); public static readonly Type SBYTE = typeof(sbyte);
public static readonly Type LONG = typeof(long); //public static readonly Type FLOAT = typeof(float);
public static readonly Type SBYTE = typeof(sbyte); public static readonly Type STRING = typeof(string);
//public static readonly Type FLOAT = typeof(float); //public static readonly Type USHORT = typeof(ushort);
public static readonly Type STRING = typeof(string); public static readonly Type UINT = typeof(uint);
//public static readonly Type USHORT = typeof(ushort); public static readonly Type ULONG = typeof(ulong);
public static readonly Type UINT = typeof(uint); public static readonly Type DATETIME = typeof(DateTime);
public static readonly Type ULONG = typeof(ulong); public static readonly Type ISERIALIZEDTYPE = typeof(ISerializedType);
public static readonly Type DATETIME = typeof(DateTime); public static readonly Type SINGLE = typeof(Single);
public static readonly Type ISERIALIZEDTYPE = typeof(ISerializedType); public static readonly Type BYTEARRAY = typeof(byte[]);
public static readonly Type SINGLE = typeof(Single);
public static readonly Type BYTEARRAY = typeof(byte[]);
public static int getValueTypeSize (Type t) public static int getValueTypeSize(Type t) {
{ if (t == BOOL || t == BYTE || t == SBYTE)
if (t == BOOL || t == BYTE || t == SBYTE) return 1;
return 1; else if (t == SHORT || t == CHAR)
else if (t == SHORT || t == CHAR) return 2;
return 2; else if (t == INT || t == UINT || t == SINGLE)
else if (t == INT || t == UINT || t == SINGLE) return 4;
return 4; else if (t == DOUBLE || t == LONG || t == ULONG || t == DATETIME)
else if (t == DOUBLE || t == LONG || t == ULONG || t == DATETIME) return 8;
return 8; else if (t == DECIMAL)
else if (t == DECIMAL) return 16;
return 16; else
else throw new ApplicationException("Unsupported Data Type");
throw new ApplicationException("Unsupported Data Type"); }
} }
}
} }
@@ -1,116 +1,117 @@
using System; // using System;
using System.Collections.Generic; // using System.Collections.Generic;
using System.Linq; // using System.Linq;
using System.Text; // using System.Text;
/* //TODORemove
* This class reprsents one lookup group that is stored together in a lookup table because it contains repeated data patterns. // /*
* if groupNo is zero, then the group is not stord in a lookup table at all. // * This class reprsents one lookup group that is stored together in a lookup table because it contains repeated data patterns.
* // * if groupNo is zero, then the group is not stord in a lookup table at all.
* // *
* // *
*/ // *
namespace BCG // */
{ // namespace BCG
public class BlueRowLookupGroup // {
{ // public class BlueRowLookupGroup
BlueTableSchema myEntrySchema; // {
public IBlueTableSchema entrySchema // BlueTableSchema myEntrySchema;
{ // public IBlueTableSchema entrySchema
get { return myEntrySchema; } // {
//cant' set this value, have to build it from the row's schema // get { return myEntrySchema; }
// //cant' set this value, have to build it from the row's schema
} // }
//for faster access and such // //for faster access and such
private int[] myGroupColNos; // private int[] myGroupColNos;
public int[] groupColNos // public int[] groupColNos
{ // {
get { return myGroupColNos; } // get { return myGroupColNos; }
} // }
private string[] myGroupColNames; // private string[] myGroupColNames;
public string[] groupColNames // public string[] groupColNames
{ // {
get { return myGroupColNames; } // get { return myGroupColNames; }
} // }
private short myGroupNumber; // private short myGroupNumber;
public short groupNumber // public short groupNumber
{ // {
get { return myGroupNumber; } // get { return myGroupNumber; }
} // }
/* how many bits are the ids into the table?
* In c# everything is stored as integers, but when it goes across the wire
* the data can be represented as a byte, a short, or an int
*/
private short myTableSize;
public short tableSize
{
get { return myTableSize; }
} // /* how many bits are the ids into the table?
// * In c# everything is stored as integers, but when it goes across the wire
// * the data can be represented as a byte, a short, or an int
// */
// private short myTableSize;
// public short tableSize
// {
// get { return myTableSize; }
//if the group number is 0, the group is not stored in tables for serialization // }
public bool isStoredInTable
{
get { return myGroupNumber != 0; }
} // //if the group number is 0, the group is not stored in tables for serialization
public BlueRowLookupGroup(short num, short sizeInBits, params string[] cols) // public bool isStoredInTable
{ // {
// get { return myGroupNumber != 0; }
myGroupNumber = num; // }
myTableSize = sizeInBits; // public BlueRowLookupGroup(short num, short sizeInBits, params string[] cols)
myGroupColNames = cols ; // {
}
/*Takes a LookupTableSchema for the rows this group caches for, and builds the schema representing // myGroupNumber = num;
each of these entries in the lookup table. This function should be called by the LookupTableSchema // myTableSize = sizeInBits;
during its constructor. // myGroupColNames = cols ;
// }
This function also caches the column numbers for this group, for quicker access*/
public void buildEntrySchema(LookupTableSchema theSchema)
{
ColumnInfo[] columns = new ColumnInfo[myGroupColNames.Length + 1];
myGroupColNos = new int[myGroupColNames.Length];
//the first column in our table is always the ID
int idColumn = 0;
columns[idColumn] = new ColumnInfo("id", idColumn, typeof(int));
//go through each of the columns
for (int col = 1; col < columns.Length; ++col)
{
ColumnInfo columnInInputTable = theSchema[groupColNames[col - 1]];
if (columnInInputTable.isConstant)
columns[col] = new ColumnInfo(columnInInputTable.colName, col, columnInInputTable.colValue);
else
columns[col] = new ColumnInfo(columnInInputTable.colName, col, columnInInputTable.colType);
myGroupColNos[col - 1] = columnInInputTable.colNo; // /*Takes a LookupTableSchema for the rows this group caches for, and builds the schema representing
} // each of these entries in the lookup table. This function should be called by the LookupTableSchema
// during its constructor.
// This function also caches the column numbers for this group, for quicker access*/
// public void buildEntrySchema(LookupTableSchema theSchema)
// {
// ColumnInfo[] columns = new ColumnInfo[myGroupColNames.Length + 1];
// myGroupColNos = new int[myGroupColNames.Length];
// //the first column in our table is always the ID
// int idColumn = 0;
// columns[idColumn] = new ColumnInfo("id", idColumn, typeof(int));
// //go through each of the columns
// for (int col = 1; col < columns.Length; ++col)
// {
// ColumnInfo columnInInputTable = theSchema[groupColNames[col - 1]];
// if (columnInInputTable.isConstant)
// columns[col] = new ColumnInfo(columnInInputTable.colName, col, columnInInputTable.colValue);
// else
// columns[col] = new ColumnInfo(columnInInputTable.colName, col, columnInInputTable.colType);
myEntrySchema = new BlueTableSchema(columns, "Lookup Group " + theSchema.tableName + ":" + myGroupNumber); // myGroupColNos[col - 1] = columnInInputTable.colNo;
// }
}
/*takes a row as input, and extracts the members of the group from the row */
public object[] extractGroupFromRow(IBlueRow input)
{
int numCols = myGroupColNames.Length;
object[] results = new object[numCols];
for (int col = 0; col < numCols; ++col)
results[col] = input[myGroupColNos[col]];
return results;
}
} // myEntrySchema = new BlueTableSchema(columns, "Lookup Group " + theSchema.tableName + ":" + myGroupNumber);
}
// }
// /*takes a row as input, and extracts the members of the group from the row */
// public object[] extractGroupFromRow(IBlueRow input)
// {
// int numCols = myGroupColNames.Length;
// object[] results = new object[numCols];
// for (int col = 0; col < numCols; ++col)
// results[col] = input[myGroupColNos[col]];
// return results;
// }
// }
// }
@@ -8,8 +8,7 @@ using System.Linq;
using BCG.Utilities.General; using BCG.Utilities.General;
namespace BCG namespace BCG {
{
/// <summary> /// <summary>
/// The BlueTableSchema is an immutable schema holder. Once created it cannot be modified. It can be created /// The BlueTableSchema is an immutable schema holder. Once created it cannot be modified. It can be created
/// either from a DataTable or from an Array of ColumnInfo. The methods through which the user can access it /// either from a DataTable or from an Array of ColumnInfo. The methods through which the user can access it
@@ -17,112 +16,105 @@ namespace BCG
/// the respective data, sorted according to the ColumnOrder. /// the respective data, sorted according to the ColumnOrder.
/// </summary> /// </summary>
[Serializable] [Serializable]
public class BlueTableSchema : IBlueTableSchema public class BlueTableSchema : IBlueTableSchema {
{ public class BlueTableSchemaSerializationHelper {
public class BlueTableSchemaSerializationHelper // public static object parse(Type t, string data) {
{ // if (t == BlueDataValidTypes.BOOL)
public static object parse(Type t, string data) // return Boolean.Parse(data);
{ // else if (t == BlueDataValidTypes.BYTE)
if (t == BlueDataValidTypes.BOOL) // return Byte.Parse(data);
return Boolean.Parse(data); // else if (t == BlueDataValidTypes.CHAR)
else if (t == BlueDataValidTypes.BYTE) // return char.Parse(data);
return Byte.Parse(data); // else if (t == BlueDataValidTypes.DATETIME)
else if (t == BlueDataValidTypes.CHAR) // return DateTime.Parse(data);
return char.Parse(data); // else if (t == BlueDataValidTypes.DOUBLE)
else if (t == BlueDataValidTypes.DATETIME) // return Double.Parse(data);
return DateTime.Parse(data); // else if (t == BlueDataValidTypes.DECIMAL)
else if (t == BlueDataValidTypes.DOUBLE) // return Decimal.Parse(data);
return Double.Parse(data); // else if (t == BlueDataValidTypes.INT)
else if (t == BlueDataValidTypes.DECIMAL) // return int.Parse(data);
return Decimal.Parse(data); // else if (t == BlueDataValidTypes.LONG)
else if (t == BlueDataValidTypes.INT) // return long.Parse(data);
return int.Parse(data); // else if (t == BlueDataValidTypes.SBYTE)
else if (t == BlueDataValidTypes.LONG) // return SByte.Parse(data);
return long.Parse(data); // else if (t == BlueDataValidTypes.STRING)
else if (t == BlueDataValidTypes.SBYTE) // return data;
return SByte.Parse(data); // else if (t == BlueDataValidTypes.UINT)
else if (t == BlueDataValidTypes.STRING) // return uint.Parse(data);
return data; // else if (t == BlueDataValidTypes.ULONG)
else if (t == BlueDataValidTypes.UINT) // return ulong.Parse(data);
return uint.Parse(data); // else if (t == BlueDataValidTypes.SINGLE)
else if (t == BlueDataValidTypes.ULONG) // return Single.Parse(data);
return ulong.Parse(data); // else
else if (t == BlueDataValidTypes.SINGLE) // throw new ApplicationException("Can not be parsed");
return Single.Parse(data); // }
else // public static void serialize(BinaryWriter bw, Type t, object o) {
throw new ApplicationException("Can not be parsed"); // if (t == BlueDataValidTypes.BOOL)
} // bw.Write((bool)o);
public static void serialize(BinaryWriter bw, Type t, object o) // else if (t == BlueDataValidTypes.BYTE)
{ // bw.Write((byte)o);
if (t == BlueDataValidTypes.BOOL) // else if (t == BlueDataValidTypes.CHAR)
bw.Write((bool)o); // bw.Write((char)o);
else if (t == BlueDataValidTypes.BYTE) // else if (t == BlueDataValidTypes.DATETIME)
bw.Write((byte)o); // bw.Write(((DateTime)o).Ticks);
else if (t == BlueDataValidTypes.CHAR) // else if (t == BlueDataValidTypes.DOUBLE)
bw.Write((char)o); // bw.Write((double)o);
else if (t == BlueDataValidTypes.DATETIME) // else if (t == BlueDataValidTypes.DECIMAL)
bw.Write(((DateTime)o).Ticks); // bw.Write((decimal)o);
else if (t == BlueDataValidTypes.DOUBLE) // else if (t == BlueDataValidTypes.INT)
bw.Write((double)o); // bw.Write((int)o);
else if (t == BlueDataValidTypes.DECIMAL) // else if (t == BlueDataValidTypes.LONG)
bw.Write((decimal)o); // bw.Write((long)o);
else if (t == BlueDataValidTypes.INT) // else if (t == BlueDataValidTypes.SBYTE)
bw.Write((int)o); // bw.Write((sbyte)o);
else if (t == BlueDataValidTypes.LONG) // else if (t == BlueDataValidTypes.STRING)
bw.Write((long)o); // bw.Write(o as string);
else if (t == BlueDataValidTypes.SBYTE) // else if (t == BlueDataValidTypes.SINGLE)
bw.Write((sbyte)o); // bw.Write((Single)o);
else if (t == BlueDataValidTypes.STRING) // else if (t == BlueDataValidTypes.BYTEARRAY) {
bw.Write(o as string); // byte[] bs = o as byte[];
else if (t == BlueDataValidTypes.SINGLE) // bw.Write(bs.Length);
bw.Write((Single)o); // bw.Write(bs);
else if (t == BlueDataValidTypes.BYTEARRAY) // } else if (t == BlueDataValidTypes.UINT)
{ // bw.Write((uint)o);
byte[] bs = o as byte[]; // else if (t == BlueDataValidTypes.ULONG)
bw.Write(bs.Length); // bw.Write((ulong)o);
bw.Write(bs); // else
} // throw new ApplicationException("Unsupported type");
else if (t == BlueDataValidTypes.UINT) // }
bw.Write((uint)o);
else if (t == BlueDataValidTypes.ULONG)
bw.Write((ulong)o);
else
throw new ApplicationException("Unsupported type");
}
public static object deserialize(BinaryReader br, Type t) // public static object deserialize(BinaryReader br, Type t) {
{ // if (t == BlueDataValidTypes.BOOL)
if (t == BlueDataValidTypes.BOOL) // return br.ReadBoolean();
return br.ReadBoolean(); // else if (t == BlueDataValidTypes.BYTE)
else if (t == BlueDataValidTypes.BYTE) // return br.ReadByte();
return br.ReadByte(); // else if (t == BlueDataValidTypes.CHAR)
else if (t == BlueDataValidTypes.CHAR) // return br.ReadChar();
return br.ReadChar(); // else if (t == BlueDataValidTypes.DATETIME)
else if (t == BlueDataValidTypes.DATETIME) // return new DateTime(br.ReadInt64());
return new DateTime(br.ReadInt64()); // else if (t == BlueDataValidTypes.DOUBLE)
else if (t == BlueDataValidTypes.DOUBLE) // return br.ReadDouble();
return br.ReadDouble(); // else if (t == BlueDataValidTypes.DECIMAL)
else if (t == BlueDataValidTypes.DECIMAL) // return br.ReadDecimal();
return br.ReadDecimal(); // else if (t == BlueDataValidTypes.INT)
else if (t == BlueDataValidTypes.INT) // return br.ReadInt32();
return br.ReadInt32(); // else if (t == BlueDataValidTypes.LONG)
else if (t == BlueDataValidTypes.LONG) // return br.ReadInt64();
return br.ReadInt64(); // else if (t == BlueDataValidTypes.SBYTE)
else if (t == BlueDataValidTypes.SBYTE) // return br.ReadSByte();
return br.ReadSByte(); // else if (t == BlueDataValidTypes.STRING)
else if (t == BlueDataValidTypes.STRING) // return br.ReadString();
return br.ReadString(); // else if (t == BlueDataValidTypes.BYTEARRAY)
else if (t == BlueDataValidTypes.BYTEARRAY) // return br.ReadBytes(br.ReadInt32());
return br.ReadBytes(br.ReadInt32()); // else if (t == BlueDataValidTypes.UINT)
else if (t == BlueDataValidTypes.UINT) // return br.ReadUInt32();
return br.ReadUInt32(); // else if (t == BlueDataValidTypes.ULONG)
else if (t == BlueDataValidTypes.ULONG) // return br.ReadUInt64();
return br.ReadUInt64(); // else if (t == BlueDataValidTypes.SINGLE)
else if (t == BlueDataValidTypes.SINGLE) // return br.ReadSingle();
return br.ReadSingle(); // else
else // throw new ApplicationException("Unsupported type");
throw new ApplicationException("Unsupported type"); // }
}
} }
protected Hashtable myIndexByColName = new Hashtable(); protected Hashtable myIndexByColName = new Hashtable();
@@ -132,29 +124,24 @@ namespace BCG
public BlueTableSchema() { } public BlueTableSchema() { }
public BlueTableSchema(DataTable table) public BlueTableSchema(DataTable table) {
{
myIndexByColOrder = new ColumnInfo[table.Columns.Count]; myIndexByColOrder = new ColumnInfo[table.Columns.Count];
myTableName = table.TableName; myTableName = table.TableName;
foreach (DataColumn col in table.Columns) foreach (DataColumn col in table.Columns) {
{
ColumnInfo ci = new ColumnInfo(col.ColumnName, col.Ordinal, col.DataType); ColumnInfo ci = new ColumnInfo(col.ColumnName, col.Ordinal, col.DataType);
myIndexByColName[ci.colName] = ci; myIndexByColName[ci.colName] = ci;
myIndexByColOrder[ci.colNo] = ci; myIndexByColOrder[ci.colNo] = ci;
} }
} }
public BlueTableSchema(ColumnInfo[] cis, string tableName) public BlueTableSchema(ColumnInfo[] cis, string tableName) {
{
myConstruct(cis, tableName); myConstruct(cis, tableName);
} }
private void myConstruct(ColumnInfo[] cis, string tableName) private void myConstruct(ColumnInfo[] cis, string tableName) {
{
myIndexByColOrder = new ColumnInfo[cis.Length]; myIndexByColOrder = new ColumnInfo[cis.Length];
myTableName = tableName; myTableName = tableName;
foreach (ColumnInfo ci in cis) foreach (ColumnInfo ci in cis) {
{
myIndexByColOrder[ci.colNo] = ci; myIndexByColOrder[ci.colNo] = ci;
myIndexByColName[ci.colName] = ci; myIndexByColName[ci.colName] = ci;
} }
@@ -169,15 +156,13 @@ namespace BCG
/// </summary> /// </summary>
/// <param name="tableName">the table name</param> /// <param name="tableName">the table name</param>
/// <param name="fromType">the plain old data type whose fields will be mirrored in the schema</param> /// <param name="fromType">the plain old data type whose fields will be mirrored in the schema</param>
public BlueTableSchema(string tableName, Type fromType) public BlueTableSchema(string tableName, Type fromType) {
{
List<ColumnInfo> cis = new List<ColumnInfo>(); List<ColumnInfo> cis = new List<ColumnInfo>();
int i = 0; int i = 0;
// we sort the field name so that we have a deterministic order given // we sort the field name so that we have a deterministic order given
// the same type. // the same type.
bool foundId = false; bool foundId = false;
foreach (FieldInfo fi in fromType.GetFields().OrderBy((f) => { return f.Name; })) foreach (FieldInfo fi in fromType.GetFields().OrderBy((f) => { return f.Name; })) {
{
if (fi.Name.ToLower().Equals("id")) if (fi.Name.ToLower().Equals("id"))
foundId = true; foundId = true;
cis.Add(new ColumnInfo(fi.Name, i++, fi.FieldType)); cis.Add(new ColumnInfo(fi.Name, i++, fi.FieldType));
@@ -188,32 +173,25 @@ namespace BCG
myConstruct(cis.ToArray(), tableName); myConstruct(cis.ToArray(), tableName);
} }
public ColumnInfo this[string colName] public ColumnInfo this[string colName] {
{ get {
get
{
object retVal = myIndexByColName[colName]; object retVal = myIndexByColName[colName];
return retVal != null ? retVal as ColumnInfo : null; return retVal != null ? retVal as ColumnInfo : null;
} }
} }
public ColumnInfo this[int colNo] public ColumnInfo this[int colNo] {
{
get { return myIndexByColOrder[colNo]; } get { return myIndexByColOrder[colNo]; }
} }
/// <summary> /// <summary>
/// The returned Array is sorted according to the Column No /// The returned Array is sorted according to the Column No
/// </summary> /// </summary>
public string[] columnNames public string[] columnNames {
{ get {
get if (myTableColNames == null) {
{
if (myTableColNames == null)
{
myTableColNames = new string[myIndexByColName.Count]; myTableColNames = new string[myIndexByColName.Count];
foreach (DictionaryEntry de in myIndexByColName) foreach (DictionaryEntry de in myIndexByColName) {
{
ColumnInfo temp = (ColumnInfo)de.Value; ColumnInfo temp = (ColumnInfo)de.Value;
myTableColNames[temp.colNo] = temp.colName; myTableColNames[temp.colNo] = temp.colName;
} }
@@ -225,8 +203,7 @@ namespace BCG
/// <summary> /// <summary>
/// The returned Array is sorted according to the Column No /// The returned Array is sorted according to the Column No
/// </summary> /// </summary>
public ColumnInfo[] columnInfo public ColumnInfo[] columnInfo {
{
get { return myIndexByColOrder; } get { return myIndexByColOrder; }
} }
@@ -234,49 +211,30 @@ namespace BCG
#region ISerializedType methods #region ISerializedType methods
public void serialize(BinaryWriter bw) public void serialize(BinaryWriter bw) {
{
bw.Write(columnNames.Length); bw.Write(columnNames.Length);
bw.Write(tableName); bw.Write(tableName);
foreach (ColumnInfo ci in columnInfo) foreach (ColumnInfo ci in columnInfo) {
{
bw.Write(ci.colName); bw.Write(ci.colName);
bw.Write(ci.colType.ToString()); bw.Write(ci.colType.ToString());
if (ci.isConstant)
{
bw.Write(true);
BlueTableSchemaSerializationHelper.serialize(bw, ci.colType, ci.colValue);
}
else
{ {
bw.Write(false); bw.Write(false);
} }
} }
} }
public void deserialze(BinaryReader br) public void deserialze(BinaryReader br) {
{
ColumnInfo[] cis = new ColumnInfo[br.ReadInt32()]; ColumnInfo[] cis = new ColumnInfo[br.ReadInt32()];
string name = br.ReadString(); string name = br.ReadString();
for (int i = 0; i < cis.Length; i++) for (int i = 0; i < cis.Length; i++) {
{
string colName = br.ReadString(); string colName = br.ReadString();
Type t = TypeInstanceLoader.loadType(br.ReadString(), true); Type t = TypeInstanceLoader.loadType(br.ReadString(), true);
bool isConstant = br.ReadBoolean(); cis[i] = new ColumnInfo(colName, i, t);
if (isConstant)
{
cis[i] = new ColumnInfo(colName, i, t, BlueTableSchemaSerializationHelper.deserialize(br, t));
}
else
{
cis[i] = new ColumnInfo(colName, i, t);
}
} }
myConstruct(cis, name); myConstruct(cis, name);
} }
public int getSerializedSize() public int getSerializedSize() {
{
throw new NotImplementedException("Feature for provided constant values to" + throw new NotImplementedException("Feature for provided constant values to" +
"non-primitive types in schema, not provided as of now"); "non-primitive types in schema, not provided as of now");
} }
@@ -0,0 +1,59 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using BCG;
namespace bts {
public class CircularBufferTable : IBlueRowCollection {
private BlueTable _table;
private List<IBlueRow> _ordered_list = new List<IBlueRow>();
private int _buffer_sz;
public CircularBufferTable(IBlueTableSchema schema, int buffer_sz) {
_table = new BlueTable(schema);
_buffer_sz = buffer_sz;
}
// public OrderedBlueTable(List<IBlueRow> rows, int buffer_sz) {
// _buffer_sz = buffer_sz;
// foreach (IBlueRow r in rows)
// add_row(r);
// }
// returns the row that might need to be deleted to keep
// the circular buffer intact
public IBlueRow add_row(IBlueRow row) {
_ordered_list.Add(row);
_table.addRow(row);
if (_ordered_list.Count > _buffer_sz) {
IBlueRow rv = _ordered_list.ElementAt(0);
_ordered_list.RemoveAt(0);
_table.deleteRow(rv);
return rv;
}
return null;
}
public IBlueRow this[int id] {
get {
return _table[id];
}
}
public IBlueTableSchema schema {
get {
return _table.schema;
}
}
public bool containsID(int id) {
return _table.containsID(id);
}
public void CopyTo(Array array, int index) { _table.CopyTo((IBlueRow[])array, index); }
public int Count { get { return _table.Count; } }
public bool IsSynchronized { get { return false; } }
public object SyncRoot { get { return this; } }
public System.Collections.IEnumerator GetEnumerator() { return _table.GetEnumerator(); }
}
}
@@ -1,56 +1,25 @@
using System; using System;
namespace BCG namespace BCG {
{
/// <summary> /// <summary>
/// Resprsents information about a column schema, ie its ordinal, the type, the name and constant value or expression. where applicable /// Resprsents information about a column schema, ie its ordinal, the type, the name and constant value or expression. where applicable
/// </summary> /// </summary>
[Serializable] [Serializable]
public class ColumnInfo : IComparable public class ColumnInfo : IComparable {
{
public static bool isAllowedType (Type t)
{
return
t.Equals (typeof (System.Int32)) ||
t.Equals (typeof (System.Int64)) ||
t.Equals (typeof (System.Double)) ||
t.Equals (typeof (System.String)) ||
t.Equals (typeof (System.DateTime)) ? true :
false;
}
//the default column info does not cach values in a lookup table, therefore it is in group 0 //the default column info does not cach values in a lookup table, therefore it is in group 0
public ColumnInfo(string colName, int colNo, Type colType) public ColumnInfo(string colName, int colNo, Type colType) {
: this(colName, colNo, colType, 0)
{
}
public ColumnInfo(string colName, int colNo, Type colType, short colGroup)
{
myColName = colName; myColName = colName;
myColNo = colNo; myColNo = colNo;
myColType = colType; myColType = colType;
myLookupTableGroup = colGroup; }
myColValue = null;
public ColumnInfo(string col_name, int col_no, TypeCode type_code)
: this(col_name, col_no, BlueDataUtility.get_type(type_code)) {
} }
public ColumnInfo (string colName, int colNo, object colValue) public int CompareTo(object obj) {
: this (colName, colNo, colValue.GetType()) {myColValue = colValue == null ? DBNull.Value : colValue;}
public ColumnInfo (string colName, int colNo, Type colType, object colValue)
: this (colName, colNo, colType)
{
myColValue = colValue == null ? DBNull.Value : colValue;
}
public int CompareTo (object obj)
{
int otherColNo = ((ColumnInfo)(obj)).colNo; int otherColNo = ((ColumnInfo)(obj)).colNo;
if (myColNo < otherColNo) if (myColNo < otherColNo)
return -1; return -1;
@@ -59,37 +28,29 @@ namespace BCG
return 0; return 0;
} }
//public bool isCalculated{get{return myExpression != null;}} public override bool Equals(object obj) {
if (obj is ColumnInfo) {
ColumnInfo other = obj as ColumnInfo;
return (colNo == other.colNo) && (colName == other.colName) && (colType == other.colType);
}
return false;
}
public bool isConstant {get{return myColValue != null;}} public override string ToString() {
return colName + " " + colNo + " " + colType;
}
// for backwards compatibility to allow build
public bool isConstant { get { return false; } }
private int myColNo; private int myColNo;
private string myColName; private string myColName;
private Type myColType; private Type myColType;
//private string myExpression;
private object myColValue;
//no table will ever have more than 65,536 columns public int colNo { get { return myColNo; } }
//if it does, we are in serious trouble public string colName { get { return myColName; } }
private short myLookupTableGroup; public Type colType { get { return myColType; } }
public int colNo{get{return myColNo;}}
public string colName {get{return myColName;}}
public Type colType {get{return myColType;}}
//this value corresponds to how the data in the column is serialized.
//if the group number is 0, the values are not stored in a table
//if the vlaue is non-zero, all columns with the the same lookup table group are stored in the same lookup table together
//are stored together in a lookup table
public short lookupTableGroup
{
get { return myLookupTableGroup; }
set { myLookupTableGroup = value; }
}
//public string expression {get{return myExpression;}}
public object colValue {get{return myColValue;}}
} }
} }
@@ -1,252 +1,252 @@
using System; // using System;
using System.Collections; // using System.Collections;
//using BCG.Utilities; // //using BCG.Utilities;
namespace BCG // namespace BCG
{ // {
/// <summary> // /// <summary>
/// Provides a multiple indexing mechanism, required to increase the peformance of the streams // /// Provides a multiple indexing mechanism, required to increase the peformance of the streams
/// </summary> // /// </summary>
public class BlueTableIndexException : Exception // public class BlueTableIndexException : Exception
{ // {
public BlueTableIndexException(string msg) : base(msg) { } // public BlueTableIndexException(string msg) : base(msg) { }
} // }
public interface IBlueTableIndex // public interface IBlueTableIndex
{ // {
void addRow(IBlueRow row); // void addRow(IBlueRow row);
void deleteRowOnPrimaryKey(object pkValue); // void deleteRowOnPrimaryKey(object pkValue);
void deleteRowOnPrimaryKey(IBlueRow row); // void deleteRowOnPrimaryKey(IBlueRow row);
void deleteRowOnBothKeys(object pkValue, object skValue); // void deleteRowOnBothKeys(object pkValue, object skValue);
void deleteRowOnBothKeys(IBlueRow row); // void deleteRowOnBothKeys(IBlueRow row);
ArrayList searchRowOnPrimaryKey(object pkValue); // ArrayList searchRowOnPrimaryKey(object pkValue);
ArrayList searchRowOnPrimaryKey(IBlueRow row); // ArrayList searchRowOnPrimaryKey(IBlueRow row);
ArrayList searchRowOnBothKeys(object pkValue, object skValue); // ArrayList searchRowOnBothKeys(object pkValue, object skValue);
ArrayList searchRowOnBothKeys(IBlueRow row); // ArrayList searchRowOnBothKeys(IBlueRow row);
} // }
/* // /*
public class BlueTableDoubleIndex : IBlueTableIndex // public class BlueTableDoubleIndex : IBlueTableIndex
{ // {
private IBlueRowCollection myTable; // private IBlueRowCollection myTable;
private string myPrimaryIndex; // private string myPrimaryIndex;
private string mySecondaryIndex; // private string mySecondaryIndex;
private Hashtable myHt = new Hashtable (); // private Hashtable myHt = new Hashtable ();
/// <summary>
/// Builds an index with 2 columns of the table acting as primary index and secondary index
/// respectively
/// </summary>
/// <param name="table">
/// table to index
/// </param>
/// <param name="primaryIndex">
/// primary key to index upon
/// </param>
/// <param name="secondaryIndex">
/// column serving as the secondary key
/// </param>
public BlueTableDoubleIndex (IBlueRowCollection table, string primaryIndex, string secondaryIndex)
{
myTable = table;
myPrimaryIndex = primaryIndex;
mySecondaryIndex = secondaryIndex;
myInit ();
}
private void myInit()
{
foreach (IBlueRow row in myTable)
addRow (row);
}
/// <summary> // /// <summary>
/// To add a row to the index // /// Builds an index with 2 columns of the table acting as primary index and secondary index
/// </summary> // /// respectively
/// <param name="row"> // /// </summary>
/// row to be added // /// <param name="table">
/// </param> // /// table to index
public void addRow (IBlueRow row) // /// </param>
{ // /// <param name="primaryIndex">
if (myHt[row[myPrimaryIndex]] != null) // /// primary key to index upon
((Hashtable)(myHt[row[myPrimaryIndex]]))[row[mySecondaryIndex]] = row; // /// </param>
else // /// <param name="secondaryIndex">
{ // /// column serving as the secondary key
TimeManager.start (); // /// </param>
Hashtable ht = new Hashtable(); // public BlueTableDoubleIndex (IBlueRowCollection table, string primaryIndex, string secondaryIndex)
TimeManager.stop (); // {
ht[row[mySecondaryIndex]] = row; // myTable = table;
myHt[row[myPrimaryIndex]] = ht; // myPrimaryIndex = primaryIndex;
} // mySecondaryIndex = secondaryIndex;
} // myInit ();
// }
/// <summary> // private void myInit()
/// If index or the primary key has already been deleted appropriate exceptions are thrown // {
/// </summary> // foreach (IBlueRow row in myTable)
/// <param name="row"></param> // addRow (row);
public void deleteRow (IBlueRow row) // }
{
if (myHt[row[myPrimaryIndex]] == null)
{
throw new BlueTableIndexException ("Theres no index (primary hash table key) for this index value");
}
((Hashtable)(myHt[row[myPrimaryIndex]])).Remove(row[mySecondaryIndex]);
if (((Hashtable)(myHt[row[myPrimaryIndex]])).Keys.Count == 0)
myHt.Remove(row[myPrimaryIndex]);
}
/// <summary> // /// <summary>
/// Returns an array of DataRow that match the primary key being passed as an argument // /// To add a row to the index
/// </summary> // /// </summary>
/// <param name="o"> // /// <param name="row">
/// Primary Key of the table // /// row to be added
/// </param> // /// </param>
/// <returns> // public void addRow (IBlueRow row)
/// Array of rows matching the criteria // {
/// </returns> // if (myHt[row[myPrimaryIndex]] != null)
public IBlueRow[] findValueFromPrimaryKey (object o) // ((Hashtable)(myHt[row[myPrimaryIndex]]))[row[mySecondaryIndex]] = row;
{ // else
object oht = myHt[o]; // {
if (oht == null) // TimeManager.start ();
return new IBlueRow[0]; // Hashtable ht = new Hashtable();
Hashtable ht = (Hashtable)oht; // TimeManager.stop ();
IBlueRow[] rows = new IBlueRow[ht.Keys.Count]; // ht[row[mySecondaryIndex]] = row;
ht.Values.CopyTo(rows, 0); // myHt[row[myPrimaryIndex]] = ht;
return rows; // }
} // }
// /// <summary>
// /// If index or the primary key has already been deleted appropriate exceptions are thrown
// /// </summary>
// /// <param name="row"></param>
// public void deleteRow (IBlueRow row)
// {
// if (myHt[row[myPrimaryIndex]] == null)
// {
// throw new BlueTableIndexException ("Theres no index (primary hash table key) for this index value");
// }
// ((Hashtable)(myHt[row[myPrimaryIndex]])).Remove(row[mySecondaryIndex]);
// if (((Hashtable)(myHt[row[myPrimaryIndex]])).Keys.Count == 0)
// myHt.Remove(row[myPrimaryIndex]);
// }
// /// <summary>
// /// Returns an array of DataRow that match the primary key being passed as an argument
// /// </summary>
// /// <param name="o">
// /// Primary Key of the table
// /// </param>
// /// <returns>
// /// Array of rows matching the criteria
// /// </returns>
// public IBlueRow[] findValueFromPrimaryKey (object o)
// {
// object oht = myHt[o];
// if (oht == null)
// return new IBlueRow[0];
// Hashtable ht = (Hashtable)oht;
// IBlueRow[] rows = new IBlueRow[ht.Keys.Count];
// ht.Values.CopyTo(rows, 0);
// return rows;
// }
/// <summary> // /// <summary>
/// returns as array of the primary keys // /// returns as array of the primary keys
/// </summary> // /// </summary>
/// <returns> // /// <returns>
/// object[] of primary keys // /// object[] of primary keys
/// </returns> // /// </returns>
public Array getPrimaryKeys() // public Array getPrimaryKeys()
{ // {
object[] retval = new object [myHt.Keys.Count]; // object[] retval = new object [myHt.Keys.Count];
myHt.Keys.CopyTo (retval, 0); // myHt.Keys.CopyTo (retval, 0);
return retval; // return retval;
} // }
} // }
*/ // */
/// <summary> // /// <summary>
/// Provides a 1-Level indexing structure. // /// Provides a 1-Level indexing structure.
/// </summary> // /// </summary>
public class BlueTableSingleIndex : IBlueTableIndex // public class BlueTableSingleIndex : IBlueTableIndex
{ // {
string myPrimaryKey; // string myPrimaryKey;
string mySecondaryKey; // string mySecondaryKey;
Hashtable myHt = new Hashtable(); // Hashtable myHt = new Hashtable();
public BlueTableSingleIndex(string primaryKey, string secondaryKey) // public BlueTableSingleIndex(string primaryKey, string secondaryKey)
{ // {
myPrimaryKey = primaryKey; // myPrimaryKey = primaryKey;
mySecondaryKey = secondaryKey; // mySecondaryKey = secondaryKey;
} // }
/// <summary> // /// <summary>
/// The primary key is the indexing key, and the secondary key is used as the key for // /// The primary key is the indexing key, and the secondary key is used as the key for
/// searching and hence deletion // /// searching and hence deletion
/// </summary> // /// </summary>
/// <param name="table"></param> // /// <param name="table"></param>
/// <param name="primaryKey"></param> // /// <param name="primaryKey"></param>
/// <param name="secondaryKey"></param> // /// <param name="secondaryKey"></param>
public BlueTableSingleIndex(IBlueRowCollection table, string primaryKey, string secondaryKey) // public BlueTableSingleIndex(IBlueRowCollection table, string primaryKey, string secondaryKey)
: this(primaryKey, secondaryKey) // : this(primaryKey, secondaryKey)
{ // {
foreach (IBlueRow row in table) // foreach (IBlueRow row in table)
addRow(row); // addRow(row);
} // }
/// <summary> // /// <summary>
/// Adds row to the indexing new structure // /// Adds row to the indexing new structure
/// </summary> // /// </summary>
/// <param name="row"></param> // /// <param name="row"></param>
public void addRow(IBlueRow row) // public void addRow(IBlueRow row)
{ // {
if (myHt[row[myPrimaryKey]] == null) // if (myHt[row[myPrimaryKey]] == null)
myHt[row[myPrimaryKey]] = new ArrayList(); // myHt[row[myPrimaryKey]] = new ArrayList();
((ArrayList)(myHt[row[myPrimaryKey]])).Add(row); // ((ArrayList)(myHt[row[myPrimaryKey]])).Add(row);
} // }
/// <summary> // /// <summary>
/// Getts rows based on the Primary Key. Matching of the primary key is the only criteria // /// Getts rows based on the Primary Key. Matching of the primary key is the only criteria
/// </summary> // /// </summary>
/// <param name="row"></param> // /// <param name="row"></param>
/// <returns></returns> // /// <returns></returns>
public ArrayList searchRowOnPrimaryKey(IBlueRow row) // public ArrayList searchRowOnPrimaryKey(IBlueRow row)
{ // {
return searchRowOnPrimaryKey(row[myPrimaryKey]); // return searchRowOnPrimaryKey(row[myPrimaryKey]);
} // }
public ArrayList searchRowOnPrimaryKey(object pkValue) // public ArrayList searchRowOnPrimaryKey(object pkValue)
{ // {
if (myHt[pkValue] == null) // if (myHt[pkValue] == null)
return new ArrayList(); // return new ArrayList();
return (ArrayList)myHt[pkValue]; // return (ArrayList)myHt[pkValue];
} // }
/// <summary> // /// <summary>
/// Gets rows based on the primary AND the secondary key // /// Gets rows based on the primary AND the secondary key
/// </summary> // /// </summary>
/// <param name="row"></param> // /// <param name="row"></param>
/// <returns></returns> // /// <returns></returns>
public ArrayList searchRowOnBothKeys(IBlueRow row) // public ArrayList searchRowOnBothKeys(IBlueRow row)
{ // {
return searchRowOnBothKeys(row[myPrimaryKey], row[mySecondaryKey]); // return searchRowOnBothKeys(row[myPrimaryKey], row[mySecondaryKey]);
} // }
public ArrayList searchRowOnBothKeys(object pkValue, object skValue) // public ArrayList searchRowOnBothKeys(object pkValue, object skValue)
{ // {
if (myHt[pkValue] == null) // if (myHt[pkValue] == null)
return new ArrayList(); // return new ArrayList();
ArrayList matchingList = (ArrayList)myHt[pkValue]; // ArrayList matchingList = (ArrayList)myHt[pkValue];
ArrayList retVal = new ArrayList(); // ArrayList retVal = new ArrayList();
foreach (IBlueRow r in matchingList) // foreach (IBlueRow r in matchingList)
if (r[mySecondaryKey].Equals(skValue)) // if (r[mySecondaryKey].Equals(skValue))
retVal.Add(r); // retVal.Add(r);
return retVal; // return retVal;
} // }
/// <summary> // /// <summary>
/// Deletes rows based on the primary key only // /// Deletes rows based on the primary key only
/// </summary> // /// </summary>
/// <param name="row"></param> // /// <param name="row"></param>
public void deleteRowOnPrimaryKey(IBlueRow row) // public void deleteRowOnPrimaryKey(IBlueRow row)
{ // {
deleteRowOnPrimaryKey(row[myPrimaryKey]); // deleteRowOnPrimaryKey(row[myPrimaryKey]);
} // }
public void deleteRowOnPrimaryKey(object pkValue) // public void deleteRowOnPrimaryKey(object pkValue)
{ // {
if (myHt[pkValue] == null) // if (myHt[pkValue] == null)
throw new BlueTableIndexException("Key to be deleted was not found in the index"); // throw new BlueTableIndexException("Key to be deleted was not found in the index");
myHt.Remove(pkValue); // myHt.Remove(pkValue);
} // }
public void deleteRowOnBothKeys(IBlueRow row) // public void deleteRowOnBothKeys(IBlueRow row)
{ // {
deleteRowOnBothKeys(row[myPrimaryKey], row[mySecondaryKey]); // deleteRowOnBothKeys(row[myPrimaryKey], row[mySecondaryKey]);
} // }
public void deleteRowOnBothKeys(object pkValue, object skValue) // public void deleteRowOnBothKeys(object pkValue, object skValue)
{ // {
if (myHt[pkValue] == null) // if (myHt[pkValue] == null)
throw new BlueTableIndexException("Key to be deleted was not found in the index"); // throw new BlueTableIndexException("Key to be deleted was not found in the index");
ArrayList matchingList = (ArrayList)myHt[pkValue]; // ArrayList matchingList = (ArrayList)myHt[pkValue];
ArrayList aux = new ArrayList(); // ArrayList aux = new ArrayList();
foreach (IBlueRow r in matchingList) // foreach (IBlueRow r in matchingList)
if (r[mySecondaryKey].Equals(skValue)) // if (r[mySecondaryKey].Equals(skValue))
aux.Add(r); // aux.Add(r);
foreach (IBlueRow r in aux) // foreach (IBlueRow r in aux)
matchingList.Remove(r); // matchingList.Remove(r);
} // }
} // }
} // }
@@ -1,324 +1,324 @@
using System; // using System;
using System.Data; // using System.Data;
using System.Collections; // using System.Collections;
using System.IO; // using System.IO;
using System.Reflection; // using System.Reflection;
using System.Collections.Generic; // using System.Collections.Generic;
using System.Linq; // using System.Linq;
using BCG.Utilities.General; // using BCG.Utilities.General;
namespace BCG // namespace BCG
{ // {
/// <summary> // /// <summary>
/// The LookupTableSchema is an immutable schema holder. Once created it cannot be modified. It can be created // /// The LookupTableSchema is an immutable schema holder. Once created it cannot be modified. It can be created
/// either from a DataTable or from an Array of ColumnInfo. The methods through which the user can access it // /// either from a DataTable or from an Array of ColumnInfo. The methods through which the user can access it
/// are the indexers (both order and name based), and the property columnInfo and columnNames, that return // /// are the indexers (both order and name based), and the property columnInfo and columnNames, that return
/// the respective data, sorted according to the ColumnOrder. // /// the respective data, sorted according to the ColumnOrder.
/// </summary> // /// </summary>
[Serializable] // [Serializable]
public class LookupTableSchema : IBlueTableSchema // public class LookupTableSchema : IBlueTableSchema
{ // {
public class LookupTableSchemaSerializationHelper // public class LookupTableSchemaSerializationHelper
{ // {
public static object parse(Type t, string data) // public static object parse(Type t, string data)
{ // {
if (t == BlueDataValidTypes.BOOL) // if (t == BlueDataValidTypes.BOOL)
return Boolean.Parse(data); // return Boolean.Parse(data);
else if (t == BlueDataValidTypes.BYTE) // else if (t == BlueDataValidTypes.BYTE)
return Byte.Parse(data); // return Byte.Parse(data);
else if (t == BlueDataValidTypes.CHAR) // else if (t == BlueDataValidTypes.CHAR)
return char.Parse(data); // return char.Parse(data);
else if (t == BlueDataValidTypes.DATETIME) // else if (t == BlueDataValidTypes.DATETIME)
return DateTime.Parse(data); // return DateTime.Parse(data);
else if (t == BlueDataValidTypes.DOUBLE) // else if (t == BlueDataValidTypes.DOUBLE)
return Double.Parse(data); // return Double.Parse(data);
else if (t == BlueDataValidTypes.DECIMAL) // else if (t == BlueDataValidTypes.DECIMAL)
return Decimal.Parse(data); // return Decimal.Parse(data);
else if (t == BlueDataValidTypes.INT) // else if (t == BlueDataValidTypes.INT)
return int.Parse(data); // return int.Parse(data);
else if (t == BlueDataValidTypes.LONG) // else if (t == BlueDataValidTypes.LONG)
return long.Parse(data); // return long.Parse(data);
else if (t == BlueDataValidTypes.SBYTE) // else if (t == BlueDataValidTypes.SBYTE)
return SByte.Parse(data); // return SByte.Parse(data);
else if (t == BlueDataValidTypes.STRING) // else if (t == BlueDataValidTypes.STRING)
return data; // return data;
else if (t == BlueDataValidTypes.UINT) // else if (t == BlueDataValidTypes.UINT)
return uint.Parse(data); // return uint.Parse(data);
else if (t == BlueDataValidTypes.ULONG) // else if (t == BlueDataValidTypes.ULONG)
return ulong.Parse(data); // return ulong.Parse(data);
else if (t == BlueDataValidTypes.SINGLE) // else if (t == BlueDataValidTypes.SINGLE)
return Single.Parse(data); // return Single.Parse(data);
else // else
throw new ApplicationException("Can not be parsed"); // throw new ApplicationException("Can not be parsed");
} // }
public static void serialize(BinaryWriter bw, Type t, object o) // public static void serialize(BinaryWriter bw, Type t, object o)
{ // {
if (t == BlueDataValidTypes.BOOL) // if (t == BlueDataValidTypes.BOOL)
bw.Write((bool)o); // bw.Write((bool)o);
else if (t == BlueDataValidTypes.BYTE) // else if (t == BlueDataValidTypes.BYTE)
bw.Write((byte)o); // bw.Write((byte)o);
else if (t == BlueDataValidTypes.CHAR) // else if (t == BlueDataValidTypes.CHAR)
bw.Write((char)o); // bw.Write((char)o);
else if (t == BlueDataValidTypes.DATETIME) // else if (t == BlueDataValidTypes.DATETIME)
bw.Write(((DateTime)o).Ticks); // bw.Write(((DateTime)o).Ticks);
else if (t == BlueDataValidTypes.DOUBLE) // else if (t == BlueDataValidTypes.DOUBLE)
bw.Write((double)o); // bw.Write((double)o);
else if (t == BlueDataValidTypes.DECIMAL) // else if (t == BlueDataValidTypes.DECIMAL)
bw.Write((decimal)o); // bw.Write((decimal)o);
else if (t == BlueDataValidTypes.INT) // else if (t == BlueDataValidTypes.INT)
bw.Write((int)o); // bw.Write((int)o);
else if (t == BlueDataValidTypes.LONG) // else if (t == BlueDataValidTypes.LONG)
bw.Write((long)o); // bw.Write((long)o);
else if (t == BlueDataValidTypes.SBYTE) // else if (t == BlueDataValidTypes.SBYTE)
bw.Write((sbyte)o); // bw.Write((sbyte)o);
else if (t == BlueDataValidTypes.STRING) // else if (t == BlueDataValidTypes.STRING)
bw.Write(o as string); // bw.Write(o as string);
else if (t == BlueDataValidTypes.SINGLE) // else if (t == BlueDataValidTypes.SINGLE)
bw.Write((Single)o); // bw.Write((Single)o);
else if (t == BlueDataValidTypes.BYTEARRAY) // else if (t == BlueDataValidTypes.BYTEARRAY)
{ // {
byte[] bs = o as byte[]; // byte[] bs = o as byte[];
bw.Write(bs.Length); // bw.Write(bs.Length);
bw.Write(bs); // bw.Write(bs);
} // }
else if (t == BlueDataValidTypes.UINT) // else if (t == BlueDataValidTypes.UINT)
bw.Write((uint)o); // bw.Write((uint)o);
else if (t == BlueDataValidTypes.ULONG) // else if (t == BlueDataValidTypes.ULONG)
bw.Write((ulong)o); // bw.Write((ulong)o);
else // else
throw new ApplicationException("Unsupported type"); // throw new ApplicationException("Unsupported type");
} // }
public static object deserialize(BinaryReader br, Type t) // public static object deserialize(BinaryReader br, Type t)
{ // {
if (t == BlueDataValidTypes.BOOL) // if (t == BlueDataValidTypes.BOOL)
return br.ReadBoolean(); // return br.ReadBoolean();
else if (t == BlueDataValidTypes.BYTE) // else if (t == BlueDataValidTypes.BYTE)
return br.ReadByte(); // return br.ReadByte();
else if (t == BlueDataValidTypes.CHAR) // else if (t == BlueDataValidTypes.CHAR)
return br.ReadChar(); // return br.ReadChar();
else if (t == BlueDataValidTypes.DATETIME) // else if (t == BlueDataValidTypes.DATETIME)
return new DateTime(br.ReadInt64()); // return new DateTime(br.ReadInt64());
else if (t == BlueDataValidTypes.DOUBLE) // else if (t == BlueDataValidTypes.DOUBLE)
return br.ReadDouble(); // return br.ReadDouble();
else if (t == BlueDataValidTypes.DECIMAL) // else if (t == BlueDataValidTypes.DECIMAL)
return br.ReadDecimal(); // return br.ReadDecimal();
else if (t == BlueDataValidTypes.INT) // else if (t == BlueDataValidTypes.INT)
return br.ReadInt32(); // return br.ReadInt32();
else if (t == BlueDataValidTypes.LONG) // else if (t == BlueDataValidTypes.LONG)
return br.ReadInt64(); // return br.ReadInt64();
else if (t == BlueDataValidTypes.SBYTE) // else if (t == BlueDataValidTypes.SBYTE)
return br.ReadSByte(); // return br.ReadSByte();
else if (t == BlueDataValidTypes.STRING) // else if (t == BlueDataValidTypes.STRING)
return br.ReadString(); // return br.ReadString();
else if (t == BlueDataValidTypes.BYTEARRAY) // else if (t == BlueDataValidTypes.BYTEARRAY)
return br.ReadBytes(br.ReadInt32()); // return br.ReadBytes(br.ReadInt32());
else if (t == BlueDataValidTypes.UINT) // else if (t == BlueDataValidTypes.UINT)
return br.ReadUInt32(); // return br.ReadUInt32();
else if (t == BlueDataValidTypes.ULONG) // else if (t == BlueDataValidTypes.ULONG)
return br.ReadUInt64(); // return br.ReadUInt64();
else if (t == BlueDataValidTypes.SINGLE) // else if (t == BlueDataValidTypes.SINGLE)
return br.ReadSingle(); // return br.ReadSingle();
else // else
throw new ApplicationException("Unsupported type"); // throw new ApplicationException("Unsupported type");
} // }
} // }
protected Hashtable myIndexByColName = new Hashtable(); // protected Hashtable myIndexByColName = new Hashtable();
protected ColumnInfo[] myIndexByColOrder; // protected ColumnInfo[] myIndexByColOrder;
private string[] myTableColNames; // private string[] myTableColNames;
private BlueRowLookupGroup[] myLookupGroups; // private BlueRowLookupGroup[] myLookupGroups;
protected string myTableName; // protected string myTableName;
public LookupTableSchema() { } // public LookupTableSchema() { }
public LookupTableSchema(string tableName, ColumnInfo[] cis, BlueRowLookupGroup[] groups) // public LookupTableSchema(string tableName, ColumnInfo[] cis, BlueRowLookupGroup[] groups)
{ // {
myConstruct(tableName, cis, groups); // myConstruct(tableName, cis, groups);
} // }
private void myConstruct(string tableName, ColumnInfo[] cis, BlueRowLookupGroup[] groups) // private void myConstruct(string tableName, ColumnInfo[] cis, BlueRowLookupGroup[] groups)
{ // {
myIndexByColOrder = new ColumnInfo[cis.Length]; // myIndexByColOrder = new ColumnInfo[cis.Length];
myTableName = tableName; // myTableName = tableName;
foreach (ColumnInfo ci in cis) // foreach (ColumnInfo ci in cis)
{ // {
myIndexByColOrder[ci.colNo] = ci; // myIndexByColOrder[ci.colNo] = ci;
myIndexByColName[ci.colName] = ci; // myIndexByColName[ci.colName] = ci;
} // }
myLookupGroups = groups; // myLookupGroups = groups;
foreach (BlueRowLookupGroup group in groups) // foreach (BlueRowLookupGroup group in groups)
{ // {
group.buildEntrySchema(this); // group.buildEntrySchema(this);
} // }
} // }
public ColumnInfo this[string colName] // public ColumnInfo this[string colName]
{ // {
get // get
{ // {
object retVal = myIndexByColName[colName]; // object retVal = myIndexByColName[colName];
return retVal != null ? retVal as ColumnInfo : null; // return retVal != null ? retVal as ColumnInfo : null;
} // }
} // }
public BlueRowLookupGroup[] lookupGroups // public BlueRowLookupGroup[] lookupGroups
{ // {
get { return myLookupGroups; } // get { return myLookupGroups; }
} // }
public ColumnInfo this[int colNo] // public ColumnInfo this[int colNo]
{ // {
get { return myIndexByColOrder[colNo]; } // get { return myIndexByColOrder[colNo]; }
} // }
/// <summary> // /// <summary>
/// The returned Array is sorted according to the Column No // /// The returned Array is sorted according to the Column No
/// </summary> // /// </summary>
public string[] columnNames // public string[] columnNames
{ // {
get // get
{ // {
if (myTableColNames == null) // if (myTableColNames == null)
{ // {
myTableColNames = new string[myIndexByColName.Count]; // myTableColNames = new string[myIndexByColName.Count];
foreach (DictionaryEntry de in myIndexByColName) // foreach (DictionaryEntry de in myIndexByColName)
{ // {
ColumnInfo temp = (ColumnInfo)de.Value; // ColumnInfo temp = (ColumnInfo)de.Value;
myTableColNames[temp.colNo] = temp.colName; // myTableColNames[temp.colNo] = temp.colName;
} // }
} // }
return myTableColNames; // return myTableColNames;
} // }
} // }
/// <summary> // /// <summary>
/// The returned Array is sorted according to the Column No // /// The returned Array is sorted according to the Column No
/// </summary> // /// </summary>
public ColumnInfo[] columnInfo // public ColumnInfo[] columnInfo
{ // {
get { return myIndexByColOrder; } // get { return myIndexByColOrder; }
} // }
public string tableName { get { return myTableName; } } // public string tableName { get { return myTableName; } }
#region ISerializedType methods // #region ISerializedType methods
public void serialize(BinaryWriter bw) // public void serialize(BinaryWriter bw)
{ // {
bw.Write(columnNames.Length); // bw.Write(columnNames.Length);
bw.Write(tableName); // bw.Write(tableName);
//first, write the column names // //first, write the column names
foreach (ColumnInfo ci in columnInfo) // foreach (ColumnInfo ci in columnInfo)
{ // {
bw.Write(ci.colName); // bw.Write(ci.colName);
bw.Write(ci.colType.ToString()); // bw.Write(ci.colType.ToString());
if (ci.isConstant) // if (ci.isConstant)
{ // {
bw.Write(true); // bw.Write(true);
LookupTableSchemaSerializationHelper.serialize(bw, ci.colType, ci.colValue); // LookupTableSchemaSerializationHelper.serialize(bw, ci.colType, ci.colValue);
} // }
else // else
{ // {
bw.Write(false); // bw.Write(false);
bw.Write(ci.lookupTableGroup); // bw.Write(ci.lookupTableGroup);
} // }
} // }
//this is here for error checking // //this is here for error checking
bw.Write(myLookupGroups.Length); // bw.Write(myLookupGroups.Length);
//now, write the size of each lookup table group // //now, write the size of each lookup table group
foreach (BlueRowLookupGroup group in myLookupGroups) // foreach (BlueRowLookupGroup group in myLookupGroups)
{ // {
bw.Write(group.groupNumber); // bw.Write(group.groupNumber);
bw.Write(group.tableSize); // bw.Write(group.tableSize);
bw.Write(group.groupColNames.Length); // bw.Write(group.groupColNames.Length);
foreach (string colName in group.groupColNames) // foreach (string colName in group.groupColNames)
{ // {
//write the index of this column in the table // //write the index of this column in the table
bw.Write(this[colName].colNo); // bw.Write(this[colName].colNo);
} // }
} // }
} // }
public void deserialze(BinaryReader br) // public void deserialze(BinaryReader br)
{ // {
int numCols = br.ReadInt32(); // int numCols = br.ReadInt32();
//these are the final output columns that will be created // //these are the final output columns that will be created
ColumnInfo[] columnInfos = new ColumnInfo[numCols]; // ColumnInfo[] columnInfos = new ColumnInfo[numCols];
Dictionary<int, List<string>> colLookupGroupMap = new Dictionary<int, List<string>>(); // Dictionary<int, List<string>> colLookupGroupMap = new Dictionary<int, List<string>>();
string tableName = br.ReadString(); // string tableName = br.ReadString();
for (int colNo = 0; colNo < numCols; ++colNo) // for (int colNo = 0; colNo < numCols; ++colNo)
{ // {
string colName = br.ReadString(); // string colName = br.ReadString();
Type colType = TypeInstanceLoader.loadType(br.ReadString(), true); // Type colType = TypeInstanceLoader.loadType(br.ReadString(), true);
bool colIsConst = br.ReadBoolean(); // bool colIsConst = br.ReadBoolean();
if (colIsConst) // if (colIsConst)
{ // {
columnInfos[colNo] = new ColumnInfo(colName, colNo, LookupTableSchemaSerializationHelper.deserialize(br, colType)); // columnInfos[colNo] = new ColumnInfo(colName, colNo, LookupTableSchemaSerializationHelper.deserialize(br, colType));
} // }
else // else
{ // {
short thisColGroup = br.ReadInt16(); // short thisColGroup = br.ReadInt16();
columnInfos[colNo] = new ColumnInfo(colName, colNo, colType, thisColGroup); // columnInfos[colNo] = new ColumnInfo(colName, colNo, colType, thisColGroup);
} // }
} // }
int numGroups = br.ReadInt32(); // int numGroups = br.ReadInt32();
BlueRowLookupGroup[] theGroups = new BlueRowLookupGroup[numGroups]; // BlueRowLookupGroup[] theGroups = new BlueRowLookupGroup[numGroups];
for (int group = 0; group < numGroups; ++group) // for (int group = 0; group < numGroups; ++group)
{ // {
short groupNo = br.ReadInt16(); // short groupNo = br.ReadInt16();
short groupSizeInBits = br.ReadInt16(); // short groupSizeInBits = br.ReadInt16();
int numColsInGroup = br.ReadInt32(); // int numColsInGroup = br.ReadInt32();
int[] groupCols = new int[numColsInGroup]; // int[] groupCols = new int[numColsInGroup];
string[] groupColNames = new string[numColsInGroup]; // string[] groupColNames = new string[numColsInGroup];
for (int col = 0; col < numColsInGroup; ++col) // for (int col = 0; col < numColsInGroup; ++col)
{ // {
groupCols[col] = br.ReadInt32(); // groupCols[col] = br.ReadInt32();
groupColNames[col] = columnInfos[groupCols[col]].colName; // groupColNames[col] = columnInfos[groupCols[col]].colName;
} // }
//create the group // //create the group
theGroups[groupNo] = new BlueRowLookupGroup(groupNo, groupSizeInBits, groupColNames); // theGroups[groupNo] = new BlueRowLookupGroup(groupNo, groupSizeInBits, groupColNames);
} // }
myConstruct(tableName, columnInfos, theGroups); // myConstruct(tableName, columnInfos, theGroups);
} // }
public int getSerializedSize() // public int getSerializedSize()
{ // {
throw new NotImplementedException("Feature for provided constant values to" + // throw new NotImplementedException("Feature for provided constant values to" +
"non-primitive types in schema, not provided as of now"); // "non-primitive types in schema, not provided as of now");
} // }
#endregion // #endregion
} // }
} // }
@@ -3,8 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
namespace BCG namespace BCG {
{
/* /*
These fields are first going to be used by BlueRay to help it determine what differnet tags mean, but eventually These fields are first going to be used by BlueRay to help it determine what differnet tags mean, but eventually
* the goal is that they will be used for all services in this system. * the goal is that they will be used for all services in this system.
@@ -12,11 +11,12 @@ namespace BCG
* not all metadata fields are present in all metadata; it depends upon the class. For example, a bluepages service * not all metadata fields are present in all metadata; it depends upon the class. For example, a bluepages service
* probably won't have a 'symbol' or 'exchange' field populated, but it'll probably have the 'type' of service populated * probably won't have a 'symbol' or 'exchange' field populated, but it'll probably have the 'type' of service populated
*/ */
public enum MetaDataField { Protocol, //is this a bluepages service, a pubsub tag, a blueray tag, a 29 west thing, or what public enum MetaDataField {
Type, //if it's a multicast, is it option, fireprice, whatever. If it's bluepages, is it persistence, pubsub, whatever Protocol, // is this a bluepages service, a pubsub tag, a blueray tag, a 29 west thing, or what
Symbol, Type, // if it's a multicast, is it option, fireprice, whatever. If it's bluepages, is it persistence, pubsub, whatever
Exchange, Symbol,
Platform, Exchange,
MarketDataType, // BAM (bid, ask, mid), last, etc MarketDataType, // BAM (bid, ask, mid), last, etc
RealName }; //does this thing have a better name we could call it RealName
}; //does this thing have a better name we could call it
} }
@@ -5,8 +5,7 @@ using System.IO;
using BCG.Utilities.General; using BCG.Utilities.General;
//using BCG.Utilities; //using BCG.Utilities;
namespace BCG namespace BCG {
{
/// <summary> /// <summary>
/// The SerializedBlueTableSchema is an immutable schema holder. Once created it cannot be modified. It can be created /// The SerializedBlueTableSchema is an immutable schema holder. Once created it cannot be modified. It can be created
/// either from a DataTable or from an Array of ColumnInfo. The methods through which the user can access it /// either from a DataTable or from an Array of ColumnInfo. The methods through which the user can access it
@@ -17,12 +16,9 @@ namespace BCG
/// memory streams, and uses this schema to unpack the values when they are needed. /// memory streams, and uses this schema to unpack the values when they are needed.
/// </summary> /// </summary>
[Serializable] [Serializable]
public class SerializedBlueTableSchema : IBlueTableSchema public class SerializedBlueTableSchema : IBlueTableSchema {
{ public class SerializedBlueTableSchemaSerializationHelper {
public class SerializedBlueTableSchemaSerializationHelper public static object parse(Type t, string data) {
{
public static object parse(Type t, string data)
{
if (t == BlueDataValidTypes.BOOL) if (t == BlueDataValidTypes.BOOL)
return Boolean.Parse(data); return Boolean.Parse(data);
else if (t == BlueDataValidTypes.BYTE) else if (t == BlueDataValidTypes.BYTE)
@@ -52,8 +48,7 @@ namespace BCG
else else
throw new ApplicationException("Can not be parsed"); throw new ApplicationException("Can not be parsed");
} }
public static void serialize(BinaryWriter bw, Type t, object o) public static void serialize(BinaryWriter bw, Type t, object o) {
{
if (t == BlueDataValidTypes.BOOL) if (t == BlueDataValidTypes.BOOL)
bw.Write((bool)o); bw.Write((bool)o);
else if (t == BlueDataValidTypes.BYTE) else if (t == BlueDataValidTypes.BYTE)
@@ -76,13 +71,11 @@ namespace BCG
bw.Write(o as string); bw.Write(o as string);
else if (t == BlueDataValidTypes.SINGLE) else if (t == BlueDataValidTypes.SINGLE)
bw.Write((Single)o); bw.Write((Single)o);
else if (t == BlueDataValidTypes.BYTEARRAY) else if (t == BlueDataValidTypes.BYTEARRAY) {
{
byte[] bs = o as byte[]; byte[] bs = o as byte[];
bw.Write(bs.Length); bw.Write(bs.Length);
bw.Write(bs); bw.Write(bs);
} } else if (t == BlueDataValidTypes.UINT)
else if (t == BlueDataValidTypes.UINT)
bw.Write((uint)o); bw.Write((uint)o);
else if (t == BlueDataValidTypes.ULONG) else if (t == BlueDataValidTypes.ULONG)
bw.Write((ulong)o); bw.Write((ulong)o);
@@ -90,8 +83,7 @@ namespace BCG
throw new ApplicationException("Unsupported type"); throw new ApplicationException("Unsupported type");
} }
public static object deserialize(BinaryReader br, Type t) public static object deserialize(BinaryReader br, Type t) {
{
if (t == BlueDataValidTypes.BOOL) if (t == BlueDataValidTypes.BOOL)
return br.ReadBoolean(); return br.ReadBoolean();
else if (t == BlueDataValidTypes.BYTE) else if (t == BlueDataValidTypes.BYTE)
@@ -132,45 +124,37 @@ namespace BCG
public SerializedBlueTableSchema() { } public SerializedBlueTableSchema() { }
//copies the schema from an existing schema, building the dispatch table //copies the schema from an existing schema, building the dispatch table
public SerializedBlueTableSchema(IBlueTableSchema toCopy) public SerializedBlueTableSchema(IBlueTableSchema toCopy) {
{
int numCols = toCopy.columnInfo.Length; int numCols = toCopy.columnInfo.Length;
ColumnInfo[] theColumns = new ColumnInfo[toCopy.columnInfo.Length]; ColumnInfo[] theColumns = new ColumnInfo[toCopy.columnInfo.Length];
foreach (ColumnInfo toCopyCI in toCopy.columnInfo) foreach (ColumnInfo toCopyCI in toCopy.columnInfo) {
{
theColumns[toCopyCI.colNo] = toCopyCI; theColumns[toCopyCI.colNo] = toCopyCI;
} }
myConstruct(theColumns, toCopy.tableName); myConstruct(theColumns, toCopy.tableName);
} }
public SerializedBlueTableSchema(DataTable table) public SerializedBlueTableSchema(DataTable table) {
{
ColumnInfo[] theseCols = new ColumnInfo[table.Columns.Count]; ColumnInfo[] theseCols = new ColumnInfo[table.Columns.Count];
myTableName = table.TableName; myTableName = table.TableName;
foreach (DataColumn col in table.Columns) foreach (DataColumn col in table.Columns) {
{
theseCols[col.Ordinal] = new ColumnInfo(col.ColumnName, col.Ordinal, col.DataType); theseCols[col.Ordinal] = new ColumnInfo(col.ColumnName, col.Ordinal, col.DataType);
} }
myConstruct(theseCols, myTableName); myConstruct(theseCols, myTableName);
} }
public SerializedBlueTableSchema(ColumnInfo[] cis, string tableName) public SerializedBlueTableSchema(ColumnInfo[] cis, string tableName) {
{
myConstruct(cis, tableName); myConstruct(cis, tableName);
} }
public void serializeObject(object data, BinaryWriter bw, int colNo) public void serializeObject(object data, BinaryWriter bw, int colNo) {
{
mySerializeDispatchTable[colNo](data, bw); mySerializeDispatchTable[colNo](data, bw);
} }
private void myConstruct(ColumnInfo[] cis, string tableName) private void myConstruct(ColumnInfo[] cis, string tableName) {
{
myIndexByColOrder = new ColumnInfo[cis.Length]; myIndexByColOrder = new ColumnInfo[cis.Length];
myTableName = tableName; myTableName = tableName;
foreach (ColumnInfo ci in cis) foreach (ColumnInfo ci in cis) {
{
myIndexByColOrder[ci.colNo] = ci; myIndexByColOrder[ci.colNo] = ci;
myIndexByColName[ci.colName] = ci; myIndexByColName[ci.colName] = ci;
} }
@@ -179,32 +163,25 @@ namespace BCG
public SerializedBlueTableSchema(string tableName, params ColumnInfo[] cis) : this(cis, tableName) { } public SerializedBlueTableSchema(string tableName, params ColumnInfo[] cis) : this(cis, tableName) { }
public ColumnInfo this[string colName] public ColumnInfo this[string colName] {
{ get {
get
{
object retVal = myIndexByColName[colName]; object retVal = myIndexByColName[colName];
return retVal != null ? retVal as ColumnInfo : null; return retVal != null ? retVal as ColumnInfo : null;
} }
} }
public ColumnInfo this[int colNo] public ColumnInfo this[int colNo] {
{
get { return myIndexByColOrder[colNo]; } get { return myIndexByColOrder[colNo]; }
} }
/// <summary> /// <summary>
/// The returned Array is sorted according to the Column No /// The returned Array is sorted according to the Column No
/// </summary> /// </summary>
public string[] columnNames public string[] columnNames {
{ get {
get if (myTableColNames == null) {
{
if (myTableColNames == null)
{
myTableColNames = new string[myIndexByColName.Count]; myTableColNames = new string[myIndexByColName.Count];
foreach (DictionaryEntry de in myIndexByColName) foreach (DictionaryEntry de in myIndexByColName) {
{
ColumnInfo temp = (ColumnInfo)de.Value; ColumnInfo temp = (ColumnInfo)de.Value;
myTableColNames[temp.colNo] = temp.colName; myTableColNames[temp.colNo] = temp.colName;
} }
@@ -216,64 +193,46 @@ namespace BCG
/// <summary> /// <summary>
/// The returned Array is sorted according to the Column No /// The returned Array is sorted according to the Column No
/// </summary> /// </summary>
public ColumnInfo[] columnInfo public ColumnInfo[] columnInfo {
{
get { return myIndexByColOrder; } get { return myIndexByColOrder; }
} }
public string tableName { get { return myTableName; } } public string tableName { get { return myTableName; } }
public int IdColumn public int IdColumn {
{
get { return myIdCol; } get { return myIdCol; }
} }
#region ISerializedType methods #region ISerializedType methods
public void serialize(BinaryWriter bw) public void serialize(BinaryWriter bw) {
{
bw.Write(columnNames.Length); bw.Write(columnNames.Length);
bw.Write(tableName); bw.Write(tableName);
foreach (ColumnInfo ci in columnInfo) foreach (ColumnInfo ci in columnInfo) {
{
bw.Write(ci.colName); bw.Write(ci.colName);
bw.Write(ci.colType.ToString()); bw.Write(ci.colType.ToString());
if (ci.isConstant) bw.Write(false);
{
bw.Write(true);
SerializedBlueTableSchemaSerializationHelper.serialize(bw, ci.colType, ci.colValue);
}
else
{
bw.Write(false);
}
} }
} }
public void deserialze(BinaryReader br) public void deserialze(BinaryReader br) {
{
ColumnInfo[] cis = new ColumnInfo[br.ReadInt32()]; ColumnInfo[] cis = new ColumnInfo[br.ReadInt32()];
string name = br.ReadString(); string name = br.ReadString();
for (int i = 0; i < cis.Length; i++) for (int i = 0; i < cis.Length; i++) {
{
string colName = br.ReadString(); string colName = br.ReadString();
Type t = TypeInstanceLoader.loadType(br.ReadString(), true); Type t = TypeInstanceLoader.loadType(br.ReadString(), true);
bool isConstant = br.ReadBoolean(); bool isConstant = br.ReadBoolean();
if (isConstant) if (isConstant) {
{ cis[i] = new ColumnInfo(colName, i, t);
cis[i] = new ColumnInfo(colName, i, t, SerializedBlueTableSchemaSerializationHelper.deserialize(br, t)); } else {
}
else
{
cis[i] = new ColumnInfo(colName, i, t); cis[i] = new ColumnInfo(colName, i, t);
} }
} }
myConstruct(cis, name); myConstruct(cis, name);
} }
public int getSerializedSize() public int getSerializedSize() {
{
throw new NotImplementedException("Feature for provided constant values to" + throw new NotImplementedException("Feature for provided constant values to" +
"non-primitive types in schema, not provided as of now"); "non-primitive types in schema, not provided as of now");
} }
@@ -282,8 +241,7 @@ namespace BCG
//builds a dispatch table used to pull values out of the memory streams in the rows. //builds a dispatch table used to pull values out of the memory streams in the rows.
private void myBuildDispatchTable() private void myBuildDispatchTable() {
{
int numCols = myIndexByColOrder.Length; int numCols = myIndexByColOrder.Length;
mySerializeDispatchTable = new SerializeDelegate[numCols]; mySerializeDispatchTable = new SerializeDelegate[numCols];
myPullFromByteBufferDispatchTable = new PullFromByteBufferDelegate[numCols]; myPullFromByteBufferDispatchTable = new PullFromByteBufferDelegate[numCols];
@@ -292,18 +250,14 @@ namespace BCG
myIdCol = idColumn.colNo; myIdCol = idColumn.colNo;
for (int col = 0; col < numCols; ++col) for (int col = 0; col < numCols; ++col) {
{
Type thisColType = myIndexByColOrder[col].colType; Type thisColType = myIndexByColOrder[col].colType;
//we don't store serializers for the id column, or string columns. //we don't store serializers for the id column, or string columns.
if (col == myIdCol || thisColType == typeof(string)) if (col == myIdCol || thisColType == typeof(string)) {
{
mySerializeDispatchTable[col] = null; mySerializeDispatchTable[col] = null;
myColumnSizesTable[col] = 0; myColumnSizesTable[col] = 0;
myPullFromByteBufferDispatchTable[col] = null; myPullFromByteBufferDispatchTable[col] = null;
} } else {
else
{
mySerializeDispatchTable[col] = myGetDispatchMethodSerialize(thisColType); mySerializeDispatchTable[col] = myGetDispatchMethodSerialize(thisColType);
myPullFromByteBufferDispatchTable[col] = myGetDispatchMethodPullFromBuffer(thisColType); myPullFromByteBufferDispatchTable[col] = myGetDispatchMethodPullFromBuffer(thisColType);
myColumnSizesTable[col] = BlueDataValidTypes.getValueTypeSize(thisColType); myColumnSizesTable[col] = BlueDataValidTypes.getValueTypeSize(thisColType);
@@ -315,16 +269,14 @@ namespace BCG
} }
public int getNullMapSize() public int getNullMapSize() {
{
int numCols = myIndexByColOrder.Length; int numCols = myIndexByColOrder.Length;
return Convert.ToInt32(Math.Ceiling((Convert.ToDouble(numCols) / 8.0))); return Convert.ToInt32(Math.Ceiling((Convert.ToDouble(numCols) / 8.0)));
} }
//this function reads the null array from inside the byte array. //this function reads the null array from inside the byte array.
//it has to copy the bytes over. //it has to copy the bytes over.
public BitArray getNullMap(byte[] theBytes) public BitArray getNullMap(byte[] theBytes) {
{
int nullMapSize = getNullMapSize(); int nullMapSize = getNullMapSize();
//the null map starts after the id, so that we have instant access to the id. //the null map starts after the id, so that we have instant access to the id.
int byteCursor = BlueDataValidTypes.getValueTypeSize(typeof(Int32)); int byteCursor = BlueDataValidTypes.getValueTypeSize(typeof(Int32));
@@ -336,8 +288,7 @@ namespace BCG
} }
//gets the value either from the bytes stream but only if the value is not a string. //gets the value either from the bytes stream but only if the value is not a string.
//doesn't work if you're getting the id. //doesn't work if you're getting the id.
public unsafe object getValueNonString(byte[] theBytes, int colNo) public unsafe object getValueNonString(byte[] theBytes, int colNo) {
{
if (colNo == myIdCol) if (colNo == myIdCol)
throw new BlueDataException("Error: do not use getValueNonString to try to fetch the id of a row"); throw new BlueDataException("Error: do not use getValueNonString to try to fetch the id of a row");
BitArray nullMap = getNullMap(theBytes); BitArray nullMap = getNullMap(theBytes);
@@ -345,8 +296,7 @@ namespace BCG
return DBNull.Value; return DBNull.Value;
//the rest of the row starts after the id and the null map //the rest of the row starts after the id and the null map
int thisOffset = BlueDataValidTypes.getValueTypeSize(typeof(Int32)) + getNullMapSize(); int thisOffset = BlueDataValidTypes.getValueTypeSize(typeof(Int32)) + getNullMapSize();
for (int currentColumn = 0; currentColumn < colNo; ++currentColumn) for (int currentColumn = 0; currentColumn < colNo; ++currentColumn) {
{
//pull the data from the binary reader, but only if this type is not null or a string //pull the data from the binary reader, but only if this type is not null or a string
//if the type wer'e looking for is a string, it would have been returned already by the accesor //if the type wer'e looking for is a string, it would have been returned already by the accesor
//in the bluerow. //in the bluerow.
@@ -357,16 +307,14 @@ namespace BCG
thisOffset += myColumnSizesTable[currentColumn]; thisOffset += myColumnSizesTable[currentColumn];
} }
fixed (byte* thisBytePtr = &theBytes[thisOffset]) fixed (byte* thisBytePtr = &theBytes[thisOffset]) {
{
return myPullFromByteBufferDispatchTable[colNo](thisBytePtr); return myPullFromByteBufferDispatchTable[colNo](thisBytePtr);
} }
} }
public unsafe object[] getAllValues(byte[] theBytes, string[] stringArray) public unsafe object[] getAllValues(byte[] theBytes, string[] stringArray) {
{
int numCols = myColumnSizesTable.Length; int numCols = myColumnSizesTable.Length;
object[] theObjs = new Object[numCols]; object[] theObjs = new Object[numCols];
@@ -374,8 +322,7 @@ namespace BCG
int thisOffset = BlueDataValidTypes.getValueTypeSize(typeof(Int32)) + getNullMapSize(); int thisOffset = BlueDataValidTypes.getValueTypeSize(typeof(Int32)) + getNullMapSize();
int thisStringNo = 0; int thisStringNo = 0;
for (int currentColumn = 0; currentColumn < numCols; ++currentColumn) for (int currentColumn = 0; currentColumn < numCols; ++currentColumn) {
{
//pull the data from the binary reader, but only if this type is not null or a string //pull the data from the binary reader, but only if this type is not null or a string
//if the type wer'e looking for is a string, it would have been returned already by the accesor //if the type wer'e looking for is a string, it would have been returned already by the accesor
//in the bluerow. //in the bluerow.
@@ -384,10 +331,8 @@ namespace BCG
theObjs[currentColumn] = DBNull.Value; theObjs[currentColumn] = DBNull.Value;
else if (myIndexByColOrder[currentColumn].colType == typeof(string)) else if (myIndexByColOrder[currentColumn].colType == typeof(string))
theObjs[currentColumn] = stringArray[thisStringNo++]; theObjs[currentColumn] = stringArray[thisStringNo++];
else if (currentColumn != myIdCol) else if (currentColumn != myIdCol) {
{ fixed (byte* thisGuy = &theBytes[thisOffset]) {
fixed (byte* thisGuy = &theBytes[thisOffset])
{
theObjs[currentColumn] = myPullFromByteBufferDispatchTable[currentColumn](thisGuy); theObjs[currentColumn] = myPullFromByteBufferDispatchTable[currentColumn](thisGuy);
} }
thisOffset += myColumnSizesTable[currentColumn]; thisOffset += myColumnSizesTable[currentColumn];
@@ -416,8 +361,7 @@ namespace BCG
private void mySerializeDateTime(object data, BinaryWriter bw) { bw.Write(((DateTime)data).ToOADate()); } private void mySerializeDateTime(object data, BinaryWriter bw) { bw.Write(((DateTime)data).ToOADate()); }
private void mySerializeSingle(object data, BinaryWriter bw) { bw.Write((Single)data); } private void mySerializeSingle(object data, BinaryWriter bw) { bw.Write((Single)data); }
private SerializeDelegate myGetDispatchMethodSerialize(Type t) private SerializeDelegate myGetDispatchMethodSerialize(Type t) {
{
if (t.Equals(BlueDataValidTypes.INT)) return new SerializeDelegate(mySerializeInt32); if (t.Equals(BlueDataValidTypes.INT)) return new SerializeDelegate(mySerializeInt32);
else if (t.Equals(BlueDataValidTypes.DOUBLE)) return new SerializeDelegate(mySerializeDouble); else if (t.Equals(BlueDataValidTypes.DOUBLE)) return new SerializeDelegate(mySerializeDouble);
else if (t.Equals(BlueDataValidTypes.CHAR)) return new SerializeDelegate(mySerializeChar); else if (t.Equals(BlueDataValidTypes.CHAR)) return new SerializeDelegate(mySerializeChar);
@@ -448,16 +392,14 @@ namespace BCG
private unsafe object myPullDecimal(byte* bytePtr) { return *((decimal*)bytePtr); } private unsafe object myPullDecimal(byte* bytePtr) { return *((decimal*)bytePtr); }
private unsafe object myPullUInt(byte* bytePtr) { return *((UInt32*)bytePtr); } private unsafe object myPullUInt(byte* bytePtr) { return *((UInt32*)bytePtr); }
private unsafe object myPullULong(byte* bytePtr) { return *((UInt64*)bytePtr); } private unsafe object myPullULong(byte* bytePtr) { return *((UInt64*)bytePtr); }
private unsafe object myPullDateTime(byte* bytePtr) private unsafe object myPullDateTime(byte* bytePtr) {
{
double thisDateTime = *((double*)bytePtr); double thisDateTime = *((double*)bytePtr);
return DateTime.FromOADate(thisDateTime); return DateTime.FromOADate(thisDateTime);
} }
private unsafe object myPullSingle(byte* bytePtr) { return *((Single*)bytePtr); ; } private unsafe object myPullSingle(byte* bytePtr) { return *((Single*)bytePtr); ; }
private unsafe PullFromByteBufferDelegate myGetDispatchMethodPullFromBuffer(Type t) private unsafe PullFromByteBufferDelegate myGetDispatchMethodPullFromBuffer(Type t) {
{
if (t.Equals(BlueDataValidTypes.INT)) return new PullFromByteBufferDelegate(myPullInt32); if (t.Equals(BlueDataValidTypes.INT)) return new PullFromByteBufferDelegate(myPullInt32);
else if (t.Equals(BlueDataValidTypes.DOUBLE)) return new PullFromByteBufferDelegate(myPullDouble); else if (t.Equals(BlueDataValidTypes.DOUBLE)) return new PullFromByteBufferDelegate(myPullDouble);
else if (t.Equals(BlueDataValidTypes.CHAR)) return new PullFromByteBufferDelegate(myPullChar); else if (t.Equals(BlueDataValidTypes.CHAR)) return new PullFromByteBufferDelegate(myPullChar);
@@ -1,51 +1,44 @@
using System; // using System;
using System.Collections; // using System.Collections;
using System.Data; // using System.Data;
using BCG.Utilities; // using BCG.Utilities;
/* this class reprsents a table stream for use with CppDataStreams. It does not hold on to the last value fired. // /* this class reprsents a table stream for use with CppDataStreams. It does not hold on to the last value fired.
* This way, the last value is purged from managed memory and only the slimmer, sexier Cpp implementation of the row remains. // * This way, the last value is purged from managed memory and only the slimmer, sexier Cpp implementation of the row remains.
* // *
*/ // */
namespace BCG // namespace BCG {
{ // public class LightTableStream : TableStream {
public class LightTableStream : TableStream // public LightTableStream(string tableName)
{ // :
public LightTableStream(string tableName) // base(tableName, null, null) {
: // }
base(tableName, null, null)
{
}
public LightTableStream(string tableName, ViewStreamDatabase db) // public LightTableStream(string tableName, ViewStreamDatabase db)
: // :
base(tableName, db, null) // base(tableName, db, null) { }
{}
public LightTableStream(string tableName, string colExp) // public LightTableStream(string tableName, string colExp)
: // :
base(tableName, // base(tableName,
null, // null,
colExp) // colExp) { }
{}
public LightTableStream(string ttableName, ViewStreamDatabase db, string colExp) :
base(ttableName,db,colExp)
{
}
protected override void myHandleUpdates(IBlueRowCollection newRows, IBlueRowCollection addedRows, IBlueRowCollection deletedRows) // public LightTableStream(string ttableName, ViewStreamDatabase db, string colExp) :
{ // base(ttableName, db, colExp) {
// }
base.myHandleUpdates(newRows, addedRows, deletedRows);
//once you've fired the rows, delete them becuase we don't want to hold onto them in memory
myLastValue = null;
}
} // protected override void _handle_updates(IBlueRowCollection newRows, IBlueRowCollection addedRows, IBlueRowCollection deletedRows) {
}
// base._handle_updates(newRows, addedRows, deletedRows);
// //once you've fired the rows, delete them becuase we don't want to hold onto them in memory
// myLastValue = null;
// }
// }
// }
@@ -1,351 +0,0 @@
using System;
using System.IO;
//using BCG.Utilities;
using mbts;
using mbts.spark;
namespace BCG
{
public class TableAccumulator : ITableAccumulator
{
private HighPerformanceTimer _timer = new HighPerformanceTimer();
private IClientDeserializer myDeserializer = new ClientDeserializationController ();
private BlueTable myStateTable;
private ISubscriberCore mySubscriptionCore;
private TableUpdateDelegate myOnUpdateDelegate;
private string myTag;
private bool myUseIncrementsForMultipleOps = DataStreamGatewaySettings.instance.useIncrementsForMultipleOps;
public TableAccumulator (string tag, ISubscriberCore subCore)
{
myTag = tag;
mySubscriptionCore = subCore;
}
#region ITableAccumulator Members
public bool isActive()
{return myOnUpdateDelegate != null;}
public event TableUpdateDelegate onUpdate
{
add
{
// BlueEventLog.logEvent ("TableSubscriber being Subscribed for tag :" + myTag, BlueEventLevel.Information);
if (myOnUpdateDelegate == null)
{
//ie first subscription
// BlueEventLog.logEvent ("Subscription made to PubSub for tag : " + myTag, BlueEventLevel.Information);
mySubscriptionCore.subscribe (myTag);
}
myOnUpdateDelegate =
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);
if (myOnUpdateDelegate != null)
{
myOnUpdateDelegate =
Delegate.Remove (myOnUpdateDelegate, value) as TableUpdateDelegate;
if (myOnUpdateDelegate == null)
{
//all subscribers gone
// BlueEventLog.logEvent ("Unubscription made to PubSub for tag : " + myTag, BlueEventLevel.Information);
mySubscriptionCore.unsubscribe (myTag);
myStateTable = null;
}
}
}
}
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)
{
byte[] ops;
Array rows;
_timer.start();
myDeserializer.deserialize (streams, out ops, out rows);
_timer.stop();
// BlueEventLog.logEvent(String.Format("deserializing {0} took {1} msecs", myTag, _timer.lastIntervalTime), BlueEventLevel.Performance);
_timer.start();
myAccumulateAndFire (ops, rows);
_timer.stop();
// BlueEventLog.logEvent(String.Format("myAccumulateAndFire for {0} took {1} msecs", myTag, _timer.lastIntervalTime), BlueEventLevel.Performance);
}
}
#endregion
private void myAccumulateAndFire (byte[] ops, Array rows)
{
//if a non create comes before the create, the deserializer returns 0 sized arrays
if (ops.Length == 0 || rows.Length == 0)
{
//ie if one is zero sized so should be the other one
// BlueEventLog.logAssert (ops.Length + rows.Length == 0);
}
else
{
if (ops.Length > 1)
{
int index = 0;
if (myStateTable == null)
{
for(index=0; index<ops.Length; index++)
if (ops[index] == StreamOpCode.create)
break;
if (index == ops.Length)
return;
}
if (myUseIncrementsForMultipleOps)
myHandleMultipleOpsIncrementally(ops, rows, index);
else
myHandleMultipleOps(ops, rows, index);
}
else
{
if (myStateTable != null || ops[0] == StreamOpCode.create)
myHandleSingleOp (ops, rows);
}
}
}
private void myHandleMultipleOps (byte[] ops, Array rows, int offset)
{
HighPerformanceTimer timer = new HighPerformanceTimer();
timer.start();
IBlueRowCollection stateAtStart = myStateTable == null ? null : new BlueTable (myStateTable);
for (int i = offset; i < ops.Length; i++)
{
byte op = ops[i];
IBlueRowCollection[] tableArray = rows.GetValue (i) as IBlueRowCollection[];
if (op == StreamOpCode.add)
myStateTable.addRows (tableArray[0]);
else if (op == StreamOpCode.remove)
myStateTable.deleteRows (tableArray[0]);
else if (op == StreamOpCode.change)
myStateTable.changeRows (tableArray[0]);
else if (op == StreamOpCode.create)
myStateTable = new BlueTable (tableArray[0]);
else if (op == StreamOpCode.multipleChange)
myStateTable.changeRows (tableArray[0]);
else if (op == StreamOpCode.multipleRemoveAdd)
{
myStateTable.deleteRows (tableArray[0]);
myStateTable.addRows (tableArray[1]);
}
}
IBlueRowCollection dRows, aRows;
if (stateAtStart == null)
{
dRows = new BlueTable (myStateTable.schema);
aRows = myStateTable;
}
else
{
BlueDataUtility.computeDifferences (myStateTable, stateAtStart, out dRows, out aRows);
}
timer.stop();
//Console.WriteLine("multiple ops for table " + myTag + " took " + timer.lastIntervalTime + " msecs");
myOnUpdateDelegate (myStateTable, aRows, dRows);
}
#region handling mutliple ops in single update call, incrementally
private void myHandleMultipleOpsIncrementally(byte[] ops, Array rows, int offset)
{
BlueTable dels = null, adds = null;
if (myStateTable != null)
{
dels = new BlueTable(myStateTable.schema);
adds = new BlueTable(myStateTable.schema);
}
for (int i = offset; i < ops.Length; i++)
{
byte op = ops[i];
IBlueRowCollection[] tableArray = rows.GetValue(i) as IBlueRowCollection[];
if (op == StreamOpCode.add)
{
myHandleAdd(BlueDataUtility.extractRow(tableArray[0], 0), dels, adds);
}
else if (op == StreamOpCode.remove)
{
myHandleRemove(BlueDataUtility.extractRow(tableArray[0], 0), dels, adds);
}
else if (op == StreamOpCode.change)
{
myHandleChange(BlueDataUtility.extractRow(tableArray[0], 0), dels, adds);
}
else if (op == StreamOpCode.create)
{
myHandleCreate(tableArray[0], ref dels, ref adds);
}
else if (op == StreamOpCode.multipleChange)
{
myHandleMultipleChanges(tableArray[0], dels, adds);
}
else if (op == StreamOpCode.multipleRemoveAdd)
{
myHandleMultipleRemovesAdds(tableArray[0], tableArray[1], dels, adds);
}
}
myOnUpdateDelegate(myStateTable, adds, dels);
}
private void myHandleAdd(IBlueRow r, BlueTable dels, BlueTable adds)
{
if (dels != null)
{
myStateTable.addRow(r);
adds.addRow(r);
}
}
private void myHandleRemove(IBlueRow r, BlueTable dels, BlueTable adds)
{
if (dels != null)
{
myStateTable.deleteRow(r);
if (adds.containsID((int)r["id"]))
adds.deleteRow(r);
else
dels.addRow(r);
}
}
private void myHandleChange(IBlueRow r, BlueTable dels, BlueTable adds)
{
if (dels != null)
{
IBlueRow er = myStateTable[(int)r["id"]];
myHandleRemove(er, dels, adds);
myHandleAdd(r, dels, adds);
}
}
private void myHandleCreate(IBlueRowCollection newTable, ref BlueTable dels, ref BlueTable adds)
{
if (dels == null)
{
// BlueEventLog.logAssert(adds == null);
dels = new BlueTable(newTable.schema);
adds = new BlueTable(newTable);
myStateTable = new BlueTable(newTable);
}
else
{
dels = new BlueTable(myStateTable);
myStateTable = new BlueTable(newTable);
adds = new BlueTable(newTable);
}
}
private void myHandleMultipleRemovesAdds(IBlueRowCollection deletedRows, IBlueRowCollection addedRows,
BlueTable dels, BlueTable adds)
{
if (dels != null)
{
foreach (IBlueRow r in deletedRows)
myHandleRemove(r, dels, adds);
foreach (IBlueRow r in addedRows)
myHandleAdd(r, dels, adds);
}
}
private void myHandleMultipleChanges(IBlueRowCollection changedRows, BlueTable dels, BlueTable adds)
{
if (dels != null)
foreach (IBlueRow r in changedRows)
myHandleChange(r, dels, adds);
}
#endregion
private void myHandleSingleOp(byte[] ops, Array rows)
{
byte op = ops[0];
IBlueRowCollection[] tableArray = rows.GetValue (0) as IBlueRowCollection[];
IBlueRowCollection dRows, aRows;
if (op == StreamOpCode.create)
{
if (myStateTable == null)
{
aRows = myStateTable = new BlueTable(tableArray[0]);
dRows = new BlueTable(myStateTable.schema);
myOnUpdateDelegate(myStateTable, aRows, dRows);
}
else
{
IBlueRowCollection newState = new BlueTable(tableArray[0]);
BlueDataUtility.computeDifferences(newState, myStateTable, out dRows, out aRows);
if (aRows.Count > 0 || dRows.Count > 0)
{
myStateTable = new BlueTable(newState);
myOnUpdateDelegate(myStateTable, aRows, dRows);
}
}
}
else
{
if (op == StreamOpCode.add)
{
myStateTable.addRows(aRows = tableArray[0]);
dRows = new BlueTable(myStateTable.schema);
}
else if (op == StreamOpCode.remove)
{
myStateTable.deleteRows(dRows = tableArray[0]);
aRows = new BlueTable(myStateTable.schema);
}
else if (op == StreamOpCode.change)
{
IBlueRow cRow = BlueDataUtility.extractRow(tableArray[0], 0);
aRows = new BlueTable(myStateTable.schema);
dRows = new BlueTable(myStateTable.schema);
(aRows as BlueTable).addRow(cRow);
(dRows as BlueTable).addRow(myStateTable[(int)cRow["id"]]);
myStateTable.changeRow(cRow);
}
else if (op == StreamOpCode.multipleChange)
{
if (myStateTable.Count == tableArray[0].Count)
{
//all rows are changed, so we can optimize this
dRows = myStateTable;
aRows = myStateTable = new BlueTable(tableArray[0]);
}
else
{
dRows = new BlueTable(myStateTable.schema);
aRows = tableArray[0];
foreach (IBlueRow r in tableArray[0])
{
(dRows as BlueTable).addRow(myStateTable[(int)r["id"]]);
myStateTable.changeRow(r);
}
}
}
else if (op == StreamOpCode.multipleRemoveAdd)
{
BlueDataUtility.absorbChanges(myStateTable, dRows = tableArray[0], aRows = tableArray[1]);
}
else
{
aRows = dRows = null;
// BlueEventLog.logAssert(false, "unknown opcode");
}
myOnUpdateDelegate(myStateTable, aRows, dRows);
}
}
}
}
@@ -1,67 +0,0 @@
using System;
using System.IO;
using System.Collections;
using BCG.Utilities;
namespace BCG {
/// <summary>
/// Controls (ie creates dynamically) an IClientDeserializer and then passes data to it.
/// </summary>
public class ClientDeserializationController : IClientDeserializer {
private IClientDeserializer myDeserializer;
private int _n_desers = 0;
public ClientDeserializationController() { }
#region IClientDeserializer Members
/// <summary>
/// Deserializes bytes into operation and data. If it gets a non create before a create, both
/// the out arrays get initialized to empty arrays
/// </summary>
/// <param name="streams"></param>
/// <param name="theOps"></param>
/// <param name="theRows"></param>
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);
byte op;
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))
as IClientDeserializer;
totalStream.Position = initialPos;
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[] { };
}
}
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
}
#endregion
}
}
@@ -1,124 +0,0 @@
using System;
using System.Collections;
using System.IO;
using BCG.Utilities;
//using BCG.Utilities.BlueConfiguration;
namespace BCG
{
/// <summary>
/// Pairs up with the UniversalSerializer to deserialize the corresponding data. Everythign anologous
/// to UniversalSerializer.
/// </summary>
public abstract class ClientDeserializer : IClientDeserializer
{
protected IBlueTableSchema mySchema;
protected IBlueTableSchema myFirstSchema;
protected IClientRowDeserializer myRowDeserializer;
public ClientDeserializer()
{
myFirstSchema = null;
mySchema = null;
}
#region IClientDeserializer Members
void BCG.IClientDeserializer.deserialize(Stream[] streams, out byte[] theOps, out Array theRows)
{
BinaryReader br = new BinaryReader(UtilityMethods.getAggregatedStream(streams));
// BlueTrace.WriteDeserializeStart(streams.Length, br.BaseStream.Length);
// emit # of streams and total length
ArrayList ops = new ArrayList(), rows = new ArrayList();
IBlueRowCollection[] result;
while (true)
{
byte op;
try
{
int value = br.BaseStream.ReadByte();
if (value == -1) break;
op = (byte)value;
// BlueTrace.WriteDeserializeOperation(op);
}
catch (EndOfStreamException)
{
break;
}
if (op == StreamOpCode.create)
{
br.ReadString(); //pubsubDeserializer
br.ReadString(); //clientDeserializer
mySchema = new BlueTableSchema();
mySchema.deserialze(br);
//keep track of the first schema you've ever seen, so you know how to reorder columns
if (myFirstSchema == null)
myFirstSchema = mySchema;
result = new IBlueRowCollection[] { myGetRows(br, op, br.ReadInt32()) };
myEncorporateRows(result[0], op);
ops.Add(op);
rows.Add(result);
}
else
{
if (mySchema != null)
{
if (op == StreamOpCode.add || op == StreamOpCode.change || op == StreamOpCode.remove)
{
result = new IBlueRowCollection[] { myGetRows(br, op, 1) };
myEncorporateRows(result[0], op);
ops.Add(op);
rows.Add(result);
}
else if (op == StreamOpCode.multipleChange)
{
result = new IBlueRowCollection[] { myGetRows(br, op, br.ReadInt32()) };
myEncorporateRows(result[0], op);
ops.Add(op);
rows.Add(result);
}
else if (op == StreamOpCode.multipleRemoveAdd)
{
result =
new IBlueRowCollection[] {
myGetRows (br, StreamOpCode.remove, br.ReadInt32 ()),
myGetRows (br, StreamOpCode.add, br.ReadInt32 ())
};
myEncorporateRows(result[0], StreamOpCode.remove);
myEncorporateRows(result[1], StreamOpCode.add);
ops.Add(op);
rows.Add(result);
}
else
{
// BlueEventLog.logEvent("Illegal op-code received", BlueEventLevel.Error);
}
}
else
{
// BlueEventLog.logEvent("Received a non create operation even though the schema" +
// "has never been created", BlueEventLevel.Warning);
}
}
}
theOps = ops.ToArray(typeof(byte)) as byte[];
theRows = rows.ToArray();
// BlueTrace.WriteDeserializeStop(rows.Count);
}
#endregion
protected abstract IBlueRowCollection myGetRows(BinaryReader br, byte op, int nRows);
protected abstract void myEncorporateRows(IBlueRowCollection rows, byte op);
}
}
@@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace BCG
{
class ClientReorderingRowDeserializer : IClientRowDeserializer
{
private IBlueTableSchema myOriginalSchema;
private IBlueTableSchema myOutputSchema;
private ClientUniversalRowDeserializer myDeserializer;
public ClientReorderingRowDeserializer(IBlueTableSchema originalSchema, IBlueTableSchema newSchema)
{
myOriginalSchema = originalSchema;
myOutputSchema = newSchema;
myDeserializer = new ClientUniversalRowDeserializer(newSchema);
}
#region IClientRowDeserializer Members
public void deserializeRow(IBlueRowCollection currentState, BinaryReader br, byte op, out IBlueRow r)
{
IBlueRow temp = null;
myDeserializer.deserializeRow(currentState, br, op, out temp);
r = BlueDataUtility.changeSchema(temp, myOutputSchema);
}
#endregion
}
}
@@ -1,35 +0,0 @@
using System;
using System.Collections;
using System.IO;
namespace BCG
{
public class ClientUniversalDeserializer : ClientDeserializer
{
public ClientUniversalDeserializer () {}
protected override IBlueRowCollection myGetRows (BinaryReader br, byte op, int nRows)
{
BlueTable retVal = new BlueTable (mySchema);
if (myRowDeserializer == null)
myRowDeserializer = new ClientUniversalRowDeserializer(mySchema);
else if (op == StreamOpCode.create)
myRowDeserializer = new ClientReorderingRowDeserializer(myFirstSchema, mySchema);
for (int i = 0; i < nRows; i++)
{
IBlueRow row;
myRowDeserializer.deserializeRow (null, br, op, out row);
retVal.addRow (row);
}
return retVal;
}
protected override void myEncorporateRows (IBlueRowCollection rows, byte op)
{
//this does not keep state so ignore calls
}
}
}
@@ -1,69 +0,0 @@
using System;
using System.Collections;
using System.IO;
using BCG.Utilities;
//using BCG.Utilities.BlueConfiguration;
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 {
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();
}
#region Schema Reordering initialization
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);
}
}
#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++) {
int colNo = mySerIndexToSchemaIndexMap[i];
values[mySerIndexToSchemaIndexMap[i]] = myNullMap[colNo] ? DBNull.Value : myDeserializationHelper.deserializeColumn(colNo, br);
}
r = new BlueRow(mySchema, values);
}
#endregion
}
}
@@ -1,149 +0,0 @@
using System;
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;
}
}
/// <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 {
/// <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);
}
}
@@ -1,12 +0,0 @@
using System;
using System.IO;
using System.Collections;
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);
}
}
@@ -1,79 +0,0 @@
using System;
using System.IO;
namespace BCG
{
/// <summary>
/// Deserializes primitive types. Contructs a hash based scheme based on the index, to make everythign O(1)
/// rather than searching it up and making it O(n)
/// </summary>
public class PrimitiveDeserializationHelper
{
private delegate object DeserializeDelegate (int colNo, BinaryReader br);
private DeserializeDelegate[] myDispatchTable;
private ColumnInfo[] myCis;
public PrimitiveDeserializationHelper (IBlueTableSchema schema)
: this (schema.columnInfo)
{}
public PrimitiveDeserializationHelper (ColumnInfo[] cis)
{
myDispatchTable = new DeserializeDelegate [(myCis = cis).Length];
foreach (ColumnInfo ci in cis)
myDispatchTable[ci.colNo] = myGetDispatchMethod (ci.colType);
}
public object deserializeColumn (int colNo, BinaryReader br)
{
return myDispatchTable[colNo] (colNo, br);
}
private DeserializeDelegate myGetDispatchMethod (Type t)
{
if (t.Equals (BlueDataValidTypes.INT)) return new DeserializeDelegate (myDeserializeInt32);
else if (t.Equals (BlueDataValidTypes.DOUBLE)) return new DeserializeDelegate (myDeserializeDouble);
else if (t.Equals (BlueDataValidTypes.STRING)) return new DeserializeDelegate (myDeserializeString);
else if (t.Equals (BlueDataValidTypes.BYTEARRAY)) return new DeserializeDelegate (myDeserializeByteArray);
else if (t.Equals (BlueDataValidTypes.CHAR)) return new DeserializeDelegate (myDeserializeChar);
else if (t.Equals (BlueDataValidTypes.LONG)) return new DeserializeDelegate (myDeserializeLong);
else if (t.Equals (BlueDataValidTypes.SBYTE)) return new DeserializeDelegate (myDeserializeSByte);
else if (t.Equals (BlueDataValidTypes.BOOL)) return new DeserializeDelegate (myDeserializeBool);
else if (t.Equals (BlueDataValidTypes.BYTE)) return new DeserializeDelegate (myDeserializeByte);
else if (t.Equals (BlueDataValidTypes.DECIMAL)) return new DeserializeDelegate (myDeserializeDecimal);
else if (t.Equals (BlueDataValidTypes.UINT)) return new DeserializeDelegate (myDeserializeUInt);
else if (t.Equals (BlueDataValidTypes.ULONG)) return new DeserializeDelegate (myDeserializeULong);
else if (t.Equals (BlueDataValidTypes.DATETIME)) return new DeserializeDelegate (myDeserializeDateTime);
else if (t.Equals (BlueDataValidTypes.SINGLE)) return new DeserializeDelegate (myDeserializeSingle);
else if (SerializationUtilityMethods.isSerializedType (t)) return new DeserializeDelegate (myDeserializeISerializedType);
else throw new ApplicationException (t.FullName + " is not a supported type");
}
private object myDeserializeInt32 (int colNo, BinaryReader br) {return br.ReadInt32 ();}
private object myDeserializeISerializedType (int colNo, BinaryReader br)
{
ISerializedType o = Activator.CreateInstance (myCis[colNo].colType)
as ISerializedType;
o.deserialze (br);
return o;
}
private object myDeserializeDouble (int colNo, BinaryReader br) {return br.ReadDouble ();}
private object myDeserializeString (int colNo, BinaryReader br) {return br.ReadString ();}
private object myDeserializeByteArray (int colNo, BinaryReader br) {return br.ReadBytes (br.ReadInt32 ());}
private object myDeserializeChar (int colNo, BinaryReader br) {return br.ReadChar ();}
private object myDeserializeLong (int colNo, BinaryReader br) {return br.ReadInt64 ();}
private object myDeserializeSByte (int colNo, BinaryReader br) {return br.ReadSByte ();}
private object myDeserializeBool (int colNo, BinaryReader br) {return br.ReadBoolean ();}
private object myDeserializeByte (int colNo, BinaryReader br) {return br.ReadByte ();}
private object myDeserializeDecimal (int colNo, BinaryReader br) {return br.ReadDecimal ();}
private object myDeserializeUInt (int colNo, BinaryReader br) {return br.ReadUInt32 ();}
private object myDeserializeDateTime (int colNo, BinaryReader br)
{
return new DateTime(br.ReadInt64());
//return DateTime.FromOADate (br.ReadDouble ());
//return new DateTime(br.ReadInt64());
}
private object myDeserializeULong (int colNo, BinaryReader br) {return br.ReadUInt64 ();}
private object myDeserializeSingle (int colNo, BinaryReader br) {return br.ReadSingle ();}
}
}
@@ -1,155 +0,0 @@
using System;
using System.Collections;
using System.Reflection;
//using BCG.Utilities.BlueConfiguration;
using BCG.Utilities;
namespace BCG
{
public class CorePrimtiveManager
{
private IDictionary myTypeLookupTable = new Hashtable ();
private static CorePrimtiveManager mySelf;
private ArrayList myAssemblyNames = new ArrayList ();
private CorePrimtiveManager()
{
myLoadAllTypes ();
}
private void myLoadAllTypes ()
{
//we only load one type here
loadAssembly ("X:\\bcg\\blue2\\Debug\\CppToCSharpDataStreamBridge.dll");
}
private static Assembly myAssemblyResolver(object sender, ResolveEventArgs args)
{
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
if (args.Name.Equals(a.FullName))
return a;
return null;
}
/// <summary>
/// Loads all the types associated with the assembly
/// </summary>
/// <param name="assemblyName"></param>
public void loadAssembly (string assemblyName)
{
if (myAssemblyNames.Contains (assemblyName))
return;
myAssemblyNames.Add (assemblyName);
Assembly loadedAssembly = GetType ().Assembly.FullName.Equals (assemblyName) ?
GetType ().Assembly :
Assembly.LoadFrom (assemblyName);
foreach (Type type in loadedAssembly.GetTypes())
if (!type.IsInterface
&& !type.IsAbstract
&& type.IsPublic)
{
bool isVisible = true;
string userRep = type.Name;
if (isVisible)
{
// BlueEventLog.logAssert(myTypeLookupTable [userRep] == null);
myTypeLookupTable[userRep] = type;
}
}
}
public static CorePrimtiveManager instance
{
get {return mySelf = mySelf == null ? new CorePrimtiveManager () : mySelf;}
}
/// <summary>
/// Returns the Type name corresponding to the primitive name
/// </summary>
/// <param name="friendlyName"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Constructs and returns an object of type corresponding to the friendly name
/// </summary>
/// <param name="friendlyName">friendly primitive name </param>
/// <param name="args">args can be null or an empty ICollection if the paramterless constructor
/// is the desired one</param>
/// <returns></returns>
public Object build (string friendlyName, ICollection args)
{
object[] constructorArgs = null;
if (args != null && args.Count > 0)
{
constructorArgs = new object [args.Count];
args.CopyTo (constructorArgs, 0);
}
if (myTypeLookupTable[friendlyName] == null)
throw new ApplicationException (friendlyName + " is not the friendly name of any of the loaded types");
return
constructorArgs == null ?
Activator.CreateInstance (myTypeLookupTable[friendlyName] as Type):
Activator.CreateInstance (myTypeLookupTable[friendlyName] as Type, constructorArgs);
}
/// <summary>
/// Returns the name of all the primitives
/// </summary>
/// <returns></returns>
public string[] getPrimitiveNames ()
{
string[] retVal = new string [myTypeLookupTable.Count];
myTypeLookupTable.Keys.CopyTo (retVal, 0);
return retVal;
}
/// <summary>
/// Return the types of all the streams
/// </summary>
/// <returns></returns>
public Type[] getStreamTypes ()
{
Type[] retVal = new Type [myTypeLookupTable.Count];
myTypeLookupTable.Values.CopyTo (retVal, 0);
return retVal;
}
public ICollection getConstructorSigns (string primitiveName)
{
ArrayList retVal = new ArrayList ();
// BlueEventLog.logAssert (myTypeLookupTable[primitiveName] != null);
Type t = myTypeLookupTable[primitiveName] as Type;
foreach (ConstructorInfo ci in t.GetConstructors())
{
string sign = "";
sign = t.Name + " (";
foreach (ParameterInfo pi in ci.GetParameters ())
sign += pi.ParameterType.Name +
" " +
pi.Name + ", ";
sign = sign.Length == (t.Name + " (").Length ? sign + ")": sign.Remove (sign.Length - 2, 2) + ")";
retVal.Add (sign);
}
return retVal;
}
public string getAssemblyName (string primitiveName)
{
// BlueEventLog.logAssert (myTypeLookupTable[primitiveName] != null);
return (myTypeLookupTable[primitiveName] as Type).Assembly.GetName().Name;
}
}
}
@@ -1,20 +0,0 @@
using System;
namespace BCG
{
public class PubStreamPrefixer
{
private static readonly string myPrefixString = "DS";
public static string prefix (string tableName)
{
return myPrefixString + "_" + tableName.ToLower();
}
public static string extractTableNameFromTag (string tag)
{
return tag.Substring ((myPrefixString + "_").Length);
}
}
}
@@ -1,339 +0,0 @@
using System;
using System.IO;
using System.Collections;
namespace BCG
{
public class SerializationUtilityMethods
{
private static IDictionary mySerializationDispatchTable,
myDeserializationDispatchTable;
private delegate void MySerialize (object data, BinaryWriter bw);
private delegate object MyDeserialize (Type t, BinaryReader br);
static SerializationUtilityMethods ()
{
mySerializationDispatchTable = new Hashtable ();
mySerializationDispatchTable [BlueDataValidTypes.BOOL.Name] =
new MySerialize (mySerializeBool);
mySerializationDispatchTable [BlueDataValidTypes.BYTE.Name] =
new MySerialize (mySerializeByte);
mySerializationDispatchTable [BlueDataValidTypes.CHAR.Name] =
new MySerialize (mySerializeChar);
mySerializationDispatchTable [BlueDataValidTypes.DATETIME.Name] =
new MySerialize (mySerializeDateTime);
mySerializationDispatchTable [BlueDataValidTypes.DECIMAL.Name] =
new MySerialize (mySerializeDecimal);
mySerializationDispatchTable [BlueDataValidTypes.DOUBLE.Name] =
new MySerialize (mySerializeDouble);
mySerializationDispatchTable [BlueDataValidTypes.INT.Name] =
new MySerialize (mySerializeInt32);
mySerializationDispatchTable [BlueDataValidTypes.ISERIALIZEDTYPE.Name] =
new MySerialize (mySerializeISerializedType);
mySerializationDispatchTable [BlueDataValidTypes.LONG.Name] =
new MySerialize (mySerializeLong);
mySerializationDispatchTable [BlueDataValidTypes.SBYTE.Name] =
new MySerialize (mySerializeSByte);
mySerializationDispatchTable [BlueDataValidTypes.STRING.Name] =
new MySerialize (mySerializeString);
mySerializationDispatchTable [BlueDataValidTypes.BYTEARRAY.Name] =
new MySerialize (mySerializeByteArray);
mySerializationDispatchTable [BlueDataValidTypes.UINT.Name] =
new MySerialize (mySerializeUInt);
mySerializationDispatchTable [BlueDataValidTypes.ULONG.Name] =
new MySerialize (mySerializeULong);
mySerializationDispatchTable [BlueDataValidTypes.SINGLE.Name] =
new MySerialize (mySerializeSingle);
myDeserializationDispatchTable = new Hashtable ();
myDeserializationDispatchTable [BlueDataValidTypes.BOOL.Name] =
new MyDeserialize (myDeserializeBool);
myDeserializationDispatchTable [BlueDataValidTypes.BYTE.Name] =
new MyDeserialize (myDeserializeByte);
myDeserializationDispatchTable [BlueDataValidTypes.CHAR.Name] =
new MyDeserialize (myDeserializeChar);
myDeserializationDispatchTable [BlueDataValidTypes.DATETIME.Name] =
new MyDeserialize (myDeserializeDateTime);
myDeserializationDispatchTable [BlueDataValidTypes.DECIMAL.Name] =
new MyDeserialize (myDeserializeDecimal);
myDeserializationDispatchTable [BlueDataValidTypes.DOUBLE.Name] =
new MyDeserialize (myDeserializeDouble);
myDeserializationDispatchTable [BlueDataValidTypes.INT.Name] =
new MyDeserialize (myDeserializeInt32);
myDeserializationDispatchTable [BlueDataValidTypes.ISERIALIZEDTYPE.Name] =
new MyDeserialize (myDeserializeISerializedType);
myDeserializationDispatchTable [BlueDataValidTypes.LONG.Name] =
new MyDeserialize (myDeserializeLong);
myDeserializationDispatchTable [BlueDataValidTypes.SBYTE.Name] =
new MyDeserialize (myDeserializeSByte);
myDeserializationDispatchTable [BlueDataValidTypes.STRING.Name] =
new MyDeserialize (myDeserializeString);
myDeserializationDispatchTable [BlueDataValidTypes.BYTEARRAY.Name] =
new MyDeserialize (myDeserializeByteArray);
myDeserializationDispatchTable [BlueDataValidTypes.UINT.Name] =
new MyDeserialize (myDeserializeUInt);
myDeserializationDispatchTable [BlueDataValidTypes.ULONG.Name] =
new MyDeserialize (myDeserializeULong);
myDeserializationDispatchTable [BlueDataValidTypes.SINGLE.Name] =
new MyDeserialize (myDeserializeSingle);
}
public static int getObjectSerializedSize (object o)
{
Type t = o.GetType ();
if (t == BlueDataValidTypes.STRING)
{
int l = (o as string).Length;
if (l < 128)
return l + 1;
if (l < 16384)
return l + 2;
if (l < 2097152)
return l + 3;
if (l < Math.Pow (2, 28))
return l + 4;
throw new ApplicationException ("String too big");
}
else if (t == BlueDataValidTypes.BYTEARRAY)
{
return getFixedLengthTypeSize (BlueDataValidTypes.INT) +
(o as byte[]).Length;
}
else if (isSerializedType (t))
{
return (o as ISerializedType).getSerializedSize ();
}
return getFixedLengthTypeSize (t);
}
public static int getFixedLengthTypeSize (Type t)
{
if (t == BlueDataValidTypes.BOOL ||
t == BlueDataValidTypes.BYTE ||
t == BlueDataValidTypes.CHAR ||
t == BlueDataValidTypes.SBYTE)
return 1;
else if (t == BlueDataValidTypes.INT ||
t == BlueDataValidTypes.UINT||
t == BlueDataValidTypes.SINGLE)
return 4;
else if (t == BlueDataValidTypes.DOUBLE ||
t == BlueDataValidTypes.LONG ||
t== BlueDataValidTypes.ULONG)
return 8;
else if (t == BlueDataValidTypes.DECIMAL)
return 16;
else if (t == BlueDataValidTypes.DATETIME)
//as objects of type DateTime are stored as doubles
return getFixedLengthTypeSize (typeof(long));
else
throw new ApplicationException (t.FullName + " is not a supported type");
}
public static bool isFixedLengthType (Type t)
{
return !(t.Equals (BlueDataValidTypes.STRING) || t.Equals (BlueDataValidTypes.BYTEARRAY) ||
isSerializedType (t));
}
public static bool isSerializedType (Type t)
{
return t.GetInterface ("BCG.ISerializedType") != null;
}
#region Serialization
public static void serializeValue (object data, BinaryWriter bw)
{
Type t = data.GetType ();
if (isSerializedType (t))
(mySerializationDispatchTable [typeof(ISerializedType).Name]
as MySerialize)(data, bw);
else
(mySerializationDispatchTable [t.Name] as MySerialize) (data, bw);
}
public static void serializeEnum(object data, BinaryWriter bw)
{
mySerializeInt32(data, bw);
}
private static void mySerializeInt32 (object data, BinaryWriter bw)
{
bw.Write ((Int32)data);
}
private static void mySerializeDouble (object data, BinaryWriter bw)
{
bw.Write ((double)data);
}
private static void mySerializeString (object data, BinaryWriter bw)
{
bw.Write (data as string);
}
private static void mySerializeByteArray (object data, BinaryWriter bw)
{
byte[] bs = data as byte[];
bw.Write (bs.Length);
bw.Write (bs);
}
private static void mySerializeSingle (object data, BinaryWriter bw)
{
bw.Write ((Single)data);
}
private static void mySerializeChar (object data, BinaryWriter bw)
{
bw.Write ((char)data);
}
private static void mySerializeLong (object data, BinaryWriter bw)
{
bw.Write ((long)data);
}
private static void mySerializeSByte (object data, BinaryWriter bw)
{
bw.Write ((sbyte)data);
}
private static void mySerializeBool (object data, BinaryWriter bw)
{
bw.Write ((bool)data);
}
private static void mySerializeByte (object data, BinaryWriter bw)
{
bw.Write ((byte)data);
}
private static void mySerializeDecimal (object data, BinaryWriter bw)
{
bw.Write ((decimal)data);
}
private static void mySerializeUInt (object data, BinaryWriter bw)
{
bw.Write ((uint)data);
}
private static void mySerializeULong (object data, BinaryWriter bw)
{
bw.Write ((ulong)data);
}
private static void mySerializeDateTime (object data, BinaryWriter bw)
{
//DateTime is written is serialiazed as OADATE
bw.Write (((DateTime)data).ToOADate());
}
private static void mySerializeISerializedType (object data, BinaryWriter bw)
{
(data as ISerializedType).serialize (bw);
}
#endregion
#region Deserialization
public static object deserializeValue(Type t, BinaryReader br)
{
return myDeserialize(t, br);
}
private static object myDeserialize (Type t, BinaryReader br)
{
return isSerializedType (t) ?
(myDeserializationDispatchTable [typeof(ISerializedType).Name]
as MyDeserialize)(t, br)
:
(myDeserializationDispatchTable [t.Name] as MyDeserialize) (t, br);
}
public static object deserializeEnum(Type t, BinaryReader br)
{
return myDeserializeInt32(t, br);
}
private static object myDeserializeInt32 (Type t, BinaryReader br)
{
return br.ReadInt32 ();
}
private static object myDeserializeISerializedType (Type t, BinaryReader br)
{
ISerializedType o = Activator.CreateInstance (t)
as ISerializedType;
o.deserialze (br);
return o;
}
private static object myDeserializeDouble (Type t, BinaryReader br)
{
return br.ReadDouble ();
}
private static object myDeserializeString (Type t, BinaryReader br)
{
return br.ReadString ();
}
private static object myDeserializeByteArray (Type t, BinaryReader br)
{
return br.ReadBytes (br.ReadInt32 ());
}
private static object myDeserializeSingle (Type t, BinaryReader br)
{
return br.ReadSingle ();
}
private static object myDeserializeChar (Type t, BinaryReader br)
{
return br.ReadChar ();
}
private static object myDeserializeLong (Type t, BinaryReader br)
{
return br.ReadInt64 ();
}
private static object myDeserializeSByte (Type t, BinaryReader br)
{
return br.ReadSByte ();
}
private static object myDeserializeBool (Type t, BinaryReader br)
{
return br.ReadBoolean ();
}
private static object myDeserializeByte (Type t, BinaryReader br)
{
return br.ReadByte ();
}
private static object myDeserializeDecimal (Type t, BinaryReader br)
{
return br.ReadDecimal ();
}
private static object myDeserializeUInt (Type t, BinaryReader br)
{
return br.ReadUInt32 ();
}
private static object myDeserializeDateTime (Type t, BinaryReader br)
{
return DateTime.FromOADate(br.ReadDouble());
//return new DateTime(br.ReadInt64());
}
private static object myDeserializeULong (Type t, BinaryReader br)
{
return br.ReadUInt64 ();
}
#endregion
}
}
@@ -1,44 +0,0 @@
using System;
namespace BCG
{
/// <summary>
/// The table publishing happens here
/// </summary>
public interface IPubTablePublisher
{
/// <summary>
/// Adds a row to the existing table
/// </summary>
/// <param name="row"></param>
void addRow (IBlueRow row);
/// <summary>
/// Deletes a row from an existing table
/// </summary>
/// <param name="row"></param>
void deleteRow (IBlueRow row);
/// <summary>
/// Changes an existing row
/// </summary>
/// <param name="row"></param>
void changeRow (IBlueRow row);
/// <summary>
/// Creates a table. if already exists overwrites it.
/// </summary>
/// <param name="rows"></param>
void createTable (IBlueRowCollection rows);
/// <summary>
/// Removes and adds more than one row; however the assumption here is that delete is
/// applied first and then add. If that violates the current state, exception is thrown
/// </summary>
/// <param name="delRows"></param>
/// <param name="addRows"></param>
void batchRemoveAdd (IBlueRowCollection delRows, IBlueRowCollection addRows);
/// <summary>
/// Changes more than one row at a time. This is specially helpful, since changes make a huge
/// percentage of the pubsub traffic.
/// </summary>
/// <param name="rows"></param>
void batchChange (IBlueRowCollection rows);
}
}
@@ -0,0 +1,75 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Xml.Serialization;
using BCG.Utilities;
using bts;
namespace BCG {
/// <summary>
/// This class will be used by the clients to publish tabular data to the pubsub
/// </summary>
public class PubTableBroker {
protected PublisherCore _publisher_core;
protected IDictionary<string, SinglePubTableBroker> _publisher_map =
new Dictionary<string, SinglePubTableBroker>();
protected bool myWaitingForFirstOp = false;
public PubTableBroker()
: this(new PublisherCore()) { }
public PubTableBroker(PublisherCore publisher) {
_publisher_core = publisher;
Log.Gen.info("PubTableBroker constructed");
}
public virtual void create_table(IBlueRowCollection table) {
string log_msg = $"PubTableBroker.createTable table: {table.schema.tableName}\n";
foreach (IBlueRow r in table) {
log_msg += $"id: {r["id"]}";
}
bts.Log.Gen.info(log_msg);
myCheckTransaction();
SinglePubTableBroker table_publisher = null;
var name_key = table.schema.tableName.ToLower();
if (!_publisher_map.TryGetValue(name_key, out table_publisher)) {
table_publisher = new SinglePubTableBroker(name_key, _publisher_core);
_publisher_map.Add(name_key, table_publisher);
}
table_publisher.create_table(table);
}
/// <summary>
/// If a table has not been created with the same instance of a PubTableBroker an ApplicationException
/// will be thrown
/// </summary>
/// <param name="r"></param>
public virtual void make_batch_changes(IBlueRowCollection new_rows,
IBlueRowCollection del_rows,
IBlueRowCollection added_rows) {
string log_msg = $"PubTableBroker.make_batch_changes table: {new_rows.schema.tableName} del: {del_rows.Count} added: {added_rows.Count}";
foreach (IBlueRow r in del_rows)
log_msg += $"id: {r["id"]} ";
log_msg += "addedRows: ";
foreach (IBlueRow r in added_rows)
log_msg += $"id: {r["id"]}";
bts.Log.Gen.info(log_msg);
SinglePubTableBroker table_publisher = null;
var name_key = new_rows.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
table_publisher.make_batch_changes(del_rows, added_rows);
}
protected void myCheckTransaction() {
if (myWaitingForFirstOp)
_publisher_core.begin_transaction();
myWaitingForFirstOp = false;
}
}
}
@@ -1,162 +0,0 @@
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 {
private readonly string _tag;
protected IBlueDataSerializer mySerializer;
protected PublisherCore myPubCore;
public PubTablePublisher(string tag, PublisherCore publisherCore) {
_tag = tag;
bts.Log.Gen.info($"PubTablePublisher.cons created for tag: {tag}");
myPubCore = publisherCore;
mySerializer = new BlueDataSerializationController();
}
#region IPubTablePublisher Members
public virtual void addRow(IBlueRow row) {
byte[] data;
mySerializer.serialize(StreamOpCode.add,
myGetRowCollectionArray(row),
out data);
myPublish(data, row.schema.tableName);
}
public virtual void deleteRow(IBlueRow row) {
byte[] data;
mySerializer.serialize(StreamOpCode.remove,
myGetRowCollectionArray(row),
out data);
myPublish(data, row.schema.tableName);
}
public virtual void changeRow(IBlueRow row) {
byte[] data;
mySerializer.serialize(StreamOpCode.change,
myGetRowCollectionArray(row),
out data);
myPublish(data, row.schema.tableName);
}
public virtual void createTable(IBlueRowCollection rows) {
byte[] data;
mySerializer.serialize(StreamOpCode.create,
new IBlueRowCollection[] { rows },
out data);
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);
}
//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);
}
// byte[] ops;
// Array rows_ds;
// _test_deserializer.deserialize(new Stream[] { new MemoryStream(data) }, out ops, out rows_ds);
}
public virtual void batchChange(IBlueRowCollection rows) {
byte[] data;
mySerializer.serialize(StreamOpCode.multipleChange,
new IBlueRowCollection[] { rows },
out data);
myPublish(data, rows.schema.tableName);
}
#endregion
#region private methods
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));
}
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) {
foreach (IBlueRow dRow in delRows)
if (!addRows.containsID((int)dRow["id"]))
return false;
return true;
} else
return false;
}
#endregion
}
public class IndependentTablePublisher : PubTablePublisher {
bool myIsCreated = false;
public IndependentTablePublisher(string tag, PublisherCore pubCore) : base(tag, pubCore) { }
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 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 deleteRow(IBlueRow row) {
myCheckCreate(row.schema);
base.deleteRow(row);
}
public override void createTable(IBlueRowCollection rows) {
myIsCreated = true;
base.createTable(rows);
}
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);
myIsCreated = true;
}
}
}
}
@@ -1,57 +0,0 @@
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 {
private IBlueDataSerializer mySerializer;
public BlueDataSerializationController() { }
#region IBlueDataSerializer Members
/// <summary>
/// Serializes an op and data; however if a non create is called before a create,
/// the serializedData is set to an empty byte array.
/// </summary>
/// <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) {
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[] { };
}
}
}
#endregion
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)
return Activator.CreateInstance(Type.GetType(serializerName), theSchema, serializerArgs) as IBlueDataSerializer;
else
return Activator.CreateInstance(Type.GetType(serializerName), theSchema) as IBlueDataSerializer;
}
}
}
@@ -1,111 +0,0 @@
using System;
using System.Collections;
using System.IO;
namespace BCG
{
/// <summary>
/// Abstract base class that can potentially serve all implementations of IBlueDataSerializer. The IBlueRowSerializer
/// is used to serialize individual rows. The implementaions should, in the constructor, contruct the myRowSerializer
/// to do the specific row serializations. Every nonabtract implementation of the this, should have a contructor
/// taking in an IBlueTableSchema.
/// </summary>
public abstract class BlueDataSerializer : IBlueDataSerializer
{
protected IBlueRowSerializer myRowSerializer;
protected string myClientDeserializerName, myPubsubDeserializerName;
public BlueDataSerializer(string pubsubDeserializerName,
string clientDeserializerName)
{
myPubsubDeserializerName = pubsubDeserializerName;
myClientDeserializerName = clientDeserializerName;
}
#region IBlueDataSerializer Members
/// <summary>
/// Provides the following serialization
///
/// -add, remove, change:
/// op
/// serializedRow (depending on the implementation of myRowSerializer)
///
/// -create
/// op
/// pubsubDeserializer name
/// clientDeserializer name
/// schema
/// # of rows
/// serializedRows
///
/// -multipleAddRemoves
/// op
/// # of deleted rows
/// serializedRows
/// # of added rows
/// serializedRows
///
/// -multipleChanges
/// op
/// # of changed rows
/// serializedRows
/// </summary>
/// <param name="op"></param>
/// <param name="rows"></param>
/// <param name="serializedData"></param>
public void serialize(byte op, IBlueRowCollection[] rows, out byte[] serializedData)
{
// BlueTrace.WriteSerializeStart(op, rows.Length);
BinaryWriter bw = new BinaryWriter(new MemoryStream());
if (op == StreamOpCode.add || op == StreamOpCode.remove || op == StreamOpCode.change)
{
bw.Write(op);
myRowSerializer.serializeRow(BlueDataUtility.extractRow(rows[0], 0), op, bw);
}
else if (op == StreamOpCode.create)
{
IBlueRowCollection createdRows = rows[0];
bw.Write(op);
bw.Write(myPubsubDeserializerName);
bw.Write(myClientDeserializerName);
int dummyIdCol = 0;
int[] dummyIdList = new int[1];
//the schema doesn't sort anything right now, because the C++ pub sub client depends on things being in a certain order
IBlueTableSchema sortedSchema = BlueDataUtility.getSortedSchema(createdRows.schema, out dummyIdList, out dummyIdCol);
sortedSchema.serialize(bw);
bw.Write(createdRows.Count);
foreach (IBlueRow r in createdRows)
myRowSerializer.serializeRow(r, StreamOpCode.add, bw);
}
else if (op == StreamOpCode.multipleRemoveAdd)
{
bw.Write(op);
IBlueRowCollection delRows = rows[0],
addRows = rows[1];
bw.Write(delRows.Count);
foreach (IBlueRow dr in delRows)
myRowSerializer.serializeRow(dr, StreamOpCode.remove, bw);
bw.Write(addRows.Count);
foreach (IBlueRow ar in addRows)
myRowSerializer.serializeRow(ar, StreamOpCode.add, bw);
}
else if (op == StreamOpCode.multipleChange)
{
bw.Write(op);
IBlueRowCollection changedRows = rows[0];
bw.Write(changedRows.Count);
foreach (IBlueRow cr in changedRows)
myRowSerializer.serializeRow(cr, StreamOpCode.change, bw);
}
bw.BaseStream.Position = 0;
serializedData = (bw.BaseStream as MemoryStream).ToArray();
// BlueTrace.WriteSerializeStop(serializedData.Length);
}
#endregion
}
}
@@ -1,21 +0,0 @@
using System;
using System.Collections;
namespace BCG
{
/// <summary>
/// All the data serialized to be send over to PubSub happens here. All it does is f(op, rows) = byte[].
/// </summary>
public interface IBlueDataSerializer
{
/// <summary>
/// f(op, rows) = byte[]
/// </summary>
/// <param name="op">Operation that can be add, delete, change etc</param>
/// <param name="rows">The data to serialize. The only case when it will be an array of more than 1 element
/// is when there are multiple deletes and adds, ie StreamOpCode.multipleRemoveAdd.
/// </param>
/// <param name="serializedData">The data serialized as bytes to be send over the wire </param>
void serialize (byte op, IBlueRowCollection[] rows, out byte[] serializedData);
}
}
@@ -1,23 +0,0 @@
using System;
using System.IO;
namespace BCG
{
/// <summary>
/// Responsible for serilializing rows
/// The way the serialization scheme works is that the header is same
/// for all serialization algorithms, only the way the row is serialized is different. Abstracting it out and we
/// can have each specific serializer have a unique implementation of IBlueRowSerializer.
/// </summary>
public interface IBlueRowSerializer
{
/// <summary>
/// Serializes a row and writes it into the BinaryWriter. Since its only one row, the ops should be appropriate
/// for one row; the ones allowed are StreamopCode.add, remove and change only.
/// </summary>
/// <param name="r"></param>
/// <param name="bw"></param>
void serializeRow (IBlueRow r, byte op, BinaryWriter bw);
}
}
@@ -1,96 +0,0 @@
using System;
using System.IO;
namespace BCG
{
/// <summary>
/// Serializes primitive types. Contructs a hash based scheme based on the index, to make everythign O(1)
/// rather than searching it up and making it O(n), n = types supported.
/// </summary>
public class PrimitiveSerializationHelper
{
private delegate void SerializeDelegate (object data, BinaryWriter bw);
private SerializeDelegate[] myDispatchTable;
#region constructors
public PrimitiveSerializationHelper (IBlueTableSchema schema)
: this (schema.columnInfo) {}
public PrimitiveSerializationHelper (ColumnInfo[] cis)
{
myDispatchTable = new SerializeDelegate [cis.Length];
foreach (ColumnInfo ci in cis)
myDispatchTable[ci.colNo] = myGetDispatchMethod (ci.colType);
}
#endregion
#region public methods
/// <summary>
/// Serializes the column no in the row and writes it into the BinaryWriter
/// </summary>
/// <param name="r"></param>
/// <param name="colNo"></param>
/// <param name="bw"></param>
public void serializeColumn (IBlueRow r, int colNo, BinaryWriter bw)
{
myDispatchTable[colNo] (r[colNo], bw);
}
/// <summary>
/// Writes the data to the BinaryWriter. The ColNo is provided to get the appropriate
/// serializer.
/// </summary>
/// <param name="data"></param>
/// <param name="colNo"></param>
/// <param name="bw"></param>
public void serializeColumn (object data, int colNo, BinaryWriter bw)
{
myDispatchTable[colNo] (data, bw);
}
#endregion
#region private methods
private void mySerializeInt32 (object data, BinaryWriter bw) {bw.Write ((Int32)data);}
private void mySerializeDouble (object data, BinaryWriter bw) {bw.Write ((double)data);}
private void mySerializeString (object data, BinaryWriter bw){bw.Write (data as string);}
private void mySerializeByteArray (object data, BinaryWriter bw)
{
byte[] bs = data as byte[];
bw.Write (bs.Length);
bw.Write (bs);
}
private void mySerializeChar (object data, BinaryWriter bw) {bw.Write ((char)data);}
private void mySerializeLong (object data, BinaryWriter bw) {bw.Write ((long)data);}
private void mySerializeSByte (object data, BinaryWriter bw) {bw.Write ((sbyte)data);}
private void mySerializeBool (object data, BinaryWriter bw) {bw.Write ((bool)data);}
private void mySerializeByte (object data, BinaryWriter bw) {bw.Write ((byte)data);}
private void mySerializeDecimal (object data, BinaryWriter bw) {bw.Write ((decimal)data);}
private void mySerializeUInt (object data, BinaryWriter bw) {bw.Write ((uint)data);}
private void mySerializeULong (object data, BinaryWriter bw){bw.Write ((ulong)data);}
private void mySerializeDateTime (object data, BinaryWriter bw) {bw.Write (((DateTime)data).Ticks);}
private void mySerializeSingle (object data, BinaryWriter bw) {bw.Write ((Single)data);}
private void mySerializeISerializedType (object data, BinaryWriter bw) {(data as ISerializedType).serialize (bw);}
private SerializeDelegate myGetDispatchMethod (Type t)
{
if (t.Equals (BlueDataValidTypes.INT)) return new SerializeDelegate (mySerializeInt32);
else if (t.Equals (BlueDataValidTypes.DOUBLE)) return new SerializeDelegate (mySerializeDouble);
else if (t.Equals (BlueDataValidTypes.STRING)) return new SerializeDelegate (mySerializeString);
else if (t.Equals (BlueDataValidTypes.BYTEARRAY)) return new SerializeDelegate (mySerializeByteArray);
else if (t.Equals (BlueDataValidTypes.CHAR)) return new SerializeDelegate (mySerializeChar);
else if (t.Equals (BlueDataValidTypes.LONG)) return new SerializeDelegate (mySerializeLong);
else if (t.Equals (BlueDataValidTypes.SBYTE)) return new SerializeDelegate (mySerializeSByte);
else if (t.Equals (BlueDataValidTypes.BOOL)) return new SerializeDelegate (mySerializeBool);
else if (t.Equals (BlueDataValidTypes.BYTE)) return new SerializeDelegate (mySerializeByte);
else if (t.Equals (BlueDataValidTypes.DECIMAL)) return new SerializeDelegate (mySerializeDecimal);
else if (t.Equals (BlueDataValidTypes.UINT)) return new SerializeDelegate (mySerializeUInt);
else if (t.Equals (BlueDataValidTypes.ULONG)) return new SerializeDelegate (mySerializeULong);
else if (t.Equals (BlueDataValidTypes.DATETIME)) return new SerializeDelegate (mySerializeDateTime);
else if (t.Equals (BlueDataValidTypes.SINGLE)) return new SerializeDelegate (mySerializeSingle);
else if (SerializationUtilityMethods.isSerializedType (t)) return new SerializeDelegate (mySerializeISerializedType);
else throw new ApplicationException (t.FullName + " is not a supported type");
}
#endregion
}
}
@@ -1,120 +0,0 @@
using System;
using System.Collections;
using System.IO;
using BCG.Utilities;
using System.Collections.Generic;
namespace BCG
{
/// <summary>
/// Helps the UniversalSerializer by serializing one row. Hence this class is agnostic to the operation
/// which is figured out by UniversalSerializer.
///
/// it sorts the schema it gets, to make sure that the rows are always published the same way.
/// For now, the sorting operation doesn't do anything. The reason for this is that C++ clients
/// are depending upon the data arriving in a certain order.
///
/// It performs a mapping : (row)->byte[]
/// </summary
internal class UniversalRowSerializer : IBlueRowSerializer
{
private PrimitiveSerializationHelper myPrimitiveSerializationHelper;
private int myFixedSize;
private int[] myNonFixedColIndexes;
private IBlueTableSchema mySchema;
//this null map is the null map that will be written to the wire
//therefore, its values represent the nulls in row, ordered by the-rearranged schema.
private BitArray myNullMap;
private byte[] myNullMapArray; //just so that a new instance is not created everytime
//this thing stores a mapping between the columns in the original schema that were passed in
private int[] mySortedSchemaToOriginalSchemaMapping;
private int myIdColumnInSortedSchema; //this is used because the id column will be different in the original row and the schema
public UniversalRowSerializer(IBlueTableSchema schema)
{
mySchema = schema;
myPrimitiveSerializationHelper = new PrimitiveSerializationHelper(mySchema);
//therefore well use the original code
//sort the schema after we give it to the serialiaztion helper, because the helper constructs a dispatch table
//so it needs to know about the original schema.
mySchema = BlueDataUtility.getSortedSchema(mySchema, out mySortedSchemaToOriginalSchemaMapping, out myIdColumnInSortedSchema);
myNullMapArray =
new byte[Convert.ToInt32(Math.Ceiling(Convert.ToDouble(mySchema.columnInfo.Length) / 8))];
myNullMap =
new BitArray(myNullMapArray);
myInitSizeCalculations();
}
#region IBlueRowSerializer methods
/// <summary>
/// Row serialized in the following order
/// row size (nullBitMap size + actual row size)
/// null bit map
/// non null row members (with id as the first col)
/// </summary>
/// <param name="r"></param>
/// <param name="bw"></param>
public void serializeRow(IBlueRow r, byte op, BinaryWriter bw)
{
myNullMap.SetAll(false);
for (int i = 0; i < mySchema.columnNames.Length; i++)
if (r[mySortedSchemaToOriginalSchemaMapping[i]] == DBNull.Value || r[mySortedSchemaToOriginalSchemaMapping[i]] == null)
myNullMap[i] = true;
myNullMap.CopyTo(myNullMapArray, 0);
long initPos = bw.BaseStream.Position;
bw.Write((int)0); ///place holder for size
bw.Write(myNullMapArray);
bw.Write((int)r[mySortedSchemaToOriginalSchemaMapping[myIdColumnInSortedSchema]]);
foreach (ColumnInfo ci in mySchema.columnInfo)
if (!myNullMap[ci.colNo] && ci.colNo != myIdColumnInSortedSchema)
myPrimitiveSerializationHelper.serializeColumn(r, mySortedSchemaToOriginalSchemaMapping[ci.colNo], bw);
long endPos = bw.BaseStream.Position;
bw.BaseStream.Position = initPos;
bw.Write(Convert.ToInt32(endPos - (initPos+4))); /// size does not include the meta data hence substracting 4
bw.BaseStream.Position = endPos;
}
public void serializeSchema(BinaryWriter bw)
{
mySchema.serialize(bw);
}
#endregion
#region size calculations
/// <summary>
/// Sets up the fixed length (size in bytes occupied by each of the primitive type)
/// and an index for the non primitive type
/// </summary>
private void myInitSizeCalculations()
{
ArrayList temp = new ArrayList();
myFixedSize = myNullMapArray.Length;
foreach (ColumnInfo ci in mySchema.columnInfo)
{
if (!SerializationUtilityMethods.isFixedLengthType(ci.colType))
temp.Add(ci.colNo);
else
myFixedSize += SerializationUtilityMethods.getFixedLengthTypeSize(ci.colType);
}
myNonFixedColIndexes = temp.ToArray(typeof(int)) as int[];
}
/// <summary>
/// Find the size of the serialized row, assumes that nullMap has already
/// been built
/// </summary>
/// <param name="fixedSize"></param>
/// <param name="r"></param>
/// <returns></returns>
private int myGetRowSizeInBytes(int fixedSize, IBlueRow r)
{
foreach (int colNo in myNonFixedColIndexes)
{
if (!myNullMap[colNo])
fixedSize += //myGetStringSizeInBytes (r[colNo] as string);
SerializationUtilityMethods.getObjectSerializedSize(r[mySortedSchemaToOriginalSchemaMapping[colNo]]);
}
return fixedSize;
}
#endregion
}
}
@@ -1,16 +0,0 @@
using System;
namespace BCG
{
/// <summary>
/// Uses the UniversalRowSerializer as the IBlueRowSerializer implementation.
/// </summary>
public class UniversalSerializer : BlueDataSerializer
{
public UniversalSerializer (IBlueTableSchema schema)
: base ("BCG.PubsubUniversalDeserializer, DataStreamCore", "BCG.ClientUniversalDeserializer")
{
myRowSerializer = new UniversalRowSerializer (schema);
}
}
}
@@ -0,0 +1,54 @@
using bts;
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 SinglePubTableBroker {
private readonly string _tag;
protected IStreamIOMsgSerializer _serializer;
protected PublisherCore _publisher_core;
public SinglePubTableBroker(string tag, PublisherCore publisher_core) {
bts.Log.Gen.info($"SinglePubTableBroker.cons created for tag: {tag}");
_tag = tag;
_publisher_core = publisher_core;
_serializer = new UniversalStreamIOSerializer();
}
public void create_table(IBlueRowCollection rows) {
bts.StreamIOMessage.CreateMessage cr_msg = new bts.StreamIOMessage.CreateMessage(rows);
bts.StreamIOMessage stream_io_msg = new bts.StreamIOMessage(cr_msg);
byte[] msg_bytes = _serializer.serialize(stream_io_msg);
PublishMsg pub_msg = new PublishMsg() {
tag = DSTagManager.get_stream_tag(rows.schema.tableName),
tag_type = DSTagManager.DataStreamTagType,
data_to_publish = msg_bytes
};
PubSubClientMessage msg = new PubSubClientMessage(pub_msg);
_publisher_core.publish(msg);
}
public void make_batch_changes(IBlueRowCollection del_rows, IBlueRowCollection added_rows) {
bts.StreamIOMessage.MultipleRemoveAddMessage mra_msg =
new bts.StreamIOMessage.MultipleRemoveAddMessage(del_rows, added_rows);
bts.StreamIOMessage stream_io_msg = new bts.StreamIOMessage(mra_msg);
byte[] msg_bytes = _serializer.serialize(stream_io_msg);
PublishMsg pub_msg = new PublishMsg() {
tag = DSTagManager.get_stream_tag(added_rows.schema.tableName),
tag_type = DSTagManager.DataStreamTagType,
data_to_publish = msg_bytes
};
PubSubClientMessage msg = new PubSubClientMessage(pub_msg);
_publisher_core.publish(msg);
}
}
}
@@ -1,25 +0,0 @@
using System;
using System.IO;
using System.Collections;
namespace BCG
{
/// <summary>
/// Deserializes a row. Returns the id of the row and its full content
/// </summary>
public interface IPubsubRowDeserializer
{
/// <summary>
/// Reads the data from the BinaryReader and deserializes it in the form of a row
/// </summary>
/// <param name="currentState">Some deserializers might need the current state, ie a Dictionary of rows
/// keyed off the id</param>
/// <param name="br">BinaryReader starting at the row</param>
/// <param name="op">The operation, as this might drive the deserializations scheme in some cases. This op
/// however is one of the basics operations, add remove or change as all other operations can be resolved into this</param>
/// <param name="id">The id of the deserialized row</param>
/// <param name="row">The actual row contents</param>
void deserializeRow (IDictionary currentState, BinaryReader br, byte op, out int id, out object row);
}
}
@@ -1,168 +0,0 @@
using System;
using System.Collections;
using System.IO;
using BCG.Utilities;
using System.Text;
namespace BCG
{
/// <summary>
/// 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
protected IPubsubRowDeserializer myDeserializer;
public PubsubDeserializer () {}
#region IPubSubDeserializer Members
public virtual void deserialize (Stream[] streams, out byte[] theOps, out Array theRows)
{
BinaryReader br = new BinaryReader (UtilityMethods.getAggregatedStream (streams));
ArrayList ops = new ArrayList (), rows = new ArrayList ();
while (true)
{
IDictionary[] result;
byte op;
try
{
int value = br.BaseStream.ReadByte();
if (value == -1) break;
op = (byte)value;
}
catch (EndOfStreamException)
{
// TODO, logically break loop
break;
}
if (op == StreamOpCode.create)
{
myState.Clear ();
br.ReadString (); //the pubsub-deserializer name, should be the same as this's name
myClientDeserializerName = br.ReadString (); //the client-deserializer name
(mySchema = new BlueTableSchema()).deserialze (br);
result = new IDictionary[] {myGetRows (br, op, br.ReadInt32 ())};
myEncorporatRows (result[0], op);
ops.Add (op);
rows.Add (result);
}
else
{
if (mySchema != null)
{
if (op == StreamOpCode.add || op == StreamOpCode.change || op == StreamOpCode.remove)
{
result = new IDictionary[] {myGetRows (br, op, 1)};
myEncorporatRows (result[0], op);
ops.Add (op);
rows.Add (result);
}
else if (op == StreamOpCode.multipleChange)
{
result = new IDictionary[] {myGetRows (br, op, br.ReadInt32 ())};
myEncorporatRows (result[0], op);
ops.Add (op);
rows.Add (result);
}
else if (op == StreamOpCode.multipleRemoveAdd)
{
ops.Add (op);
result = new IDictionary [] {
myGetRows (br, StreamOpCode.remove, br.ReadInt32 ()),
myGetRows (br, StreamOpCode.add, br.ReadInt32 ())
};
myEncorporatRows (result[0], StreamOpCode.remove);
myEncorporatRows (result[1], StreamOpCode.add);
rows.Add (result);
}
else
{
// BlueEventLog.logEvent ("Illegal op-code received", BlueEventLevel.Error);
}
}
else
{
// BlueEventLog.logEvent ("Received a non create operation even though the schema" +
// "has never been created", BlueEventLevel.Warning);
}
}
}
theOps = ops.ToArray (typeof(byte)) as byte[];
theRows = rows.ToArray ();
}
/// <summary>
/// Sends in a create signal, so that new clients can get a create everytime and start
/// afresh from there
/// </summary>
/// <returns></returns>
public virtual byte[] getState()
{
if (mySchema == null)
return new byte[] {};
else
{
BinaryWriter bw = new BinaryWriter (new MemoryStream ());
bw.Write (StreamOpCode.create);
bw.Write (GetType().AssemblyQualifiedName);
bw.Write (myClientDeserializerName);
mySchema.serialize (bw);
bw.Write (myState.Count);
foreach (byte[] row in myState.Values)
bw.Write (row);
return (bw.BaseStream as MemoryStream).ToArray ();
}
}
#endregion
/// <summary>
/// Every row that has been deserialized passes through this method, so that it can update the state.
/// </summary>
/// <param name="rows"></param>
/// <param name="op"></param>
protected virtual void myEncorporatRows (IDictionary rows, byte op)
{
if (op == StreamOpCode.add || op == StreamOpCode.create)
foreach (DictionaryEntry de in rows)
{
if (myState.Contains(de.Key)) {
// BlueEventLog2.instance().logEvent(String.Format("Duplicate row creation. t: {0} id:{1}", mySchema.tableName, de.Key),BlueEventLog2Level.Fatal);
StringBuilder b = new StringBuilder();
foreach (string n in mySchema.columnNames)
b.AppendFormat(" {0}", n);
// BlueEventLog2.instance().logEvent(String.Format("Schema:{0}", b.ToString()), BlueEventLog2Level.Fatal);
}
myState.Add(de.Key, de.Value);
}
else if (op == StreamOpCode.remove)
foreach (DictionaryEntry de in rows)
{
if (!myState.Contains(de.Key))
{
// BlueEventLog2.instance().logEvent(String.Format("Unknown row deletion. t: {0} id:{1}", mySchema.tableName, de.Key), BlueEventLog2Level.Fatal);
StringBuilder b = new StringBuilder();
foreach (string n in mySchema.columnNames)
b.AppendFormat(" {0}", n);
// BlueEventLog2.instance().logEvent(String.Format("Schema:{0}", b.ToString()),BlueEventLog2Level.Fatal);
}
myState.Remove(de.Key);
}
else if (op == StreamOpCode.change || op == StreamOpCode.multipleChange)
foreach (DictionaryEntry de in rows)
myState[de.Key] = de.Value;
}
/// <summary>
/// Mass deserialization happens here, also since there is no knowledge of the schema
/// </summary>
/// <param name="br"></param>
/// <param name="op"></param>
/// <param name="noOfRows"></param>
/// <returns></returns>
protected abstract IDictionary myGetRows (BinaryReader br, byte op, int noOfRows);
}
}
@@ -1,23 +0,0 @@
using System;
using System.Collections;
using System.IO;
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++) {
int id; object row;
myDeserializer.deserializeRow(myState, br, op, out id, out row);
retVal.Add(id, row);
}
return retVal;
}
}
}
@@ -1,34 +0,0 @@
using System;
using System.IO;
using System.Collections;
namespace BCG
{
public class PubsubUniversalRowDeserializer : IPubsubRowDeserializer
{
private int myNullMapLength;
private IBlueTableSchema mySchema;
private int myRowOverheadSize = SerializationUtilityMethods.getFixedLengthTypeSize (typeof(int));
public PubsubUniversalRowDeserializer (IBlueTableSchema schema)
{
mySchema = schema;
myNullMapLength = Convert.ToInt32((Math.Ceiling(Convert.ToDouble(mySchema.columnNames.Length)/8)));
}
#region IRowDeserializer Members
public void deserializeRow (IDictionary currentState, BinaryReader br, byte op, out int id, out object row)
{
//current state is ignored
long pos = br.BaseStream.Position;
int rowSize = br.ReadInt32 ();
br.BaseStream.Position = pos;
row = br.ReadBytes (rowSize + myRowOverheadSize);
id = BitConverter.ToInt32 (row as byte[], myNullMapLength + myRowOverheadSize);
}
#endregion
}
}
@@ -1,49 +0,0 @@
using System;
using System.IO;
using System.Collections.Generic;
using BCG.Utilities;
namespace BCG {
/// <summary>
/// Keeps a collection of TagStateBanks to hold the state of each tag
/// </summary>
public class PubsubServerTagHandler : IPubSubServerTagHandler {
private IDictionary<string, TagStateBank> _tag_state_map = new Dictionary<string, TagStateBank>();
private bool myPublishStatistics = //DataStreamGatewaySettings.instance.enablePubsubStats;
false;
#region IPubSubServerTagHandler Members
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) {
bts.Log.Gen.info($"PubsubServerTagHandler.update tag: {tag} streams: {messageBodies.Length}");
if (myPublishStatistics) {
StatisticsLogger.instance.log(tag, messageBodies);
}
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);
}
tag_state_bank.update(messageBodies);
}
public void doWork() { }
public string[] supportedTagTypes { get { return new string[] { "DataStreamTag" }; } }
public void register(InternalPublishDelegate callback) { }
#endregion
}
}
@@ -1,102 +0,0 @@
using System;
using System.IO;
using System.Collections;
using BCG.Utilities;
using System.Threading;
namespace BCG
{
class TagData
{
public DateTime lastUpdateTime;
public long totalSize;
public int lastUpdateSize;
public TagData(DateTime ut, long ts, int lus)
{
lastUpdateTime = ut;
totalSize = ts;
lastUpdateSize = lus;
}
public override string ToString()
{
return lastUpdateTime.ToString() + "," + totalSize.ToString() + "," + lastUpdateSize.ToString();
}
}
class StatisticsLogger
{
private IDictionary myTagData = new Hashtable();
private static StatisticsLogger mySelf;
private BlockingQueue myQueue = new BlockingQueue();
private DateTime myLastFireTime = DateTime.MinValue;
private TimeSpan myPubsubStatsUpdateInterval = new TimeSpan(0, 0, 0, 0, DataStreamGatewaySettings.instance.pubsubStatsUpdateInterval);
private TimeSpan myTagStatsUpdateInterval = new TimeSpan(0, 0, 0, 0, DataStreamGatewaySettings.instance.singleTagStatsUpdateInterval);
private StatisticsLogger()
{
Thread readThread = new Thread(new ThreadStart(myReadAndPublish));
readThread.Priority = ThreadPriority.BelowNormal;
readThread.Start();
}
public static StatisticsLogger instance
{
get
{
if (mySelf == null)
mySelf = new StatisticsLogger();
return mySelf;
}
}
public void log(string tag, Stream[] bodies)
{
long nBytes = 0;
foreach (Stream s in bodies)
nBytes += s.Length;
myQueue.enqueue(new object[] { tag, Convert.ToInt32 (nBytes) });
}
private void myReadAndPublish()
{
while (true)
{
object qe = myQueue.dequeue(50);
if (qe != null)
{
object[] args = qe as object[];
string tag = args[0].ToString();
int dataSize = (int)args[1];
if (!myTagData.Contains(tag))
{
myTagData.Add(tag, new TagData(DateTime.Now, Convert.ToInt64(dataSize), dataSize));
}
else
{
TagData tdToSend = myTagData[tag] as TagData;
tdToSend.lastUpdateSize += dataSize;
tdToSend.totalSize += dataSize;
}
}
myFireMonitors();
}
}
private void myFireMonitors()
{
if (DateTime.Now.Subtract(myLastFireTime) >= myPubsubStatsUpdateInterval)
{
foreach (string tag in myTagData.Keys)
{
TagData td = myTagData[tag] as TagData;
if (td.lastUpdateSize > 0 && DateTime.Now.Subtract(td.lastUpdateTime) >= myTagStatsUpdateInterval)
{
td.lastUpdateTime = DateTime.Now;
td.lastUpdateSize = 0;
}
}
myLastFireTime = DateTime.Now;
}
}
}
}
@@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace BCG {
public class TagStateBank {
private PubsubDeserializationController myDeserializationController = new PubsubDeserializationController();
public TagStateBank() { }
public TagStateBank(string tag) {
bts.Log.Gen.info("TagStateBank created for tag: {tag}");
}
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);
}
}
}
@@ -1,146 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using BCG.Utilities;
namespace BCG
{
public class CompressionClientDeserializer : IClientDeserializer
{
protected IBlueTableSchema mySchema;
protected IBlueTableSchema myFirstSchema;
protected IClientRowDeserializer myRowDeserializer;
public CompressionClientDeserializer()
{
myFirstSchema = null;
mySchema = null;
}
#region IClientDeserializer Members
public void deserialize(Stream[] streams, out byte[] theOps, out Array theRows)
{
BinaryReader br = new BinaryReader(UtilityMethods.getAggregatedStream(streams));
// BlueTrace.WriteDeserializeStart(streams.Length, br.BaseStream.Length);
// emit # of streams and total length
ArrayList ops = new ArrayList(), rows = new ArrayList();
IBlueRowCollection[] result;
while (true)
{
byte op;
try
{
int value = br.BaseStream.ReadByte();
if (value == -1) break;
op = (byte)value;
// BlueTrace.WriteDeserializeOperation(op);
}
catch (EndOfStreamException)
{
break;
}
if (op == StreamOpCode.create)
{
br.ReadString(); //pubsubDeserializer
br.ReadString(); //clientDeserializer
mySchema = new BlueTableSchema();
mySchema.deserialze(br);
//keep track of the first schema you've ever seen, so you know how to reorder columns
if (myFirstSchema == null)
myFirstSchema = mySchema;
/// decompress here
int compressedMessageSize = br.ReadInt32();
byte[] compressedData = br.ReadBytes(compressedMessageSize);
BinaryReader decompressedBr = new BinaryReader(UtilityMethods.decompress(compressedData));
result = new IBlueRowCollection[] { myGetRows(decompressedBr, op, decompressedBr.ReadInt32()) };
myEncorporateRows(result[0], op);
ops.Add(op);
rows.Add(result);
}
else
{
if (mySchema != null)
{
if (op == StreamOpCode.add || op == StreamOpCode.change || op == StreamOpCode.remove)
{
result = new IBlueRowCollection[] { myGetRows(br, op, 1) };
myEncorporateRows(result[0], op);
ops.Add(op);
rows.Add(result);
}
else if (op == StreamOpCode.multipleChange)
{
int compressedMessageSize = br.ReadInt32();
byte[] compressedData = br.ReadBytes(compressedMessageSize);
BinaryReader decompressedBr = new BinaryReader(UtilityMethods.decompress(compressedData));
result = new IBlueRowCollection[] { myGetRows(decompressedBr, op, decompressedBr.ReadInt32()) };
myEncorporateRows(result[0], op);
ops.Add(op);
rows.Add(result);
}
else if (op == StreamOpCode.multipleRemoveAdd)
{
int compressedMessageSize = br.ReadInt32();
byte[] compressedData = br.ReadBytes(compressedMessageSize);
BinaryReader decompressedBr = new BinaryReader(UtilityMethods.decompress(compressedData));
result =
new IBlueRowCollection[] {
myGetRows (decompressedBr, StreamOpCode.remove, decompressedBr.ReadInt32 ()),
myGetRows (decompressedBr, StreamOpCode.add, decompressedBr.ReadInt32 ())
};
myEncorporateRows(result[0], StreamOpCode.remove);
myEncorporateRows(result[1], StreamOpCode.add);
ops.Add(op);
rows.Add(result);
}
else
{
// BlueEventLog.logEvent("Illegal op-code received", BlueEventLevel.Error);
}
}
else
{
// BlueEventLog.logEvent("Received a non create operation even though the schema" +
// "has never been created", BlueEventLevel.Warning);
}
}
}
theOps = ops.ToArray(typeof(byte)) as byte[];
theRows = rows.ToArray();
// BlueTrace.WriteDeserializeStop(rows.Count);
}
#endregion
private IBlueRowCollection myGetRows(BinaryReader br, byte op, int nRows)
{
BlueTable retVal = new BlueTable(mySchema);
if (myRowDeserializer == null)
myRowDeserializer = new ClientUniversalRowDeserializer(mySchema);
else if (op == StreamOpCode.create)
myRowDeserializer = new ClientReorderingRowDeserializer(myFirstSchema, mySchema);
for (int i = 0; i < nRows; i++)
{
IBlueRow row;
myRowDeserializer.deserializeRow(null, br, op, out row);
retVal.addRow(row);
}
return retVal;
}
private void myEncorporateRows(IBlueRowCollection rows, byte op) { }
}
}
@@ -1,192 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
using BCG.Utilities;
namespace BCG
{
public class CompressionPubsubDeserializer : IPubsubDeserializer
{
protected IDictionary myState = new Hashtable();
protected IBlueTableSchema mySchema;
protected string myClientDeserializerName; //for the getState method
protected IPubsubRowDeserializer myRowDeserializer;
public CompressionPubsubDeserializer() { }
#region IPubSubDeserializer Members
public virtual void deserialize(Stream[] streams, out byte[] theOps, out Array theRows)
{
BinaryReader br = new BinaryReader(UtilityMethods.getAggregatedStream(streams));
ArrayList ops = new ArrayList(), rows = new ArrayList();
while (true)
{
IDictionary[] result;
byte op;
try
{
int value = br.BaseStream.ReadByte();
if (value == -1) break;
op = (byte)value;
}
catch (EndOfStreamException)
{
break;
}
if (op == StreamOpCode.create)
{
myState.Clear();
br.ReadString(); //the pubsub-deserializer name, should be the same as this's name
myClientDeserializerName = br.ReadString(); //the client-deserializer name
(mySchema = new BlueTableSchema()).deserialze(br);
/// deserialize this part
int compressedMessageSize = br.ReadInt32();
BinaryReader decompressedBr = new BinaryReader(UtilityMethods.decompress(br.ReadBytes(compressedMessageSize)));
result = new IDictionary[] { myGetRows(decompressedBr, op, decompressedBr.ReadInt32()) };
myEncorporatRows(result[0], op);
ops.Add(op);
rows.Add(result);
}
else
{
if (mySchema != null)
{
if (op == StreamOpCode.add || op == StreamOpCode.change || op == StreamOpCode.remove)
{
result = new IDictionary[] { myGetRows(br, op, 1) };
myEncorporatRows(result[0], op);
ops.Add(op);
rows.Add(result);
}
else if (op == StreamOpCode.multipleChange)
{
int compressedMessageSize = br.ReadInt32();
BinaryReader decompressedBr = new BinaryReader(UtilityMethods.decompress(br.ReadBytes(compressedMessageSize)));
result = new IDictionary[] { myGetRows(decompressedBr, op, decompressedBr.ReadInt32()) };
myEncorporatRows(result[0], op);
ops.Add(op);
rows.Add(result);
}
else if (op == StreamOpCode.multipleRemoveAdd)
{
ops.Add(op);
int compressedMessageSize = br.ReadInt32();
BinaryReader decompressedBr = new BinaryReader(UtilityMethods.decompress(br.ReadBytes(compressedMessageSize)));
result = new IDictionary[] {
myGetRows (decompressedBr, StreamOpCode.remove, decompressedBr.ReadInt32 ()),
myGetRows (decompressedBr, StreamOpCode.add, decompressedBr.ReadInt32 ())
};
myEncorporatRows(result[0], StreamOpCode.remove);
myEncorporatRows(result[1], StreamOpCode.add);
rows.Add(result);
}
else
{
// BlueEventLog.logEvent("Illegal op-code received", BlueEventLevel.Error);
}
}
else
{
// BlueEventLog.logEvent("Received a non create operation even though the schema" +
// "has never been created", BlueEventLevel.Warning);
}
}
}
theOps = ops.ToArray(typeof(byte)) as byte[];
theRows = rows.ToArray();
}
/// <summary>
/// Sends in a create signal, so that new clients can get a create everytime and start
/// afresh from there
/// </summary>
/// <returns></returns>
public virtual byte[] getState()
{
if (mySchema == null)
return new byte[] { };
else
{
BinaryWriter bw = new BinaryWriter(new MemoryStream());
bw.Write(StreamOpCode.create);
bw.Write(GetType().AssemblyQualifiedName);
bw.Write(myClientDeserializerName);
mySchema.serialize(bw);
/// compress it here
BinaryWriter decompressedBw = new BinaryWriter(new MemoryStream());
decompressedBw.Write(myState.Count);
foreach (byte[] row in myState.Values)
decompressedBw.Write(row);
decompressedBw.BaseStream.Position = 0;
byte[] compressedData = UtilityMethods.compress(decompressedBw.BaseStream);
bw.Write(compressedData.Length);
bw.Write(compressedData);
return (bw.BaseStream as MemoryStream).ToArray();
}
}
#endregion
/// <summary>
/// Every row that has been deserialized passes through this method, so that it can update the state.
/// </summary>
/// <param name="rows"></param>
/// <param name="op"></param>
protected virtual void myEncorporatRows(IDictionary rows, byte op)
{
if (op == StreamOpCode.add || op == StreamOpCode.create)
foreach (DictionaryEntry de in rows)
{
if (myState.Contains(de.Key))
{
// BlueEventLog2.instance().logEvent(String.Format("Duplicate row creation. t: {0} id:{1}", mySchema.tableName, de.Key), BlueEventLog2Level.Fatal);
StringBuilder b = new StringBuilder();
foreach (string n in mySchema.columnNames)
b.AppendFormat(" {0}", n);
// BlueEventLog2.instance().logEvent(String.Format("Schema:{0}", b.ToString()), BlueEventLog2Level.Fatal);
}
myState.Add(de.Key, de.Value);
}
else if (op == StreamOpCode.remove)
foreach (DictionaryEntry de in rows)
{
if (!myState.Contains(de.Key))
{
// BlueEventLog2.instance().logEvent(String.Format("Unknown row deletion. t: {0} id:{1}", mySchema.tableName, de.Key), BlueEventLog2Level.Fatal);
StringBuilder b = new StringBuilder();
foreach (string n in mySchema.columnNames)
b.AppendFormat(" {0}", n);
// BlueEventLog2.instance().logEvent(String.Format("Schema:{0}", b.ToString()), BlueEventLog2Level.Fatal);
}
myState.Remove(de.Key);
}
else if (op == StreamOpCode.change || op == StreamOpCode.multipleChange)
foreach (DictionaryEntry de in rows)
myState[de.Key] = de.Value;
}
/// <summary>
/// Mass deserialization happens here, also since there is no knowledge of the schema
/// </summary>
/// <param name="br"></param>
/// <param name="op"></param>
/// <param name="noOfRows"></param>
/// <returns></returns>
private IDictionary myGetRows (BinaryReader br, byte op, int noOfRows)
{
myRowDeserializer = myRowDeserializer == null ? new PubsubUniversalRowDeserializer (mySchema) : myRowDeserializer;
Hashtable retVal = new Hashtable ();
for (int i = 0; i < noOfRows; i++)
{
int id; object row;
myRowDeserializer.deserializeRow (myState, br, op, out id, out row);
retVal.Add (id, row);
}
return retVal;
}
}
}
@@ -1,90 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace BCG
{
public class CompressionSerializer : IBlueDataSerializer
{
private IBlueRowSerializer myRowSerializer;
private string myPubsubDeserializerName = "BCG.CompressionPubsubDeserializer, DataStreamCore", myClientDeserializerName = "BCG.CompressionClientDeserializer";
public CompressionSerializer (IBlueTableSchema schema)
{
myRowSerializer = new UniversalRowSerializer (schema);
}
public void serialize(byte op, IBlueRowCollection[] rows, out byte[] serializedData)
{
// BlueTrace.WriteSerializeStart(op, rows.Length);
BinaryWriter bw = new BinaryWriter(new MemoryStream());
if (op == StreamOpCode.add || op == StreamOpCode.remove || op == StreamOpCode.change)
{
bw.Write(op);
/// no need to compress the only row
myRowSerializer.serializeRow(BlueDataUtility.extractRow(rows[0], 0), op, bw);
}
else if (op == StreamOpCode.create)
{
IBlueRowCollection createdRows = rows[0];
bw.Write(op);
bw.Write(myPubsubDeserializerName);
bw.Write(myClientDeserializerName);
int dummyIdCol = 0;
int[] dummyIdList = new int[1];
//the schema doesn't sort anything right now, because the C++ pub sub client depends on things being in a certain order
IBlueTableSchema sortedSchema = BlueDataUtility.getSortedSchema(createdRows.schema, out dummyIdList, out dummyIdCol);
sortedSchema.serialize(bw);
/// compress it here
BinaryWriter decompressedBw = new BinaryWriter(new MemoryStream());
decompressedBw.Write(createdRows.Count);
foreach (IBlueRow r in createdRows)
myRowSerializer.serializeRow(r, StreamOpCode.add, decompressedBw);
decompressedBw.BaseStream.Position = 0;
byte[] compressedData = UtilityMethods.compress(decompressedBw.BaseStream);
bw.Write(compressedData.Length);
bw.Write(compressedData);
}
else if (op == StreamOpCode.multipleRemoveAdd)
{
bw.Write(op);
IBlueRowCollection delRows = rows[0], addRows = rows[1];
/// compress it here
BinaryWriter decompressedBw = new BinaryWriter(new MemoryStream());
decompressedBw.Write(delRows.Count);
foreach (IBlueRow dr in delRows)
myRowSerializer.serializeRow(dr, StreamOpCode.remove, decompressedBw);
decompressedBw.Write(addRows.Count);
foreach (IBlueRow ar in addRows)
myRowSerializer.serializeRow(ar, StreamOpCode.add, decompressedBw);
decompressedBw.BaseStream.Position = 0;
byte[] compressedData = UtilityMethods.compress(decompressedBw.BaseStream);
bw.Write(compressedData.Length);
bw.Write(compressedData);
}
else if (op == StreamOpCode.multipleChange)
{
bw.Write(op);
IBlueRowCollection changedRows = rows[0];
/// compress it here
BinaryWriter decompressedBw = new BinaryWriter(new MemoryStream());
decompressedBw.Write(changedRows.Count);
foreach (IBlueRow cr in changedRows)
myRowSerializer.serializeRow(cr, StreamOpCode.change, decompressedBw);
decompressedBw.BaseStream.Position = 0;
byte[] compressedData = UtilityMethods.compress(decompressedBw.BaseStream);
bw.Write(compressedData.Length);
bw.Write(compressedData);
}
bw.BaseStream.Position = 0;
serializedData = (bw.BaseStream as MemoryStream).ToArray();
// BlueTrace.WriteSerializeStop(serializedData.Length);
}
}
}
@@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BCG
{
public class BBOOptionDeserializer : ClientFixedDeserializer
{
public BBOOptionDeserializer() { }
}
}
@@ -1,49 +0,0 @@
using System;
using BCG.Utilities;
namespace BCG
{
public abstract class ClientFixedDeserializer : ClientDeserializer
{
private BlueTable myCurrentState;
public ClientFixedDeserializer () {}
protected override IBlueRowCollection myGetRows (System.IO.BinaryReader br, byte op, int nRows)
{
BlueTable retVal = new BlueTable (mySchema);
op = op == StreamOpCode.create ? StreamOpCode.add :
op == StreamOpCode.multipleChange ? StreamOpCode.change : op;
if (myRowDeserializer == null)
{
myRowDeserializer = new ClientFixedRowDeserializer (mySchema);
myCurrentState = new BlueTable (mySchema);
}
for (int i = 0; i < nRows; i++)
{
IBlueRow r;
myRowDeserializer.deserializeRow (myCurrentState, br, op, out r);
retVal.addRow (r);
}
return retVal;
}
protected override void myEncorporateRows (IBlueRowCollection rows, byte op)
{
if (op == StreamOpCode.create)
myCurrentState = new BlueTable (rows);
else if (op == StreamOpCode.add)
myCurrentState.addRows (rows);
else if (op == StreamOpCode.remove)
myCurrentState.deleteRows (rows);
else if (op == StreamOpCode.change || op == StreamOpCode.multipleChange)
myCurrentState.changeRows (rows);
else
{
// BlueEventLog.logAssert (false, "Illegal operation for this context");
}
}
}
}
@@ -1,38 +0,0 @@
using System;
using System.IO;
using BCG.Utilities;
namespace BCG
{
public class ClientFixedRowDeserializer : IClientRowDeserializer
{
private PrimitiveDeserializationHelper myHelper;
private IBlueTableSchema mySchema;
public ClientFixedRowDeserializer (IBlueTableSchema schema)
{
myHelper = new PrimitiveDeserializationHelper (mySchema = schema);
}
#region IClientRowDeserializer Members
public void deserializeRow (IBlueRowCollection currentState, BinaryReader br, byte op, out IBlueRow r)
{
if (op == StreamOpCode.add || op == StreamOpCode.change)
{
object[] retVal = new object[mySchema.columnInfo.Length];
foreach (ColumnInfo ci in mySchema.columnInfo)
retVal[ci.colNo] = myHelper.deserializeColumn (ci.colNo, br);
r = new BlueRow (mySchema, retVal);
}
else if (op == StreamOpCode.remove)
r = currentState[br.ReadInt32 ()];
else
{
// BlueEventLog.logAssert (false, op.ToString() + " not valid in this context");
r = null;
}
}
#endregion
}
}
@@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BCG
{
public class MarketOptionTheoClientDeserializer : ClientFixedDeserializer
{
public MarketOptionTheoClientDeserializer() { }
}
}
@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BCG
{
public class BBOOptionSerializer : FixedSerializer
{
public BBOOptionSerializer(IBlueTableSchema schema)
: base(schema, "BCG.BBOOptionPubsubDeserializer", "BCG.BBOOptionDeserializer")
{ }
}
}
@@ -1,35 +0,0 @@
using System;
using System.IO;
namespace BCG
{
/// <summary>
/// Optimized to serialize fixed length rows, ie schemas that have only primitive types and non-nulls
/// </summary>
public class FixedRowSerializer : IBlueRowSerializer
{
private PrimitiveSerializationHelper myHelper;
private int myIdColNo;
private IBlueTableSchema mySchema;
public FixedRowSerializer (IBlueTableSchema schema)
{
myIdColNo = schema["id"].colNo;
myHelper = new PrimitiveSerializationHelper (schema);
mySchema = schema;
}
#region IBlueRowSerializer Members
public void serializeRow (IBlueRow r, byte op, BinaryWriter bw)
{
if (op == StreamOpCode.remove)
myHelper.serializeColumn (r, myIdColNo, bw);
else
foreach (ColumnInfo ci in r.schema.columnInfo)
myHelper.serializeColumn (r, ci.colNo, bw);
}
#endregion
}
}
@@ -1,20 +0,0 @@
using System;
using System.IO;
namespace BCG
{
/// <summary>
/// Tailored to serialize tables that haved fixed schema (ie no dynamic length types like strings, arrays etc and no nulls)
/// </summary>
public abstract class FixedSerializer : BlueDataSerializer
{
public FixedSerializer (IBlueTableSchema schema,
string pubsubDeserializer,
string clientDeserializer)
: base (pubsubDeserializer, clientDeserializer)
{
myRowSerializer = new FixedRowSerializer (schema);
}
}
}
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BCG
{
public class MarketOptionTheoSerializer : FixedSerializer
{
public MarketOptionTheoSerializer(IBlueTableSchema schema)
: base(schema, "BCG.MarketOptionTheoPubsubDeserializer",
"BCG.MarketOptionTheoClientDeserializer")
{ }
}
}
@@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BCG
{
public class BBOOptionPubsubDeserializer : PubsubFixedDeserializer
{
public BBOOptionPubsubDeserializer() { }
}
}
@@ -1,12 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BCG
{
public class MarketOptionTheoPubsubDeserializer : PubsubFixedDeserializer
{
public MarketOptionTheoPubsubDeserializer()
{ }
}
}
@@ -1,32 +0,0 @@
using System;
using System.Collections;
using System.IO;
namespace BCG
{
public abstract class PubsubFixedDeserializer : PubsubDeserializer
{
protected BlueTable myCurrentState;
public PubsubFixedDeserializer () {}
protected override IDictionary myGetRows (BinaryReader br, byte op, int noOfRows)
{
if (myDeserializer == null)
myDeserializer = new PubsubFixedRowDeserializer (mySchema);
IDictionary retVal = new Hashtable ();
op = op == StreamOpCode.create ? StreamOpCode.add :
op == StreamOpCode.multipleChange ? StreamOpCode.change : op;
for (int i = 0; i < noOfRows; i++)
{
int id;
object row;
myDeserializer.deserializeRow (myState, br, op, out id, out row);
retVal.Add (id, row);
}
return retVal;
}
}
}
@@ -1,37 +0,0 @@
using System;
using System.IO;
using System.Collections;
namespace BCG
{
public class PubsubFixedRowDeserializer : IPubsubRowDeserializer
{
private int myRowSize, myIdOffset;
public PubsubFixedRowDeserializer (IBlueTableSchema schema)
{
foreach (ColumnInfo ci in schema.columnInfo)
{
myRowSize += SerializationUtilityMethods.getFixedLengthTypeSize (ci.colType);
myIdOffset += ci.colNo < schema["id"].colNo ? SerializationUtilityMethods.getFixedLengthTypeSize (ci.colType) : 0;
}
}
#region IPubsubRowDeserializer Members
public void deserializeRow (IDictionary currentState, BinaryReader br, byte op, out int id, out object row)
{
if (op == StreamOpCode.add || op == StreamOpCode.change)
{
row = br.ReadBytes (myRowSize);
id = BitConverter.ToInt32 (row as byte[], myIdOffset);
}
else //delete => only the id
{
id = br.ReadInt32 ();
row = currentState[id];
}
}
#endregion
}
}
@@ -1,56 +0,0 @@
using System;
using System.IO;
using System.Collections;
using BCG.Utilities;
namespace BCG
{
public abstract class ClientFixedChangingDeserializer : ClientDeserializer
{
private string [] myChangingCols;
protected BlueTable myCurrentState;
public ClientFixedChangingDeserializer (string[] changingCols)
{
myChangingCols = changingCols;
}
protected override IBlueRowCollection myGetRows (System.IO.BinaryReader br, byte op, int nRows)
{
BlueTable retVal = new BlueTable (mySchema);
op = op == StreamOpCode.create ? StreamOpCode.add :
op == StreamOpCode.multipleChange ? StreamOpCode.change : op;
if (myRowDeserializer == null)
{
myRowDeserializer = new ClientFixedChangingRowDeserializer (mySchema, myChangingCols);
myCurrentState = new BlueTable (mySchema);
}
for (int i = 0; i < nRows; i++)
{
IBlueRow r;
myRowDeserializer.deserializeRow (myCurrentState, br, op, out r);
retVal.addRow (r);
}
return retVal;
}
protected override void myEncorporateRows (IBlueRowCollection rows, byte op)
{
if (op == StreamOpCode.create)
myCurrentState = new BlueTable (rows);
else if (op == StreamOpCode.add)
myCurrentState.addRows (rows);
else if (op == StreamOpCode.remove)
myCurrentState.deleteRows (rows);
else if (op == StreamOpCode.change || op == StreamOpCode.multipleChange)
myCurrentState.changeRows (rows);
else
{
// BlueEventLog.logAssert (false, "Illegal operation for this context");
}
}
}
}
@@ -1,67 +0,0 @@
using System;
using System.Collections;
using System.IO;
using BCG.Utilities;
namespace BCG
{
/// <summary>
/// Deserializes a fixed length row with no nulls on the client side.
/// </summary>
public class ClientFixedChangingRowDeserializer : IClientRowDeserializer
{
private int[] myChangingColIndices;
protected PrimitiveDeserializationHelper myHelper;
protected IBlueTableSchema mySchema;
public ClientFixedChangingRowDeserializer (IBlueTableSchema schema, string[] changingCols)
{
myHelper = new PrimitiveDeserializationHelper (mySchema = schema);
myChangingColIndices = new int [changingCols.Length];
for (int i = 0; i < changingCols.Length; i++)
myChangingColIndices[i] = schema[changingCols[i]].colNo;
Array.Sort (myChangingColIndices);
}
public void deserializeRow (IBlueRowCollection currentState, BinaryReader br, byte op, out IBlueRow r)
{
if (op == StreamOpCode.add)
myDeserializeAdd (currentState, br, out r);
else if (op == StreamOpCode.remove)
myDeserializeRemove (currentState, br, out r);
else if (op == StreamOpCode.change)
myDeserializeChange (currentState, br, out r);
else
{
r = null;
// BlueEventLog.logAssert (false, "Illegal operation for this function, can only deal with single row " +
// "add, delete and change");
}
}
protected virtual void myDeserializeAdd (IBlueRowCollection currentState, BinaryReader br, out IBlueRow r)
{
object[] retVal = new object[mySchema.columnInfo.Length];
foreach (ColumnInfo ci in mySchema.columnInfo)
retVal[ci.colNo] = myHelper.deserializeColumn (ci.colNo, br);
r = new BlueRow (mySchema, retVal);
}
protected virtual void myDeserializeRemove (IBlueRowCollection currentState, BinaryReader br, out IBlueRow r)
{
r = currentState[br.ReadInt32()];
}
protected virtual void myDeserializeChange (IBlueRowCollection currentState, BinaryReader br, out IBlueRow r)
{
MutableBlueRow rv = new MutableBlueRow (currentState[br.ReadInt32 ()]);
foreach (int colNo in myChangingColIndices)
rv.setValue (colNo, myHelper.deserializeColumn (colNo, br));
r = rv;
}
}
}
@@ -1,90 +0,0 @@
using System;
using System.Collections;
using System.IO;
using BCG.Utilities;
namespace BCG
{
/// <summary>
/// Specializes in serializing rows that are sent over as a result of a change; only the changed columns are
/// sent together with the id.
/// </summary>
public class FixedChangingRowSerializer : IBlueRowSerializer
{
private int[] myChangingColIndices;
private PrimitiveSerializationHelper myHelper;
private IBlueTableSchema mySchema;
public FixedChangingRowSerializer (IBlueTableSchema schema, params string[] changingColumns)
{
myHelper = new PrimitiveSerializationHelper (schema);
myChangingColIndices = new int[changingColumns.Length];
for (int i = 0; i < changingColumns.Length; i++)
myChangingColIndices[i] = schema[changingColumns[i]].colNo;
Array.Sort (myChangingColIndices);
mySchema = schema;
}
#region IBlueRowSerializer Members
public void serializeRow (IBlueRow r, byte op, BinaryWriter bw)
{
if (op == StreamOpCode.add)
{
mySerializeAdd (r, bw);
}
else if (op == StreamOpCode.remove)
{
mySerializeRemove (r, bw);
}
else if (op == StreamOpCode.change)
{
mySerializeChange (r, bw);
}
else
{
// BlueEventLog.logAssert (false, String.Format ("{0} is not a valid op in this context", op));
}
}
#endregion
/// <summary>
/// The whole row is written, one column after the other with the order defined by the schema. There
/// are no columns headers
/// </summary>
/// <param name="r"></param>
/// <param name="bw"></param>
protected virtual void mySerializeAdd (IBlueRow r, BinaryWriter bw)
{
foreach (ColumnInfo ci in r.schema.columnInfo)
myHelper.serializeColumn (r, ci.colNo, bw);
}
/// <summary>
/// Only the id is written
/// </summary>
/// <param name="r"></param>
/// <param name="bw"></param>
protected virtual void mySerializeRemove (IBlueRow r, BinaryWriter bw)
{
myHelper.serializeColumn (r, r.schema["id"].colNo, bw);
}
/// <summary>
/// Serializes only the changed columns, alongside the id. So the format is
/// {id, changedColumns*}. The order of the changedColumns are sorted according
/// to their index in the schema.
/// </summary>
/// <param name="r"></param>
/// <param name="bw"></param>
protected virtual void mySerializeChange (IBlueRow r, BinaryWriter bw)
{
myHelper.serializeColumn (r, r.schema["id"].colNo, bw);
foreach (int colNo in myChangingColIndices)
myHelper.serializeColumn (r, colNo, bw);
}
}
}
@@ -1,110 +0,0 @@
using System;
using System.Collections;
using System.IO;
using BCG.Utilities;
namespace BCG
{
/// <summary>
/// Tailored to serialize tables that haved fixed schema (ie no dynamic length types like strings, arrays etc and no nulls)
/// and are constantly changing
/// </summary>
public abstract class FixedChangingSerializer : BlueDataSerializer
{
public FixedChangingSerializer (IBlueTableSchema schema,
string[] changingCols,
string pubsubDeserializer,
string clientDeserializer)
: base (pubsubDeserializer, clientDeserializer)
{
myRowSerializer = new FixedChangingRowSerializer (schema, changingCols);
}
}
#region BidAsk
public class BidAskSerializer : FixedChangingSerializer
{
public BidAskSerializer (IBlueTableSchema schema)
: base (schema,
new string[] {"bidAskZone"},
"BCG.BidAskPubsubDeserializer",
"BCG.BidAskClientDeserializer"
)
{}
}
public class BidAskPubsubDeserializer : PubsubFixedChangingDeserializer
{
public BidAskPubsubDeserializer () : base (new string[] {"bidAskZone"})
{}
}
public class BidAskClientDeserializer : ClientFixedChangingDeserializer
{
public BidAskClientDeserializer () : base (new string[] {"bidAskZone"})
{}
}
#endregion
#region HHMarketPrice
public class HHMarketPriceSerializer : FixedChangingSerializer
{
public HHMarketPriceSerializer(IBlueTableSchema schema)
: base(schema,
new string[] { "MarketPrice" },
"BCG.HHMarketPricePubsubDeserializer",
"BCG.HHMarketPriceClientDeserializer"
)
{ }
}
public class HHMarketPricePubsubDeserializer : PubsubFixedChangingDeserializer
{
public HHMarketPricePubsubDeserializer()
: base(new string[] { "MarketPrice" })
{ }
}
public class HHMarketPriceClientDeserializer : ClientFixedChangingDeserializer
{
public HHMarketPriceClientDeserializer()
: base(new string[] { "MarketPrice" })
{ }
}
#endregion
#region ThrottledMarketPrice
public class ThrottledPriceSerializer : FixedChangingSerializer
{
public ThrottledPriceSerializer(IBlueTableSchema schema)
: base(schema,
new string[] { "PRICE" },
"BCG.ThrottledPricePubsubDeserializer",
"BCG.ThrottledPriceClientDeserializer"
)
{ }
}
public class ThrottledPricePubsubDeserializer : PubsubFixedChangingDeserializer
{
public ThrottledPricePubsubDeserializer()
: base(new string[] { "PRICE" })
{ }
}
public class ThrottledPriceClientDeserializer : ClientFixedChangingDeserializer
{
public ThrottledPriceClientDeserializer()
: base(new string[] { "PRICE" })
{ }
}
#endregion
}
Loaded 100 of 241 files, more files were not shown because too many files have changed in this diff. Show more