Compare commits

...
159 Commits
Author SHA1 Message Date
arham 781fa97b55 Fix: changed polling from 100ms to 1ms, hardcoded 2026-05-08 14:55:03 +00:00
Taha fd50050064 Position cols in TC2 work again now 2026-05-07 03:57:07 +00:00
arham 6ac43881ae add: add missing tag to default conf 2026-05-07 00:22:28 +00:00
arham 4af1419748 Add: timezone change to chi and std higher ram for multicast compose 2026-05-07 00:22:03 +00:00
arham 7cfcdc3770 fix: ilink3 code generator produces correct code that handles null values 2026-05-07 00:21:10 +00:00
arham d03a705077 fix: ilink3 genereated files updated to handle null values with null instead of ascii zero 2026-05-07 00:20:34 +00:00
arham 58eccad70d fix: fills ui price was zero now it works 2026-05-07 00:19:44 +00:00
arham 5f8ec04ff1 Add: useful tools to prod docker image 2026-05-07 00:19:16 +00:00
arham 05e2107655 Fix: change object pool to detect exe report memory leak from assert to error 2026-05-07 00:18:45 +00:00
arham d41f613e32 FIx: change object pool limit for il3gw for exe reports 2026-05-07 00:17:52 +00:00
arham bcbb598423 Add: better logs and disconnect handling 2026-05-04 20:42:23 +00:00
arham e88c44f9db CME TEMPLATE 9 2026-05-04 16:39:48 -04:00
arham 93625957d1 Fix: CRITICAL CME FIX 2026-04-29 03:58:45 +00:00
John Colvin 8eccb869e1 Remove unnecessary nuget stuff from externals 2026-04-08 00:13:01 -04:00
John Colvin 40f4333fc7 fix: SingleSecurityCriteria must have single id or venue/name pair 2026-04-07 17:23:25 +00:00
John Colvin 319d5c2384 vscode: Fix PubSubServer config environment param 2026-04-07 17:23:25 +00:00
arham 4a74713369 ophir multicast config replay and live working 2026-04-02 00:17:46 +00:00
arham 082beef1da Rename 2026-03-31 23:59:04 +00:00
arham f92d789e90 Add: recording config 2026-03-31 14:16:55 +00:00
arham cd3e845dd9 Fix: set log to diag, it logs every book update 2026-03-31 14:09:37 +00:00
arham a5b704eef1 Add: config for ophir wb 2026-03-31 14:09:05 +00:00
arham afee63e061 Add: new docker compose to support mulitcast 2026-03-31 14:08:42 +00:00
John Colvin fc9356d1a0 deploy: Optionally mount sparkd entrypoint in config dir
To mount a custom entrypoint script, put it in the config profile dir
and define the following env vars:

    SPARKD__IMAGE=sparkd_symbols
    SPARKD__MAIN_ENTRYPOINT=/home/bts/.local/share/bts/sparkd/conf/<custom-entrypoint>

To invoke the "normal" sparkd entrypoint script from the mounted one:

    ./sparkd-entrypoint.sh
2026-03-27 18:28:25 +00:00
John Colvin a85f22c6a8 deploy: Fix sudo issues in sparkd-entrypoint.sh 2026-03-27 17:59:20 +00:00
John Colvin 2024eba4d0 deploy: Add ophir_sim_replay config profile for sparkd 2026-03-26 16:20:41 -04:00
John Colvin 1a49a828ad build: Don't activate venv when generating individual protos
We activate the venv for the whole build
2026-03-26 16:20:41 -04:00
John Colvin c0448c7c8d deploy: Resolve profile dirs with regex patterns 2026-03-26 16:20:41 -04:00
John Colvin a6c6e7faf3 improve: Wait until py work requested before loading py modules
So we don't crash due to missing py modules when no py plugins are running.
2026-03-26 16:20:41 -04:00
John Colvin 56445d2d66 deploy: Add sparkd-shell service to compose.yaml for troubleshooting 2026-03-26 16:20:41 -04:00
John Colvin ccf1bd51c2 cleanup: Remove unused code 2026-03-26 16:20:41 -04:00
John Colvin fd21269df7 refactor: Wrap md run logic in class MarketDataSession
Start in the constructor, gracefully exit in the destructor.
2026-03-26 16:20:41 -04:00
John Colvin fe85c3e648 Allow md recording dir to be mounted as volume in docker compose 2026-03-26 16:20:41 -04:00
John Colvin e1d33ecadf deploy: Configure timezone in entrypoint script 2026-03-26 16:20:41 -04:00
John Colvin 83df96c70f deploy: Move compose entrypoint to dedicated script 2026-03-26 16:20:41 -04:00
John Colvin f718f5b15c deploy: Fix typo in sparkd conf dir path in compose.yaml 2026-03-26 16:20:41 -04:00
John Colvin 5d752f3b73 refactor: Replace DataPacket with IDataPacket in more places 2026-03-26 16:20:40 -04:00
John Colvin d308dbf15a build: Check if venv already active before activating 2026-03-26 16:20:40 -04:00
John Colvin 21c43b9240 refactor: Replace TableFormatter with table.h
Also move to "format" dir
2026-03-26 16:20:40 -04:00
John Colvin e1553f1b04 refactor: Replace StringFinder/Joiner.h with find/join.h
Also move to "algorithm" dir
2026-03-26 16:20:40 -04:00
John Colvin a26918efe9 refactor: Rename a few TitleCase .h files snake_case
* EnumMacros.h -> enum_macros.h
* TimeSpan.h ---> time_span.h
* TimeStamp.h --> time_stamp.h
2026-03-26 16:20:40 -04:00
John Colvin f729fc4c59 diag: Use structured logs in MDP3Listener::onOption 2026-03-26 16:20:40 -04:00
John Colvin fa67adbe36 deploy: Install tzdata in linux_dotnet8 Dockerfile
So we can configure timezone in compose services. Specifically, we need this
to support live cme md (so onixs doesn't think messages are "too old").
2026-03-26 16:20:40 -04:00
John Colvin 72f9ec582e cleanup: Remove unused code 2026-03-26 16:20:40 -04:00
John Colvin 8fea31bdf6 refactor: Add new glbx variable ticks to security (shm and proto) 2026-03-26 16:20:39 -04:00
John Colvin ca96e41391 build: Upgrade cs LangVersion 11 -> 12 2026-03-26 16:20:39 -04:00
John Colvin d4e5c95fde refactor: Rename SparkApiCredentials -> SparkCredentials 2026-03-26 16:20:39 -04:00
John Colvin f6e0ec3617 refactor: Rename SparkdLoginService -> SparkLoginService
This makes it consistent with other type names (we don't use "Sparkd"
anywhere else).
2026-03-26 16:20:39 -04:00
John Colvin 3fa5284838 refactor: Rename SparkdCredentials.cs -> SparkApiCredentials.cs
Matches the class name
2026-03-26 16:20:39 -04:00
John Colvin 4dcaa565f6 cleanup: Remove unnecessary subscription wrapper in cs sdk 2026-03-26 16:20:39 -04:00
John Colvin 75ecfa89d6 build: Clean up spark_client.sln
* Remove unused csprojs related to old sdk
* Remove erroneous build type config
2026-03-26 16:20:39 -04:00
John Colvin 1c930439a4 fix build (dsqa): Add using Spark.Api.MarketData
Needed to reference IMarketDataClient
2026-03-26 16:19:30 -04:00
John Colvin 25084b8cd9 fix build (cs): Add "global::" prefix when using Spark.Api ns
Resolves conflicts with the Bts.Spark.Api namespace when the using
statement is nested inside the root "Bts" namespace.
2026-03-26 16:17:16 -04:00
John Colvin 5b8a8a8882 build: Simplify target to include native assets in cs 2026-03-08 16:00:49 +00:00
John Colvin 21052090a2 fix (pre-emptive): Format dotnet flag opts correctly
In pack_spark_sdk.py, the dotnet pack cmd is constructed with a dict of
opts. If the value part is None, the opt should be formatted as a flag,
"--key" instead of "--key None".
2026-03-07 13:32:03 -05:00
John Colvin 9bd32b8225 fix build (pack cs sdk): Fix --(no-)cs toggle behavior
* Always run "dotnet pack", regardless of csharp toggle opt
* Run "dotnet publish" if csharp toggled on
2026-03-07 13:20:56 -05:00
John Colvin e8e234f420 fix: Don't fire empty updates in Books IObservable 2026-03-07 01:19:38 -05:00
John Colvin be23237a45 fix: Update last val in IObservable FlattenSeries ext
The bootstrap delegate that stitches the sequences together wasn't
getting properly invoked because of this.
2026-03-07 01:19:28 -05:00
arham a9d92650f8 Add: Spread name to synthspreadbbo 2026-03-03 04:33:44 +00:00
arham c03fb13126 Fix: rename EnterSpreaderOrderAsync from CreateSynthAsync 2026-03-03 01:16:10 +00:00
arham 01e6e37db6 Add: Config for ophir live data sim exe 2026-03-03 01:10:34 +00:00
arham 786b0849a7 FIX: removed errenous code that stopped mdp3 from working 2026-03-03 01:09:06 +00:00
John Colvin 4826fc9237 build: Remove dependency on Newtonsoft.Json (in DataStreamCore)
Replace with System.Text.Json (official dotnet)
2026-02-23 13:03:49 -05:00
John Colvin c3341ec29f refactor: Replace a few more DataPacket refs with IDataPacket 2026-02-23 12:56:27 -05:00
John Colvin eb88052c7e chore: Add Metadata prop to IDataPacket
To give it parity with DataPacket
2026-02-23 12:55:23 -05:00
John Colvin 74332f9944 fix: Pass IMarketDataClient to PrimitiveManager to enable md streams
In DataStreamQueryAnalyzer and Spark Api Server
2026-02-23 11:24:33 -05:00
John Colvin 54c97b5610 fix: Set buffer Position to 0 when deserializing pubsub echo payload 2026-02-21 16:36:53 -05:00
John Colvin 5c05afd9b3 fix: Only fire stream update if there are actually changes
In other words, don't fire if addedRows and deletedRows are both empty.
2026-02-21 16:36:53 -05:00
John Colvin dcbba39e4a fix: Add null check in BlueDataUtility.build_dp_inc 2026-02-21 16:36:53 -05:00
John Colvin d09f22007e fix: Ensure PubSubTagHandlerFactory uses correct config
* Add this service as part of the PubSubClient services for dep
  injection (it is needed by PublisherCore)

* Get rid of PublisherCore's default constructor, so dep injection
  treats the tag handler factory as a required param (fails if it isn't
  available)
  - Replace the default ctr with a static "Create" fn, so code that
    hasn't been updated to use dependency injection can still use that.
  - Use PubSubConfig.Instance (runtime) instead of compile time Default

* Fix compile time Default config
  - In fallback handler config, change Tag from "" to ".*" and move it
    from the beginning of the list to the end (it should be the last
    resort, not the other way around).
2026-02-21 16:36:53 -05:00
John Colvin a07e7ea6b8 fix: Don't call MasterWorker/vsd doWork on DSQA ui thread
Now that we use dependency injection, this is handled by a dedicated
service (MasterWorkerService). As a side effect, stream updates aren't
necessarily fired on the ui thread, so we refresh the grid on a form
timer callback.
2026-02-21 16:36:47 -05:00
John Colvin 4da52ff724 fix: Replace DataPacket w/ IDataPacket in DSQA 2026-02-21 14:49:39 -05:00
John Colvin 05c7a32fc5 refactor: Add parameterless ctr to PubsubEchoTestStream
So it's quick/easy to check in DSQA (less typing required)
2026-02-21 14:23:51 -05:00
John Colvin 404d3073f9 ui: Unhide PubsubHeartbeatStream (pss_hb) from DSQA 2026-02-21 14:11:46 -05:00
John Colvin 7f1154d70c cleanup: Fix indentation in PubsubHeartbeatStream.cs 2026-02-21 14:10:11 -05:00
John Colvin 5bc2e29096 fix build: Only check "dsqa" flag when building on windows
The --dsqa opt isn't defined when running on linux.
2026-02-21 17:55:12 +00:00
John Colvin f5731a184c fix: Actually disable Spark in default DSQA config 2026-02-20 11:08:33 -05:00
John Colvin 120fe8e5c6 vscode: Add DSQA debug config to skip build 2026-02-20 10:44:19 -05:00
John Colvin 137fdc537d refactor: Move DSQA config to appsettings.json 2026-02-20 10:43:13 -05:00
John Colvin a605e57bee build: Add dsqa toggle to build_data_stream.py
Windows only
2026-02-20 02:33:38 -05:00
John Colvin 3ca4bf784c ui: Remove bts.BlueOrb namespace filter for DSQA streams 2026-02-20 02:13:17 -05:00
John Colvin 6c3b7ebdaf refactor: Use dependency injection in DSQA 2026-02-20 02:13:17 -05:00
John Colvin 2fbb6fe563 Disable Spark in default DSQA config 2026-02-20 02:13:17 -05:00
John Colvin 9ea33ac110 ui: Unhide PubSubServerStateStream (pss_state) from DSQA 2026-02-20 02:13:17 -05:00
John Colvin 0bc021912a fix: Replace more DataPacket references with IDataPacket 2026-02-20 02:13:17 -05:00
John Colvin fa017bd9ff fix build: Remove old ViewStream.rows references from dsqa
The 'rows' prop no longer exists
2026-02-20 02:13:17 -05:00
John Colvin 57b59215e6 fix build: Don't echo parenthesis in .cmd if block
It's not allowed (because windows).
2026-02-18 02:54:25 -05:00
arham 210768e391 fix: handle badrequests in websocket api 2026-02-18 05:40:27 +00:00
arham f01e8a578d Add: enter synthetic spreader orders through 2026-02-18 05:36:02 +00:00
arham 528a00cf98 Add: config for okx_bin_sim 2026-02-18 05:31:18 +00:00
arham 96a04a7c84 Fix: side and status to json in orderrecodtuple 2026-02-18 05:30:28 +00:00
arham abaf48beb4 Add: other fields to tosjon for security.cs 2026-02-18 05:29:03 +00:00
John Colvin 08fcae94c0 Update externals (moved emumba deribit deb to bitbucket cloud) 2026-02-17 18:16:22 +00:00
John Colvin 30814a2ed6 fix build: Fix Bts.Extensions.Hosting projref path 2026-02-15 16:48:02 +00:00
John Colvin 3c61de5f13 devcontainer: Install Rakurai deb
Download from bitbucket cloud.
2026-02-14 18:43:07 +00:00
John Colvin 771c58d4ad devcontainer: Move emumba deb to bitbucket cloud
I just learned that Bitbucket offers per-repo cloud storage for arbitary
files (the "Downloads" section on the web gui). Doing this before adding
another third-party deb to our build (rakurai), which is quite large at
140MB. We don't want to pack that into our repo.
2026-02-14 18:42:03 +00:00
John Colvin 5db5d40a99 devcontainer: Fix CMake NO_PUBLIC_KEY warning 2026-02-14 18:29:28 +00:00
John Colvin 020ec9c6bf build: Replace proj refs w/ internal nugets when packing 2026-02-03 16:57:32 +00:00
John Colvin 4e28835bbd vscode: Add tools/py to shell PYTHONPATH 2026-02-03 16:57:32 +00:00
John Colvin 6985fbb090 refactor: Move CompressionUtilities into separate csproj
It was nested in PubSub. The new csproj is named Bts.IO.Compression.
2026-02-03 16:57:32 +00:00
John Colvin 2f42311220 build: Update a few python packages
* protobuf         4.21.12 -> 6.33.4
* pybind11         2.13.6 --> 3.0.1
* pybind11-stubgen 2.5.3 ---> 2.5.5
2026-02-03 16:57:32 +00:00
John Colvin 3842efcef1 build: Define build py requirements in separate files
No need to install backend build deps when building the front-end, and
vice versa. The build scripts (build_spark.cmd, build_sparkd.sh, etc.)
automatically install only the necessary requirements now.

Note: We'll keep the monolith requirements.txt file around (at least for
now), as it includes more than just build deps (e.g., numpy, pandas, and
jupyter for data analysis; pybit for bybit plugins, etc.).
2026-02-03 16:57:32 +00:00
John Colvin 635107eb68 cleanup: Remove unused py code 2026-02-03 05:20:29 +00:00
John Colvin 1b9a49b924 cleanup: Add missing files and env vars to sparkd config profiles 2026-02-03 05:20:29 +00:00
John Colvin ead35389d5 build: Make PubSub packable 2026-02-03 05:20:29 +00:00
John Colvin 22b44845fb build: Update Microsoft.AspNetCore.Cors to 2.3.9 2026-02-03 05:20:29 +00:00
John Colvin 8ab26f3e1d build: Remove dependency on Newtonsoft.Json
Replace with System.Text.Json (official dotnet)
2026-02-03 05:16:21 +00:00
John Colvin 01c61bb16d fix build: Publish spark_api_server csproj instead of the sln
There's a version conflict with System.Data.Common when publishing the sln.
2026-01-22 05:50:49 +00:00
John Colvin e09e49ce56 fix build: Add Bts.Net to Spark.Api.Server.sln
It seems like the dep is automatically detected on windows, but not
linux (so we need to add it explicitly).
2026-01-21 15:06:00 -05:00
John Colvin e6cc20858b build: Honor "UseProjectRefs" in spark_websocket, spark_api_server 2026-01-21 14:28:48 -05:00
John Colvin 2eb80082d8 refactor: Move Bts.Extensions.Hosting, Bts.Net to cs dir
They aren't exclusively used by DataStream csprojs
2026-01-21 14:20:39 -05:00
John Colvin d55ef854ba fix build: Don't actually copy files when building with --dry-run 2026-01-21 14:03:01 -05:00
John Colvin b1417ece5d fix build: Fix cmake windows preset in publish_api_server.py
Changed from 'spark' -> 'spark-windows'
2026-01-21 14:03:01 -05:00
John Colvin f6ae219a72 build: Add a few toggle opts to publish py scripts
--(no-)cpp           Enable/disable cpp build
--(no-)cs            Enable/disable csharp build
--(no-)csproj-refs   Depend on csproj refs, or locally built nugets
2026-01-21 14:03:01 -05:00
John Colvin 1e4b9cf833 Add new StartWithOnTimeout ext fn for IObservable
Ophir wanted this functionality for data in the sdk
2026-01-19 10:44:51 -05:00
John Colvin 228931dd2a cleanup: Fix indentation in launch.json
Also rename launch task "(gdb) Attach" -> "Sparkd Attach"
2026-01-19 10:44:51 -05:00
John Colvin f5b4b36ea1 Move devcontainer Dockerfile to bluetradingsystems/linux_dotnet8_dev
We now host it on dockerhub under that name
2026-01-19 10:44:51 -05:00
arham f19d2d695b Fix: Updated path so that profiles work 2026-01-16 06:55:09 +00:00
John Colvin d4b9b6bcba fix: Dispose subscription in TopOfBookQuoter demo 2026-01-14 10:35:42 -05:00
John Colvin 84d74a7873 refactor: Actually implement IDisposable in MarketDataClient 2026-01-14 10:35:42 -05:00
John Colvin 8c34280d75 fix: Init PriceTicker Security to avoid null ref in Equals impl 2026-01-14 10:35:42 -05:00
John Colvin 474d96ced4 feat: Add PriceStats/Ticker to ISimpleSparkClient (cs sdk) 2026-01-14 10:35:42 -05:00
John Colvin 1432692a26 refactor: Make PriceStats/Ticker record structs
Also rename props in PascalCase
2026-01-13 13:57:47 -05:00
arham 1dde5c3ac2 add: trades aggressor side works in the recorder 2026-01-13 18:25:56 +00:00
arham 1cc31e0d2d add: databento datahandler reads cme recorded files with time delay 2026-01-13 18:00:43 +00:00
arham edbd0d2a7b add: conf for es weekly 2026-01-13 17:59:25 +00:00
arham 56a4ec94a2 Fix: glbx config to use databento as marketdata src 2026-01-13 17:55:13 +00:00
arham e3e3d42972 fix: removed double call to std::move 2026-01-13 17:52:16 +00:00
arham 1b9dff3a83 Add: low tick high tick to genereal marketdata listener 2026-01-13 17:51:43 +00:00
John Colvin 8521a98445 ui: Add Tag column to OrderBook window 2026-01-12 10:45:00 -05:00
John Colvin 10eb1ecf1e feat: Add order tag param to ISimpleSparkClient (cs sdk) 2026-01-12 10:44:59 -05:00
John Colvin 88beb0f148 fix: Avoid null ref ex in DiffStream 2026-01-11 15:15:13 -05:00
John Colvin 0f70ae5da2 fix: Fix 'future' -> 'spread' typo in LiveFuturesContractStream 2026-01-11 15:15:13 -05:00
John Colvin bcd207f89e cleanup: Fix more build warnings in DataStreamSuite
Alot more
2026-01-11 15:15:13 -05:00
John Colvin 989d103eef fix: Properly store and dispose md subscription in BBOStream 2026-01-11 15:15:12 -05:00
John Colvin aacd22d496 refactor: Move Exception utils to Spark.Core.Diagnostics ns 2026-01-11 15:15:12 -05:00
John Colvin 5d318b6422 refactor: Rename PropertyNotNull -> MemberNotNull
Because it can be used to null check any member (including fields and
method returns), not just properties.
2026-01-11 15:15:11 -05:00
John Colvin d89164c0ff refactor: Move CollectionExtensions to Spark.Core.Collections namespace 2026-01-11 15:12:33 -05:00
John Colvin cbddb3ae28 fix: Avoid potential race bug in c# OrderPool 2026-01-11 11:20:40 -05:00
John Colvin 2aa25d4085 refactor: Rename ExceptionAssert.not_null -> NotNull 2026-01-11 11:20:40 -05:00
John Colvin cd34f9b1cb cleanup: Tidy up SecondStream, move ThrottleStream to own file
There actually already was a file called "ThrottleStream", but since it
didn't have the ".cs" extension it wasn't getting built.
2026-01-11 11:20:40 -05:00
John Colvin 5f689dbd8e cleanup: Tidy whitespace and using statements 2026-01-11 11:20:40 -05:00
John Colvin 03a8f4e9c0 refactor: Replace DataPacket w/ IDataPacket in many places 2026-01-11 11:20:40 -05:00
John Colvin 49a952fb32 refactor: Generate a few row types with new t4 templates
* PubSubHeartbeatRow
* PubSubRouteRow
* PubSubServerStateRow
* PubSubServerTagStatsRow
* TableMetadataRow
2026-01-10 12:59:14 -05:00
John Colvin a1c6e0ccab build: Add t4 templates to generate c# row types
Produces classes/structs that implement IBlueRow with strongly typed
properties for each column.
2026-01-10 12:59:14 -05:00
John Colvin 63a3eb968c diag: Assert DataStream updates are incremental
In debug builds
2026-01-10 12:59:14 -05:00
John Colvin 9de4b27003 refactor: Ensure stream subscriptions only disposed once
In the debugger, I noticed a few streams were unhooking their internal
onChange callbacks unnecessarily (when they were already unhooked).
2026-01-10 12:59:14 -05:00
John Colvin 849c6c28e5 fix: Don't fire empty updates in MutableAppendStream 2026-01-10 12:59:14 -05:00
John Colvin bf3a8f076f fix: Change DSQA config pubsub port to 22019
The port PubSubServer runs on by default
2026-01-10 12:59:14 -05:00
John Colvin 44749739b9 build: Define centralized SparkVersion prop
All csprojs should be on the same version. At the very least, it
is a sensible default.
2026-01-10 12:59:14 -05:00
John Colvin ddf16bcd5c fix: Add missing LiveMarketDataStream attribute to InstrumentsStream
Otherwise PrimitiveManager returns null for that stream type
2026-01-10 12:59:14 -05:00
John Colvin cfe7d43770 fix: Initialize ViewStreamDatabase.instance in DSQA 2026-01-10 12:59:14 -05:00
John Colvin bb5ea19f69 refactor: Get rid of ViewStream.rows prop
It was causing weird side effects in debugger
2026-01-10 12:59:14 -05:00
John Colvin 327665b4c3 fix: Add null check in ProximityJoinStream 2026-01-08 14:24:27 -05:00
John Colvin 2843638386 fix: Only start Stopwatch when actually doing work 2026-01-08 14:24:27 -05:00
John Colvin 915322927a fix: Dispose md subscription in InstrumentsStream 2026-01-08 14:23:09 -05:00
John Colvin 9905216131 fix: Format PubSub and DSQA config json in PascalCase
Matches what's in appsettings.json files
2026-01-08 14:22:57 -05:00
John Colvin f88915a940 fix build: Add --spark-version opt in build_data_stream.py 2026-01-07 02:34:56 -05:00
John Colvin c5ea913e27 fix: Shutdown application when user closes login dialog
Previously, it would hang until you manually killed the process.
2026-01-06 14:02:10 -05:00
John Colvin 7719aaa2b3 fix: Add EnvironmentVariables config provider to HostBuilder 2026-01-06 14:02:10 -05:00
786 changed files with 23227 additions and 5214 deletions

No files matched your search

+6
View File
@@ -25,6 +25,12 @@
"commands": [
"fake"
]
},
"dotnet-t4": {
"version": "3.0.0",
"commands": [
"t4"
]
}
}
}
+7 -1
View File
@@ -1,5 +1,11 @@
{
"dockerFile": "Dockerfile",
"build": {
"dockerfile": "../docker/images/bluetradingsystems/linux_dotnet8_dev/Dockerfile",
"options": [
"--secret",
"id=bitbucket_access_token,src=${localWorkspaceFolder}/.secrets/bitbucket_access_token.txt"
]
},
"hostRequirements": {
"memory": "8gb",
"storage": "10gb"
@@ -1,4 +0,0 @@
#!/usr/bin/env bash
this_dir="$(realpath "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")")"
sudo dpkg -i "$this_dir/emumba-deribit-connector-3.3.1-Linux.LICENSE_DISABLED.deb"
+8
View File
@@ -29,6 +29,9 @@
# tools/deploy.sh --help
#
### Host/Runtime ###
TZ=Etc/UTC
### Sparkd ###
# The internal image for sparkd to use. For more info, view:
# src/server/sparkd/Dockerfile
@@ -38,6 +41,9 @@ SPARKD__CONFIG_DIR=src/app_sparkd/configurations/dev
# Mount a specific volume or dir to "~/sparkdata/data" inside the docker.
# Defaults to a volume named "sparkd_<config_port>" (e.g., sparkd_8000).
# SPARKD__DATA_DIR=/home/bts/sparkdata/data
# Mount volume or dir to "/md_recording" inside the docker. Defaults to volume
# "sparkd_md_recording_<config_port>" (e.g., sparkd_md_recording_8000).
# SPARKD__MD_RECORDING_DIR=/home/bts/md_recording
SPARKD__SOURCE_DIR=install/sparkd-release-gcc
SPARKD__RUNTIME_CONF_DIR=/home/ubuntu/8000/sparkdata/conf/
SPARKD__CONFIG_PORT=8000
@@ -45,6 +51,8 @@ SPARKD__QUICKBUS_PORT=8001
SPARKD__SIM_FIX_PORT=8002
SPARKD__SHM_SIZE=4gb
SPARKD__PYTHON_REQUIREMENTS=requirements.txt
SPARKD__SPARKD_ENTRYPOINT=src/app_sparkd/sparkd-entrypoint.sh
SPARKD__MAIN_ENTRYPOINT=./sparkd-entrypoint.sh
### PubSubServer ###
PUBSUB__CONFIG_DIR=src/DataStreamSuite/PubSubServer/Configurations/Development
+57 -15
View File
@@ -142,17 +142,30 @@
"name": "DataStreamQueryAnalyzer",
"type": "coreclr",
"request": "launch",
//"preLaunchTask": "Build DataStreamQueryAnalyzer (Debug)",
"preLaunchTask": "Build DataStream (Debug)",
"program": "",
"windows": {
"program": "DataStreamQueryAnalyzer.exe",
"args": [
"--config",
"${workspaceFolder}/src/DataStreamSuite/DataStreamQueryAnalyzer/Configurations/DataStreamQueryAnalyzer.json"
],
"cwd": "build/Debug/bin/net8.0-windows",
"env": {
"PYTHON_EXE": "${workspaceFolder}/.venv/Scripts/python.exe"
"PYTHON_EXE": "${workspaceFolder}/.venv/Scripts/python.exe",
"DOTNET_ENVIRONMENT": "${input:dataStreamQueryAnalyzerEnvironment}",
},
},
"stopAtEntry": false,
"console": "integratedTerminal",
},
{
"name": "DataStreamQueryAnalyzer (Skip Build)",
"type": "coreclr",
"request": "launch",
"program": "",
"windows": {
"program": "DataStreamQueryAnalyzer.exe",
"cwd": "build/Debug/bin/net8.0-windows",
"env": {
"PYTHON_EXE": "${workspaceFolder}/.venv/Scripts/python.exe",
"DOTNET_ENVIRONMENT": "${input:dataStreamQueryAnalyzerEnvironment}",
},
},
"stopAtEntry": false,
@@ -170,11 +183,10 @@
"windows": {
"program": "PubSubServer.exe",
},
"args": [
"--config",
"${workspaceFolder}/src/DataStreamSuite/PubSubServer/Configurations/${input:pubSubServerConfig}.json"
],
"cwd": "build/Debug/bin/net8.0",
"env": {
"DOTNET_ENVIRONMENT": "${input:pubSubServerEnvironment}",
},
"stopAtEntry": false,
"console": "integratedTerminal"
},
@@ -371,6 +383,25 @@
}
]
},
{
"name": "Sparkd Attach",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/build/sparkd-debug-clang/src/app_sparkd/sparkd",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
],
"inputs": [
{
@@ -396,6 +427,16 @@
],
"default": "MarketDataPublisher",
},
{
"id": "dataStreamQueryAnalyzerEnvironment",
"type": "pickString",
"description": "DataStreamQueryAnalyzer Configuration",
"options": [
"Development",
"Local",
],
"default": "Development",
},
{
"id": "dataStreamPublisherEnvironment",
"type": "pickString",
@@ -407,14 +448,15 @@
"default": "Local",
},
{
"id": "pubSubServerConfig",
"id": "pubSubServerEnvironment",
"type": "pickString",
"description": "PubSub Configuration",
"description": "PubSubServer Configuration",
"options": [
"PubSubServer",
"SimpleEchoClient",
"Development",
"EchoServer",
"Local",
],
"default": "PubSubServer",
"default": "Development",
},
{
"id": "sdkDemoEnvironment",
+1 -1
View File
@@ -1 +1 @@
PYTHONPATH=/workspaces/spark/build/sparkd-debug-clang/src/lib_python_interop;/workspaces/spark/src/lib_python_interop/python_interop_plugins
PYTHONPATH=/workspaces/spark/build/sparkd-debug-clang/src/lib_python_interop;/workspaces/spark/src/lib_python_interop/python_interop_plugins;/workspaces/spark/tools/py
+22 -15
View File
@@ -541,12 +541,11 @@
"command": "",
"windows": {
"command": "DataStreamQueryAnalyzer.exe",
"args": [
"--config",
"${workspaceFolder}/src/DataStreamSuite/DataStreamQueryAnalyzer/Configurations/DataStreamQueryAnalyzer.json",
],
"options": {
"cwd": "${workspaceFolder}/build/${input:buildConfiguration}/bin/net8.0-windows"
"cwd": "${workspaceFolder}/build/${input:buildConfiguration}/bin/net8.0-windows",
"env": {
"DOTNET_ENVIRONMENT": "${input:dataStreamQueryAnalyzerEnvironment}",
},
},
},
"icon": {
@@ -561,12 +560,11 @@
"command": "",
"windows": {
"command": "DataStreamQueryAnalyzer.exe",
"args": [
"--config",
"${workspaceFolder}/src/DataStreamSuite/DataStreamQueryAnalyzer/Configurations/DataStreamQueryAnalyzer.json",
],
"options": {
"cwd": "${workspaceFolder}/build/Debug/bin/net8.0-windows"
"cwd": "${workspaceFolder}/build/Debug/bin/net8.0-windows",
"env": {
"DOTNET_ENVIRONMENT": "${input:dataStreamQueryAnalyzerEnvironment}",
},
},
},
"icon": {
@@ -581,12 +579,11 @@
"command": "",
"windows": {
"command": "DataStreamQueryAnalyzer.exe",
"args": [
"--config",
"${workspaceFolder}/src/DataStreamSuite/DataStreamQueryAnalyzer/Configurations/DataStreamQueryAnalyzer.json",
],
"options": {
"cwd": "${workspaceFolder}/build/Release/bin/net8.0-windows"
"cwd": "${workspaceFolder}/build/Release/bin/net8.0-windows",
"env": {
"DOTNET_ENVIRONMENT": "${input:dataStreamQueryAnalyzerEnvironment}",
},
},
},
"icon": {
@@ -1048,6 +1045,16 @@
],
"default": "Debug",
},
{
"id": "dataStreamQueryAnalyzerEnvironment",
"type": "pickString",
"description": "DataStreamQueryAnalyzer Configuration",
"options": [
"Development",
"Local",
],
"default": "Development",
},
{
"id": "sparkdCmakePreset",
"type": "pickString",
+2 -5
View File
@@ -11,9 +11,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Spark.Core", "src\cs\Bt
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Spark.Api", "src\cs\Bts.Spark.Api\Bts.Spark.Api.csproj", "{8949AF88-F1D3-4BC4-827F-B088B555F7B9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataStreamSuite", "DataStreamSuite", "{60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Extensions.Hosting", "src\DataStreamSuite\Bts.Extensions.Hosting\Bts.Extensions.Hosting.csproj", "{37E4E890-D025-4729-90F9-6F95862F47BC}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Extensions.Hosting", "src\cs\Bts.Extensions.Hosting\Bts.Extensions.Hosting.csproj", "{37E4E890-D025-4729-90F9-6F95862F47BC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Spark.Sdk", "src\cs\Bts.Spark.Sdk\Bts.Spark.Sdk.csproj", "{A5FF3FAF-43CB-496B-AF4B-F61EFD645579}"
EndProject
@@ -97,8 +95,7 @@ Global
{C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{E3BF9514-CB1A-4E07-A8DD-73300FD9726C} = {C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295}
{8949AF88-F1D3-4BC4-827F-B088B555F7B9} = {C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295}
{60E0D592-FFB3-0D0A-C4AA-E88919B48F9D} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{37E4E890-D025-4729-90F9-6F95862F47BC} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{37E4E890-D025-4729-90F9-6F95862F47BC} = {C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295}
{A5FF3FAF-43CB-496B-AF4B-F61EFD645579} = {C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295}
{FCFDBDBE-74B0-41C4-9011-C651B21056D4} = {C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295}
EndGlobalSection
+58 -2
View File
@@ -43,7 +43,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.ColumnExpressions", "sr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStream", "src\DataStreamSuite\DataStream\DataStream.csproj", "{39AEA075-6457-46C0-8821-1158BE6EFA57}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Extensions.Hosting", "src\DataStreamSuite\Bts.Extensions.Hosting\Bts.Extensions.Hosting.csproj", "{F3DC52D7-8C59-4EC0-86D9-0E5732EAFCF7}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Extensions.Hosting", "src\cs\Bts.Extensions.Hosting\Bts.Extensions.Hosting.csproj", "{F3DC52D7-8C59-4EC0-86D9-0E5732EAFCF7}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cs", "cs", "{385C4948-E080-56A6-E29E-8B0F4913175C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Net", "src\cs\Bts.Net\Bts.Net.csproj", "{43FB297B-7A4D-4835-A878-E6DF345B580C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.IO.Compression", "src\cs\Bts.IO.Compression\Bts.IO.Compression.csproj", "{BC277499-8215-4F9F-B9AB-07B6391110BF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -517,6 +523,54 @@ Global
{F3DC52D7-8C59-4EC0-86D9-0E5732EAFCF7}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU
{F3DC52D7-8C59-4EC0-86D9-0E5732EAFCF7}.RelWithDebInfo|x86.ActiveCfg = Debug|Any CPU
{F3DC52D7-8C59-4EC0-86D9-0E5732EAFCF7}.RelWithDebInfo|x86.Build.0 = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Debug|x64.ActiveCfg = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Debug|x64.Build.0 = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Debug|x86.ActiveCfg = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Debug|x86.Build.0 = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.MinSizeRel|x86.Build.0 = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Release|x64.ActiveCfg = Release|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Release|x64.Build.0 = Release|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Release|Any CPU.Build.0 = Release|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Release|x86.ActiveCfg = Release|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.Release|x86.Build.0 = Release|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.RelWithDebInfo|x86.ActiveCfg = Debug|Any CPU
{43FB297B-7A4D-4835-A878-E6DF345B580C}.RelWithDebInfo|x86.Build.0 = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Debug|x64.ActiveCfg = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Debug|x64.Build.0 = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Debug|x86.ActiveCfg = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Debug|x86.Build.0 = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.MinSizeRel|x86.Build.0 = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Release|x64.ActiveCfg = Release|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Release|x64.Build.0 = Release|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Release|Any CPU.Build.0 = Release|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Release|x86.ActiveCfg = Release|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.Release|x86.Build.0 = Release|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.RelWithDebInfo|x86.ActiveCfg = Debug|Any CPU
{BC277499-8215-4F9F-B9AB-07B6391110BF}.RelWithDebInfo|x86.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -535,7 +589,9 @@ Global
{9F6D7DE8-185B-4C1D-B809-3314D092DF28} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
{6BD3F6D8-B6FC-44E8-B8FE-06352F638B9B} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
{39AEA075-6457-46C0-8821-1158BE6EFA57} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
{F3DC52D7-8C59-4EC0-86D9-0E5732EAFCF7} = {C09ED521-D2DF-40BC-A76F-EB3CB870B2F6}
{385C4948-E080-56A6-E29E-8B0F4913175C} = {267F81EF-A8AB-49FD-9F56-D7EC3C1F7C7C}
{43FB297B-7A4D-4835-A878-E6DF345B580C} = {385C4948-E080-56A6-E29E-8B0F4913175C}
{BC277499-8215-4F9F-B9AB-07B6391110BF} = {385C4948-E080-56A6-E29E-8B0F4913175C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {422D1620-0166-4C26-9A81-CA8A2EB1AB58}
+63 -37
View File
@@ -2,6 +2,7 @@ services:
sparkd:
volumes:
- ${SPARKD__DATA_DIR:-sparkd_data}:/home/bts/.local/share/bts/sparkd/data
- ${SPARKD__MD_RECORDING_DIR:-md_recording}:/md_recording
build:
dockerfile: src/app_sparkd/Dockerfile
args:
@@ -9,24 +10,35 @@ services:
- SOURCE_DIR=${SPARKD__SOURCE_DIR}
- CONFIG_DIR=${SPARKD__CONFIG_DIR}
- PYTHON_REQUIREMENTS=${SPARKD__PYTHON_REQUIREMENTS}
- SPARKD_ENTRYPOINT=${SPARKD__SPARKD_ENTRYPOINT}
shm_size: "${SPARKD__SHM_SIZE:-512mb}"
command: >
sh -c "
echo bts | sudo -S chown -R bts:bts /home/bts/.local/share/bts/sparkd/data
if [ -e "/home/bts/.local/share/bts/sparkd/data/logging.sparkd/log" ]; then
mv "/home/bts/.local/share/bts/sparkd/data/logging.sparkd/log" "/home/bts/.local/share/bts/sparkd/data/logging.sparkd/log_$(date '+%Y%m%d-%H%M')"
fi
if [ -e "/home/bts/.local/share/bts/conf/.env.local" ]; then
echo 'Sourcing /home/bts/.local/share/bts/conf/.env.local'
set -a
. /home/bts/.local/share/bts/sparkd/conf/.env.local
set +a
fi
if [ -d /home/bts/.local/share/bts/sparkd/conf/plugins ]; then
echo 'Copying /home/bts/.local/share/bts/sparkd/conf/plugins to runtime dir (/home/bts/bin)'
cp -r /home/bts/.local/share/bts/sparkd/conf/plugins /home/bts/bin/
fi
./sparkd run"
env_file:
- .env
- ${SPARKD__CONFIG_DIR}/.env
ports:
- "${SPARKD__CONFIG_PORT}:${SPARKD__CONFIG_PORT}"
- "${SPARKD__QUICKBUS_PORT}:${SPARKD__QUICKBUS_PORT}"
- "${SPARKD__SIM_FIX_PORT}:${SPARKD__SIM_FIX_PORT}"
entrypoint: ${SPARKD__MAIN_ENTRYPOINT}
deploy:
resources:
limits:
memory: "${SPARKD__MEMORY:-4gb}"
sparkd-shell:
volumes:
- ${SPARKD__DATA_DIR:-sparkd_data}:/home/bts/.local/share/bts/sparkd/data
- ${SPARKD__MD_RECORDING_DIR:-md_recording}:/md_recording
build:
dockerfile: docker/images/bluetradingsystems/linux_shell/Dockerfile
args:
- IMAGE=${SPARKD__IMAGE}
- SOURCE_DIR=${SPARKD__SOURCE_DIR}
- CONFIG_DIR=${SPARKD__CONFIG_DIR}
- PYTHON_REQUIREMENTS=${SPARKD__PYTHON_REQUIREMENTS}
- SPARKD_ENTRYPOINT=${SPARKD__SPARKD_ENTRYPOINT}
shm_size: "${SPARKD__SHM_SIZE:-512mb}"
command: "do sleep 1; done"
env_file:
- .env
- ${SPARKD__CONFIG_DIR}/.env
@@ -42,6 +54,7 @@ services:
sparkd-symbols:
volumes:
- ${SPARKD__DATA_DIR:-sparkd_data}:/home/bts/.local/share/bts/sparkd/data
- ${SPARKD__MD_RECORDING_DIR:-md_recording}:/md_recording
- ${SPARKD__RUNTIME_CONF_DIR:-sparkd_conf}:/home/bts/.local/share/bts/sparkd/conf
build:
dockerfile: src/app_sparkd/Dockerfile
@@ -50,26 +63,8 @@ services:
- SOURCE_DIR=${SPARKD__SOURCE_DIR}
- CONFIG_DIR=${SPARKD__CONFIG_DIR}
- PYTHON_REQUIREMENTS=${SPARKD__PYTHON_REQUIREMENTS}
- SPARKD_ENTRYPOINT=${SPARKD__SPARKD_ENTRYPOINT}
shm_size: "${SPARKD__SHM_SIZE:-512mb}"
command: >
sh -c "
echo bts | sudo -S chown -R bts:bts /home/bts/.local/share/bts/sparkd
if [ -e "/home/bts/.local/share/bts/sparkd/data/logging.sparkd/log" ]; then
mv "/home/bts/.local/share/bts/sparkd/data/logging.sparkd/log" "/home/bts/.local/share/bts/sparkd/data/logging.sparkd/log_$(date '+%Y%m%d-%H%M')"
fi
ls -alh /home/bts/.local/share/bts/sparkd/conf/
cat /home/bts/.local/share/bts/sparkd/conf/.env.local
if [ -e "/home/bts/.local/share/bts/sparkd/conf/.env.local" ]; then
echo 'Sourcing /home/bts/.local/share/bts/sparkd/conf/.env.local'
set -a
. /home/bts/.local/share/bts/sparkd/conf/.env.local
set +a
fi
if [ -d /home/bts/.local/share/bts/sparkd/conf/plugins ]; then
echo 'Copying /home/bts/.local/share/bts/sparkd/conf/plugins to runtime dir (/home/bts/bin)'
cp -r /home/bts/.local/share/bts/sparkd/conf/plugins /home/bts/bin/
fi
./sparkd run"
env_file:
- .env
- ${SPARKD__CONFIG_DIR}/.env
@@ -77,6 +72,7 @@ services:
- "${SPARKD__CONFIG_PORT}:${SPARKD__CONFIG_PORT}"
- "${SPARKD__QUICKBUS_PORT}:${SPARKD__QUICKBUS_PORT}"
- "${SPARKD__SIM_FIX_PORT}:${SPARKD__SIM_FIX_PORT}"
entrypoint: ${SPARKD__MAIN_ENTRYPOINT}
deploy:
restart_policy:
condition: any
@@ -84,7 +80,34 @@ services:
resources:
limits:
memory: "${SPARKD__MEMORY:-4gb}"
sparkd-multicast:
environment:
- TZ=America/Chicago
volumes:
- ${SPARKD__DATA_DIR:-sparkd_data}:/home/bts/.local/share/bts/sparkd/data
- ${SPARKD__MD_RECORDING_DIR:-md_recording}:/md_recording
- ${SPARKD__RUNTIME_CONF_DIR:-sparkd_conf}:/home/bts/.local/share/bts/sparkd/conf
build:
dockerfile: src/app_sparkd/Dockerfile
args:
- IMAGE=${SPARKD__IMAGE}
- SOURCE_DIR=${SPARKD__SOURCE_DIR}
- CONFIG_DIR=${SPARKD__CONFIG_DIR}
- PYTHON_REQUIREMENTS=${SPARKD__PYTHON_REQUIREMENTS}
- SPARKD_ENTRYPOINT=${SPARKD__SPARKD_ENTRYPOINT}
shm_size: "${SPARKD__SHM_SIZE:-8192mb}"
env_file:
- .env
- ${SPARKD__CONFIG_DIR}/.env
network_mode: "host"
entrypoint: ${SPARKD__MAIN_ENTRYPOINT}
deploy:
restart_policy:
condition: any
delay: 3s
resources:
limits:
memory: "${SPARKD__MEMORY:-16gb}"
sparkd-tail:
image: bluetradingsystems/linux_dotnet8
volumes:
@@ -195,3 +218,6 @@ volumes:
name: "md_publisher_22019"
historic_md:
name: "historic_md"
md_recording:
name: "sparkd_md_recording_${SPARKD__CONFIG_PORT:-8000}"
external: true
@@ -8,6 +8,7 @@ RUN apt-get update && apt-get install -y ca-certificates
RUN apt-get update && apt-get install -y libssh2-1-dev
RUN apt-get update && apt-get install -y software-properties-common
RUN apt-get update && apt-get install -y sudo
RUN apt-get update && apt-get install -y tzdata
# GCC
ARG gcc_major=13
@@ -18,6 +19,11 @@ RUN add-apt-repository ppa:ubuntu-toolchain-r/test \
RUN apt-get update \
&& apt-get install -y dotnet8
RUN apt-get update && apt-get install -y gdb
RUN apt-get update && apt-get install -y fish
RUN apt-get update && apt-get install -y vim
RUN apt-get update && apt-get install -y less
RUN locale-gen en_US.UTF-8
ARG docker_user="bts"
@@ -55,14 +55,16 @@ RUN \
clangd-$clang_major
# CMake
RUN \
curl -fsSL https://apt.kitware.com/keys/kitware-archive-latest.asc 2> /dev/null \
| gpg --dearmor - \
| tee /usr/share/keyrings/kitware-archive-keyring.gpg > /dev/null \
&& echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" \
| tee /etc/apt/sources.list.d/kitware.list > /dev/null \
&& apt-get update \
&& apt-get install -y cmake
RUN set -eux \
&& apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl gpg \
&& curl -fsSL https://apt.kitware.com/keys/kitware-archive-latest.asc \
| gpg --dearmor -o /usr/share/keyrings/kitware-archive-keyring.gpg \
&& echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main" \
> /etc/apt/sources.list.d/kitware.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends cmake \
&& rm -rf /var/lib/apt/lists/*
# Dotnet
RUN apt-get update && apt-get install -y dotnet8
@@ -80,9 +82,14 @@ RUN mkdir -p /etc/apt/keyrings \
# Emumba (deps)
RUN apt-get update && apt-get -y install rapidjson-dev
# Emumba
COPY emumba /emumba
RUN dpkg -i /emumba/emumba-deribit-connector-3.3.1-Linux.LICENSE_DISABLED.deb \
&& rm -r /emumba
ARG EMUMBA_DERIBIT_CONNECTOR_DEB_URL="https://api.bitbucket.org/2.0/repositories/bluetradesys/spark/downloads/emumba-deribit-connector-3.3.1-Linux.LICENSE_DISABLED.deb"
RUN --mount=type=secret,id=bitbucket_access_token \
set -eux \
&& apt-get update \
&& TOKEN="$(cat /run/secrets/bitbucket_access_token)" \
&& curl -fL -H "Authorization: Bearer ${TOKEN}" $EMUMBA_DERIBIT_CONNECTOR_DEB_URL -o /tmp/emumba-deribit-connector.deb \
&& apt-get install -y /tmp/emumba-deribit-connector.deb \
&& rm -f /tmp/emumba-deribit-connector.deb
# Pcap
RUN apt-get update && apt-get install -y libpcap0.8-dev
@@ -90,6 +97,18 @@ RUN apt-get update && apt-get install -y libpcap0.8-dev
# Databento (deps)
RUN apt-get update && apt-get -y install libzstd-dev
# Rakurai
ARG RAKURAI_DEB_URL="https://api.bitbucket.org/2.0/repositories/bluetradesys/spark/downloads/rakurai-dex-connector_0.0.5_amd64.deb"
RUN --mount=type=secret,id=bitbucket_access_token \
set -eux \
&& apt-get update \
&& TOKEN="$(cat /run/secrets/bitbucket_access_token)" \
&& curl -fL -H "Authorization: Bearer ${TOKEN}" $RAKURAI_DEB_URL -o /tmp/rakurai.deb \
# Need --force-overwrite because rakuirai and emumba-deribit-connector both include the same
# spdlog headers.
&& apt-get install -y -o Dpkg::Options::="--force-overwrite" /tmp/rakurai.deb \
&& rm -f /tmp/rakuirai.deb
# Docker in Docker
RUN apt-get update && apt-get install -y \
docker.io \
@@ -0,0 +1,11 @@
FROM ubuntu:24.04
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
fish \
less \
vim
USER bts
WORKDIR /home/bts
+3 -3
View File
@@ -18,10 +18,10 @@ MarkupSafe==3.0.2
mccabe==0.6.1
numpy==2.2.6
platformdirs==2.3.0
protobuf==4.21.12
protobuf==6.33.4
pybars3==0.9.7
pybind11==2.13.6
pybind11-stubgen==2.5.3
pybind11==3.0.1
pybind11-stubgen==2.5.5
pybit==5.11.0
pycodestyle==2.7.0
pycparser==2.20
+281 -380
View File
@@ -1,405 +1,306 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32922.545
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bts.Spark.Api", "src\cs\Bts.Spark.Api\Bts.Spark.Api.csproj", "{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spark", "src\client\spark\Spark.csproj", "{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spark.Console", "src\client\Spark.Console\Spark.Console.csproj", "{387566C6-C6F6-412C-A30C-9855BBCB4816}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bts.Spark.Core", "src\cs\Bts.Spark.Core\Bts.Spark.Core.csproj", "{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_sdk", "src\client\spark_sdk\spark_sdk.csproj", "{6963C314-83C4-4667-B0D0-C2F7AE208C29}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_test", "src\client\spark_test\spark_test.csproj", "{ECD78CC5-138F-4809-A764-2358C2AC2E82}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_websocket", "src\client\spark_websocket\spark_websocket.csproj", "{3201359D-C071-4089-9EDE-B04D759F1508}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "spark_api_server", "src\client\spark_api_server\spark_api_server.csproj", "{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamCore", "src\DataStreamSuite\DataStreamCore\DataStreamCore.csproj", "{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStream", "src\DataStreamSuite\DataStream\DataStream.csproj", "{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedStreams", "src\DataStreamSuite\SharedStreams\SharedStreams.csproj", "{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PubSub", "src\DataStreamSuite\PubSub\PubSub.csproj", "{51C40BA9-F226-4A35-939D-1ED6F5FF7299}"
EndProject
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cs", "cs", "{D7C6B9C7-1058-B1EA-FEE6-34C56B05AEDB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Spark.Core", "src\cs\Bts.Spark.Core\Bts.Spark.Core.csproj", "{684863A1-3396-4D31-A731-C0725CF07F4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Spark.Api", "src\cs\Bts.Spark.Api\Bts.Spark.Api.csproj", "{45292808-4EF3-4D4A-B3F5-B75C42EE5870}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Extensions.Hosting", "src\cs\Bts.Extensions.Hosting\Bts.Extensions.Hosting.csproj", "{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.IO.Compression", "src\cs\Bts.IO.Compression\Bts.IO.Compression.csproj", "{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Net", "src\cs\Bts.Net\Bts.Net.csproj", "{7543386A-5EBA-4AF0-9E0F-35657B58557D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DataStreamSuite", "DataStreamSuite", "{60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Net", "src\DataStreamSuite\Bts.Net\Bts.Net.csproj", "{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PubSub", "src\DataStreamSuite\PubSub\PubSub.csproj", "{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.Extensions.Hosting", "src\DataStreamSuite\Bts.Extensions.Hosting\Bts.Extensions.Hosting.csproj", "{90A48718-F6A7-4747-97EA-89632B451008}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamCore", "src\DataStreamSuite\DataStreamCore\DataStreamCore.csproj", "{F7C6F079-67BA-4899-9B43-D3F8C121D264}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArithmeticExpressions", "src\DataStreamSuite\ArithmeticExpressions\ArithmeticExpressions.csproj", "{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BaseUtilities", "src\DataStreamSuite\BaseUtilities\BaseUtilities.csproj", "{ECBAA198-EC93-4174-8156-BDA5F5E95042}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BooleanExpressions", "src\DataStreamSuite\BooleanExpressions\BooleanExpressions.csproj", "{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.ColumnExpressions", "src\DataStreamSuite\Bts.ColumnExpressions\Bts.ColumnExpressions.csproj", "{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bts.ColumnSortExpressions", "src\DataStreamSuite\Bts.ColumnSortExpressions\Bts.ColumnSortExpressions.csproj", "{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStreamExpressions", "src\DataStreamSuite\DataStreamExpressions\DataStreamExpressions.csproj", "{B6070F41-8759-448B-B56D-A7D15D489569}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataStream", "src\DataStreamSuite\DataStream\DataStream.csproj", "{B2D721AB-920C-4CD6-8DBF-6778A115A449}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharedStreams", "src\DataStreamSuite\SharedStreams\SharedStreams.csproj", "{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "client", "client", "{C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "spark", "spark", "{42C014A0-00C5-0620-8552-38912E891A7F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spark", "src\client\spark\Spark.csproj", "{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spark_test", "src\client\spark_test\spark_test.csproj", "{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spark.Console", "src\client\Spark.Console\Spark.Console.csproj", "{2B8243FF-60C6-4607-8AAE-7762D29B0A48}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
MinSizeRel|x64 = MinSizeRel|x64
MinSizeRel|Any CPU = MinSizeRel|Any CPU
MinSizeRel|x86 = MinSizeRel|x86
Release|x64 = Release|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
RelWithDebInfo|x64 = RelWithDebInfo|x64
RelWithDebInfo|Any CPU = RelWithDebInfo|Any CPU
RelWithDebInfo|x86 = RelWithDebInfo|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Debug|x64.ActiveCfg = Debug|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Debug|x64.Build.0 = Debug|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Debug|x86.ActiveCfg = Debug|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Debug|x86.Build.0 = Debug|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.MinSizeRel|x64.ActiveCfg = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.MinSizeRel|x64.Build.0 = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|x64.ActiveCfg = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|x64.Build.0 = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|Any CPU.Build.0 = Release|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|x86.ActiveCfg = Release|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.Release|x86.Build.0 = Release|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x64.Build.0 = Release|x64
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{DC9A8975-8211-4FC9-A9BA-C8B9D26AD481}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x64.ActiveCfg = Debug|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x64.Build.0 = Debug|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x86.ActiveCfg = Debug|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Debug|x86.Build.0 = Debug|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.MinSizeRel|x64.ActiveCfg = Release|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.MinSizeRel|x64.Build.0 = Release|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Release|x64.ActiveCfg = Release|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Release|x64.Build.0 = Release|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Release|Any CPU.Build.0 = Release|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Release|x86.ActiveCfg = Release|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.Release|x86.Build.0 = Release|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.RelWithDebInfo|x64.Build.0 = Release|x64
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{9A4D4D07-1AB6-4B2B-B111-A4F34D6C267E}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x64.ActiveCfg = Debug|x64
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x64.Build.0 = Debug|x64
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|Any CPU.Build.0 = Debug|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x86.ActiveCfg = Debug|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Debug|x86.Build.0 = Debug|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x64.ActiveCfg = Debug|x64
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x64.Build.0 = Debug|x64
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x64.ActiveCfg = Release|x64
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x64.Build.0 = Release|x64
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|Any CPU.ActiveCfg = Release|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|Any CPU.Build.0 = Release|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x86.ActiveCfg = Release|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.Release|x86.Build.0 = Release|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x64.Build.0 = Release|x64
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{387566C6-C6F6-412C-A30C-9855BBCB4816}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|x64.ActiveCfg = Debug|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|x64.Build.0 = Debug|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|x86.ActiveCfg = Debug|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Debug|x86.Build.0 = Debug|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.MinSizeRel|x64.ActiveCfg = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.MinSizeRel|x64.Build.0 = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Release|x64.ActiveCfg = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Release|x64.Build.0 = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Release|Any CPU.Build.0 = Release|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Release|x86.ActiveCfg = Release|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.Release|x86.Build.0 = Release|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|x64.Build.0 = Release|x64
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{6E449EB6-20AC-4FA6-B8D9-10F4BB7E1FEE}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Debug|x64.ActiveCfg = Debug|x64
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Debug|x64.Build.0 = Debug|x64
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Debug|x86.ActiveCfg = Debug|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Debug|x86.Build.0 = Debug|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.MinSizeRel|x64.ActiveCfg = Release|x64
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.MinSizeRel|x64.Build.0 = Release|x64
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Release|x64.ActiveCfg = Release|x64
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Release|x64.Build.0 = Release|x64
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Release|Any CPU.Build.0 = Release|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Release|x86.ActiveCfg = Release|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.Release|x86.Build.0 = Release|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.RelWithDebInfo|x64.Build.0 = Release|x64
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{6963C314-83C4-4667-B0D0-C2F7AE208C29}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Debug|x64.ActiveCfg = Debug|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Debug|x64.Build.0 = Debug|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Debug|x86.ActiveCfg = Debug|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Debug|x86.Build.0 = Debug|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.MinSizeRel|x64.ActiveCfg = Debug|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.MinSizeRel|x64.Build.0 = Debug|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Release|x64.ActiveCfg = Release|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Release|x64.Build.0 = Release|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Release|Any CPU.Build.0 = Release|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Release|x86.ActiveCfg = Release|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.Release|x86.Build.0 = Release|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.RelWithDebInfo|x64.Build.0 = Release|x64
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{ECD78CC5-138F-4809-A764-2358C2AC2E82}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|x64.ActiveCfg = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|x64.Build.0 = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|x86.ActiveCfg = Debug|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.Debug|x86.Build.0 = Debug|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|x64.ActiveCfg = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|x64.Build.0 = Debug|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|x64.ActiveCfg = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|x64.Build.0 = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|Any CPU.Build.0 = Release|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|x86.ActiveCfg = Release|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.Release|x86.Build.0 = Release|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|x64.Build.0 = Release|x64
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{3201359D-C071-4089-9EDE-B04D759F1508}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|x64.ActiveCfg = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|x64.Build.0 = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|x86.ActiveCfg = Debug|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Debug|x86.Build.0 = Debug|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|x64.ActiveCfg = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|x64.Build.0 = Debug|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|x64.ActiveCfg = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|x64.Build.0 = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|Any CPU.Build.0 = Release|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|x86.ActiveCfg = Release|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.Release|x86.Build.0 = Release|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|x64.ActiveCfg = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|x64.Build.0 = Release|x64
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{2B8C5D01-FF78-4BFA-B332-5E430586DAF9}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Debug|x64.ActiveCfg = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Debug|x64.Build.0 = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Debug|x86.ActiveCfg = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Debug|x86.Build.0 = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Release|x64.ActiveCfg = Release|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Release|x64.Build.0 = Release|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Release|Any CPU.Build.0 = Release|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Release|x86.ActiveCfg = Release|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.Release|x86.Build.0 = Release|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{4E4F491F-C688-43C4-88DA-AC92BC5FA1B8}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Debug|x64.ActiveCfg = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Debug|x64.Build.0 = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Debug|x86.ActiveCfg = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Debug|x86.Build.0 = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Release|x64.ActiveCfg = Release|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Release|x64.Build.0 = Release|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Release|Any CPU.Build.0 = Release|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Release|x86.ActiveCfg = Release|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.Release|x86.Build.0 = Release|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{2AC54ADC-3246-427E-9CA9-FEA2DBCB9432}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Debug|x64.ActiveCfg = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Debug|x64.Build.0 = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Debug|x86.ActiveCfg = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Debug|x86.Build.0 = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Release|x64.ActiveCfg = Release|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Release|x64.Build.0 = Release|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Release|Any CPU.Build.0 = Release|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Release|x86.ActiveCfg = Release|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.Release|x86.Build.0 = Release|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{4E96E5CC-7791-40B3-A8A1-C34FBB736B3B}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Debug|x64.ActiveCfg = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Debug|x64.Build.0 = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Debug|x86.ActiveCfg = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Debug|x86.Build.0 = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.MinSizeRel|Any CPU.ActiveCfg = MinSizeRel|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.MinSizeRel|Any CPU.Build.0 = MinSizeRel|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.MinSizeRel|x86.ActiveCfg = MinSizeRel|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.MinSizeRel|x86.Build.0 = MinSizeRel|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Release|x64.ActiveCfg = Release|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Release|x64.Build.0 = Release|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Release|Any CPU.Build.0 = Release|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Release|x86.ActiveCfg = Release|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.Release|x86.Build.0 = Release|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.RelWithDebInfo|Any CPU.ActiveCfg = RelWithDebInfo|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.RelWithDebInfo|Any CPU.Build.0 = RelWithDebInfo|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.RelWithDebInfo|x86.ActiveCfg = RelWithDebInfo|Any CPU
{51C40BA9-F226-4A35-939D-1ED6F5FF7299}.RelWithDebInfo|x86.Build.0 = RelWithDebInfo|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Debug|x64.ActiveCfg = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Debug|x64.Build.0 = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Debug|x86.ActiveCfg = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Debug|x86.Build.0 = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.MinSizeRel|x86.Build.0 = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Release|x64.ActiveCfg = Release|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Release|x64.Build.0 = Release|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Release|Any CPU.Build.0 = Release|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Release|x86.ActiveCfg = Release|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.Release|x86.Build.0 = Release|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.RelWithDebInfo|x86.ActiveCfg = Debug|Any CPU
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4}.RelWithDebInfo|x86.Build.0 = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Debug|x64.ActiveCfg = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Debug|x64.Build.0 = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Debug|x86.ActiveCfg = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Debug|x86.Build.0 = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.MinSizeRel|x64.Build.0 = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.MinSizeRel|x86.ActiveCfg = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.MinSizeRel|x86.Build.0 = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Release|x64.ActiveCfg = Release|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Release|x64.Build.0 = Release|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Release|Any CPU.Build.0 = Release|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Release|x86.ActiveCfg = Release|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.Release|x86.Build.0 = Release|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.RelWithDebInfo|x64.ActiveCfg = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.RelWithDebInfo|x64.Build.0 = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.RelWithDebInfo|Any CPU.ActiveCfg = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.RelWithDebInfo|Any CPU.Build.0 = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.RelWithDebInfo|x86.ActiveCfg = Debug|Any CPU
{90A48718-F6A7-4747-97EA-89632B451008}.RelWithDebInfo|x86.Build.0 = Debug|Any CPU
{684863A1-3396-4D31-A731-C0725CF07F4E}.Debug|Any CPU.ActiveCfg = Debug|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Debug|Any CPU.Build.0 = Debug|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Debug|x64.ActiveCfg = Debug|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Debug|x64.Build.0 = Debug|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Debug|x86.ActiveCfg = Debug|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Debug|x86.Build.0 = Debug|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Release|Any CPU.ActiveCfg = Release|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Release|Any CPU.Build.0 = Release|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Release|x64.ActiveCfg = Release|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Release|x64.Build.0 = Release|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Release|x86.ActiveCfg = Release|x64
{684863A1-3396-4D31-A731-C0725CF07F4E}.Release|x86.Build.0 = Release|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Debug|Any CPU.ActiveCfg = Debug|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Debug|Any CPU.Build.0 = Debug|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Debug|x64.ActiveCfg = Debug|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Debug|x64.Build.0 = Debug|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Debug|x86.ActiveCfg = Debug|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Debug|x86.Build.0 = Debug|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Release|Any CPU.ActiveCfg = Release|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Release|Any CPU.Build.0 = Release|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Release|x64.ActiveCfg = Release|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Release|x64.Build.0 = Release|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Release|x86.ActiveCfg = Release|x64
{45292808-4EF3-4D4A-B3F5-B75C42EE5870}.Release|x86.Build.0 = Release|x64
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Debug|x64.ActiveCfg = Debug|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Debug|x64.Build.0 = Debug|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Debug|x86.ActiveCfg = Debug|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Debug|x86.Build.0 = Debug|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Release|Any CPU.Build.0 = Release|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Release|x64.ActiveCfg = Release|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Release|x64.Build.0 = Release|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Release|x86.ActiveCfg = Release|Any CPU
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6}.Release|x86.Build.0 = Release|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Debug|Any CPU.Build.0 = Debug|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Debug|x64.ActiveCfg = Debug|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Debug|x64.Build.0 = Debug|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Debug|x86.ActiveCfg = Debug|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Debug|x86.Build.0 = Debug|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Release|Any CPU.ActiveCfg = Release|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Release|Any CPU.Build.0 = Release|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Release|x64.ActiveCfg = Release|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Release|x64.Build.0 = Release|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Release|x86.ActiveCfg = Release|Any CPU
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958}.Release|x86.Build.0 = Release|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Debug|x64.ActiveCfg = Debug|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Debug|x64.Build.0 = Debug|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Debug|x86.ActiveCfg = Debug|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Debug|x86.Build.0 = Debug|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Release|Any CPU.Build.0 = Release|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Release|x64.ActiveCfg = Release|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Release|x64.Build.0 = Release|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Release|x86.ActiveCfg = Release|Any CPU
{7543386A-5EBA-4AF0-9E0F-35657B58557D}.Release|x86.Build.0 = Release|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Debug|x64.ActiveCfg = Debug|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Debug|x64.Build.0 = Debug|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Debug|x86.ActiveCfg = Debug|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Debug|x86.Build.0 = Debug|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Release|Any CPU.Build.0 = Release|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Release|x64.ActiveCfg = Release|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Release|x64.Build.0 = Release|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Release|x86.ActiveCfg = Release|Any CPU
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43}.Release|x86.Build.0 = Release|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Debug|x64.ActiveCfg = Debug|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Debug|x64.Build.0 = Debug|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Debug|x86.ActiveCfg = Debug|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Debug|x86.Build.0 = Debug|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Release|Any CPU.Build.0 = Release|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Release|x64.ActiveCfg = Release|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Release|x64.Build.0 = Release|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Release|x86.ActiveCfg = Release|Any CPU
{F7C6F079-67BA-4899-9B43-D3F8C121D264}.Release|x86.Build.0 = Release|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Debug|x64.ActiveCfg = Debug|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Debug|x64.Build.0 = Debug|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Debug|x86.ActiveCfg = Debug|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Debug|x86.Build.0 = Debug|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Release|Any CPU.Build.0 = Release|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Release|x64.ActiveCfg = Release|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Release|x64.Build.0 = Release|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Release|x86.ActiveCfg = Release|Any CPU
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7}.Release|x86.Build.0 = Release|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Debug|x64.ActiveCfg = Debug|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Debug|x64.Build.0 = Debug|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Debug|x86.ActiveCfg = Debug|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Debug|x86.Build.0 = Debug|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Release|Any CPU.Build.0 = Release|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Release|x64.ActiveCfg = Release|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Release|x64.Build.0 = Release|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Release|x86.ActiveCfg = Release|Any CPU
{ECBAA198-EC93-4174-8156-BDA5F5E95042}.Release|x86.Build.0 = Release|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Debug|x64.ActiveCfg = Debug|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Debug|x64.Build.0 = Debug|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Debug|x86.ActiveCfg = Debug|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Debug|x86.Build.0 = Debug|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Release|Any CPU.Build.0 = Release|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Release|x64.ActiveCfg = Release|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Release|x64.Build.0 = Release|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Release|x86.ActiveCfg = Release|Any CPU
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40}.Release|x86.Build.0 = Release|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Debug|x64.ActiveCfg = Debug|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Debug|x64.Build.0 = Debug|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Debug|x86.ActiveCfg = Debug|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Debug|x86.Build.0 = Debug|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Release|Any CPU.Build.0 = Release|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Release|x64.ActiveCfg = Release|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Release|x64.Build.0 = Release|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Release|x86.ActiveCfg = Release|Any CPU
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7}.Release|x86.Build.0 = Release|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Debug|x64.ActiveCfg = Debug|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Debug|x64.Build.0 = Debug|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Debug|x86.ActiveCfg = Debug|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Debug|x86.Build.0 = Debug|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Release|Any CPU.Build.0 = Release|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Release|x64.ActiveCfg = Release|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Release|x64.Build.0 = Release|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Release|x86.ActiveCfg = Release|Any CPU
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60}.Release|x86.Build.0 = Release|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Debug|x64.ActiveCfg = Debug|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Debug|x64.Build.0 = Debug|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Debug|x86.ActiveCfg = Debug|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Debug|x86.Build.0 = Debug|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Release|Any CPU.Build.0 = Release|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Release|x64.ActiveCfg = Release|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Release|x64.Build.0 = Release|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Release|x86.ActiveCfg = Release|Any CPU
{B6070F41-8759-448B-B56D-A7D15D489569}.Release|x86.Build.0 = Release|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Debug|x64.ActiveCfg = Debug|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Debug|x64.Build.0 = Debug|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Debug|x86.ActiveCfg = Debug|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Debug|x86.Build.0 = Debug|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Release|Any CPU.Build.0 = Release|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Release|x64.ActiveCfg = Release|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Release|x64.Build.0 = Release|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Release|x86.ActiveCfg = Release|Any CPU
{B2D721AB-920C-4CD6-8DBF-6778A115A449}.Release|x86.Build.0 = Release|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Debug|Any CPU.Build.0 = Debug|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Debug|x64.ActiveCfg = Debug|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Debug|x64.Build.0 = Debug|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Debug|x86.ActiveCfg = Debug|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Debug|x86.Build.0 = Debug|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Release|Any CPU.ActiveCfg = Release|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Release|Any CPU.Build.0 = Release|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Release|x64.ActiveCfg = Release|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Release|x64.Build.0 = Release|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Release|x86.ActiveCfg = Release|Any CPU
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20}.Release|x86.Build.0 = Release|Any CPU
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Debug|Any CPU.ActiveCfg = Debug|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Debug|Any CPU.Build.0 = Debug|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Debug|x64.ActiveCfg = Debug|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Debug|x64.Build.0 = Debug|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Debug|x86.ActiveCfg = Debug|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Debug|x86.Build.0 = Debug|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Release|Any CPU.ActiveCfg = Release|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Release|Any CPU.Build.0 = Release|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Release|x64.ActiveCfg = Release|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Release|x64.Build.0 = Release|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Release|x86.ActiveCfg = Release|x64
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3}.Release|x86.Build.0 = Release|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Debug|Any CPU.ActiveCfg = Debug|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Debug|Any CPU.Build.0 = Debug|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Debug|x64.ActiveCfg = Debug|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Debug|x64.Build.0 = Debug|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Debug|x86.ActiveCfg = Debug|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Debug|x86.Build.0 = Debug|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Release|Any CPU.ActiveCfg = Release|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Release|Any CPU.Build.0 = Release|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Release|x64.ActiveCfg = Release|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Release|x64.Build.0 = Release|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Release|x86.ActiveCfg = Release|x64
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224}.Release|x86.Build.0 = Release|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Debug|Any CPU.ActiveCfg = Debug|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Debug|Any CPU.Build.0 = Debug|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Debug|x64.ActiveCfg = Debug|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Debug|x64.Build.0 = Debug|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Debug|x86.ActiveCfg = Debug|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Debug|x86.Build.0 = Debug|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Release|Any CPU.ActiveCfg = Release|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Release|Any CPU.Build.0 = Release|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Release|x64.ActiveCfg = Release|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Release|x64.Build.0 = Release|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Release|x86.ActiveCfg = Release|x64
{2B8243FF-60C6-4607-8AAE-7762D29B0A48}.Release|x86.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{D7C6B9C7-1058-B1EA-FEE6-34C56B05AEDB} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{684863A1-3396-4D31-A731-C0725CF07F4E} = {D7C6B9C7-1058-B1EA-FEE6-34C56B05AEDB}
{45292808-4EF3-4D4A-B3F5-B75C42EE5870} = {D7C6B9C7-1058-B1EA-FEE6-34C56B05AEDB}
{AA57F8D9-7BD6-4161-881B-AD2CEF9A30F6} = {D7C6B9C7-1058-B1EA-FEE6-34C56B05AEDB}
{28A26DF7-5F7A-43A2-A548-B55FEBCC3958} = {D7C6B9C7-1058-B1EA-FEE6-34C56B05AEDB}
{7543386A-5EBA-4AF0-9E0F-35657B58557D} = {D7C6B9C7-1058-B1EA-FEE6-34C56B05AEDB}
{60E0D592-FFB3-0D0A-C4AA-E88919B48F9D} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{5DE3B533-DCE6-4BF4-8F7E-08C440E177B4} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{90A48718-F6A7-4747-97EA-89632B451008} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {422D1620-0166-4C26-9A81-CA8A2EB1AB58}
EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
{C13A5ABD-F739-4BE8-A2FE-511E989A5B43} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{F7C6F079-67BA-4899-9B43-D3F8C121D264} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{E60C119D-2919-4E2F-9D39-90DB1A8FF9A7} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{ECBAA198-EC93-4174-8156-BDA5F5E95042} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{F54AE5C0-2ECA-4151-82E6-0D7EFE88FF40} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{A898C6C3-F134-4AF0-AFB3-3834C58CC0D7} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{1E296FB3-D185-4A95-A1EB-AA5B37B85C60} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{B6070F41-8759-448B-B56D-A7D15D489569} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{B2D721AB-920C-4CD6-8DBF-6778A115A449} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{38EE36C6-892C-4C94-8BB0-1ACB164E1F20} = {60E0D592-FFB3-0D0A-C4AA-E88919B48F9D}
{C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{42C014A0-00C5-0620-8552-38912E891A7F} = {C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295}
{D432F3E9-3D2F-4623-B7B9-CEBA6701FFC3} = {42C014A0-00C5-0620-8552-38912E891A7F}
{DD00F5D5-6C2F-4FDA-AE3D-25CF01A9A224} = {C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295}
{2B8243FF-60C6-4607-8AAE-7762D29B0A48} = {C5A3B5EA-BE9F-76E5-E9B8-8A22B289B295}
EndGlobalSection
EndGlobal
@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>$(SparkVersion)</Version>
</PropertyGroup>
<ItemGroup>
@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>$(SparkVersion)</Version>
</PropertyGroup>
</Project>
@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>$(SparkVersion)</Version>
</PropertyGroup>
<ItemGroup>
@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>$(SparkVersion)</Version>
</PropertyGroup>
<ItemGroup>
@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>$(SparkVersion)</Version>
</PropertyGroup>
<ItemGroup>
@@ -4,7 +4,6 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>$(SparkVersion)</Version>
</PropertyGroup>
<ItemGroup>
@@ -1,9 +1,7 @@
using System;
namespace BCG {
[DataStreamUserRespresentation("CountStream")]
public class CountStream : ViewStream {
private DataPacket myLastFiredDataPacket;
IDataPacket? myLastFiredDataPacket;
private IBlueTableSchema mySchema = new BlueTableSchema("count",
new ColumnInfo("id", 0, typeof(int)),
new ColumnInfo("count", 1, typeof(int)));
@@ -24,7 +22,6 @@ namespace BCG {
myVS.onChange -= new ChangeDelegate(myHandleChanges);
}
private void myHandleChanges(object newValue) {
myFireEvent(
myLastFiredDataPacket =
@@ -39,11 +36,8 @@ namespace BCG {
private IBlueRowCollection myGetRows(object dp, int id) {
BlueTable retVal = new BlueTable(mySchema);
retVal.addRow
(new BlueRow(mySchema, id, (dp as DataPacket).newRows.Count));
retVal.addRow(new BlueRow(mySchema, id, ((IDataPacket)dp).newRows.Count));
return retVal;
}
}
}
@@ -1,5 +1,8 @@
namespace bts.BlueOrb {
using BCG;
using Bts.DataStreamCore;
using System;
using System.Text.RegularExpressions;
@@ -21,22 +24,24 @@ namespace bts.BlueOrb {
#region IStreamFilter Members
public bool filter(IBlueRow dr) {
bool rv = true;
for (int i = 0; i < myCols.Length; i++) {
rv &= myRegExps[i].IsMatch(dr[myCols[i]] is DBNull ? "" : dr[myCols[i]].ToString());
if (!rv)
return rv;
var val = dr[myCols[i]];
var str = val is DBNull
? string.Empty
: (val?.ToString() ?? string.Empty);
if (!myRegExps[i].IsMatch(str)) {
return false;
}
}
return rv;
return true;
}
#endregion
}
private BlueTable myLastFiredRows;
private IBlueRowCollection myLastReceivedRows;
BlueTable? myLastFiredRows;
IBlueRowCollection? myLastReceivedRows;
private IStreamFilter myFilter;
private ViewStream myParentStream;
private string myFilterString;
private bool myUseNewFilter = false;// Configuration.get<DataStreamConfig>().UseNewFilter;
#region constructors
public delegate bool OnFilter(IBlueRow r);
@@ -52,12 +57,11 @@ namespace bts.BlueOrb {
public FilterStream(ViewStream vs, IStreamFilter filter) {
{
myParentStream = vs;
myFilter = filter;
myFilterString = filter.ToString();
if (filter is IDynamicStreamFilter)
(filter as IDynamicStreamFilter).onFilterChange += new FilterChangeDelegate(myHandleFilterChange);
myParentStream = vs;
myFilter = filter;
myFilterString = filter.ToString() ?? string.Empty;
if (filter is IDynamicStreamFilter dynFilter) {
dynFilter.onFilterChange += myHandleFilterChange;
}
}
@@ -86,7 +90,7 @@ namespace bts.BlueOrb {
}
protected override void myFireEvent(object o) {
DataPacket dp = o as DataPacket;
var dp = (IDataPacket)o;
if (myLastValue == null || dp.addedRows.Count + dp.deletedRows.Count > 0)
base.myFireEvent(o);
}
@@ -94,23 +98,27 @@ namespace bts.BlueOrb {
private void myHandleCallbacks(object newValue) {
DataPacket retVal;
DataPacket arrivedPacket = newValue as DataPacket;
IDataPacket arrivedPacket = (IDataPacket)newValue;
myLastReceivedRows = arrivedPacket.newRows;
if (myLastFiredRows != null) {
retVal = new DataPacket(myLastFiredRows, new BlueTable(myLastFiredRows.schema),
new BlueTable(myLastFiredRows.schema));
foreach (IBlueRow r in arrivedPacket.deletedRows)
if (myLastFiredRows.containsID((int)r["id"])) {
var deletedRows = new Lazy<BlueTable>(() => (BlueTable)retVal.deletedRows);
foreach (IBlueRow r in arrivedPacket.deletedRows) {
if (myLastFiredRows.containsID(r.Id())) {
myLastFiredRows.deleteRow(r);
(retVal.deletedRows as BlueTable).addRow(r);
deletedRows.Value.addRow(r);
}
foreach (IBlueRow r in arrivedPacket.addedRows)
}
var addedRows = new Lazy<BlueTable>(() => (BlueTable)retVal.addedRows);
foreach (IBlueRow r in arrivedPacket.addedRows) {
if (myFilter.filter(r)) {
myLastFiredRows.addRow(r);
(retVal.addedRows as BlueTable).addRow(r);
addedRows.Value.addRow(r);
}
}
} else {
myLastFiredRows = new BlueTable(arrivedPacket.schema);
myLastFiredRows = new BlueTable(arrivedPacket.Schema);
retVal = new DataPacket(myLastFiredRows, myLastFiredRows, new BlueTable(myLastFiredRows.schema));
foreach (IBlueRow r in arrivedPacket.newRows)
if (myFilter.filter(r))
@@ -1,12 +1,13 @@
using System;
using BCG;
using Bts.DataStreamCore;
using Spark.Core.Diagnostics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using bts;
//using bts.SilverPine;
using BCG;
namespace bts.BlueOrb {
[DataStreamUserRespresentation("GroupByStream")]
@@ -14,20 +15,21 @@ namespace bts.BlueOrb {
public interface INonIncGroupByEvaluator {
// grouped_rows
IBlueRowCollection evaluate(IDictionary<int, List<IBlueRow>> grouped_rows);
string[] get_group_by_cols();
IBlueRowCollection? evaluate(IDictionary<int, List<IBlueRow>> grouped_rows);
string[]? get_group_by_cols();
}
private class DelNonIncGroupByEvaluator : INonIncGroupByEvaluator {
Func<string[]> _groupby_cols_func;
Func<string[]?> _groupby_cols_func;
Func<List<IBlueRow>, List<IBlueRow>> _evaluate_func;
public DelNonIncGroupByEvaluator(Func<string[]> groupby_cols_func,
public DelNonIncGroupByEvaluator(Func<string[]?> groupby_cols_func,
Func<List<IBlueRow>, List<IBlueRow>> evaluate_func) {
_groupby_cols_func = groupby_cols_func;
_evaluate_func = evaluate_func;
}
public IBlueRowCollection evaluate(IDictionary<int, List<IBlueRow>> grouped_rows) {
BlueTable rv = null;
public IBlueRowCollection? evaluate(IDictionary<int, List<IBlueRow>> grouped_rows) {
BlueTable? rv = null;
foreach (var kv in grouped_rows) {
List<IBlueRow> g_rows = kv.Value;
List<IBlueRow> out_rows = _evaluate_func.Invoke(g_rows);
@@ -39,17 +41,19 @@ namespace bts.BlueOrb {
}
return rv;
}
public string[] get_group_by_cols() {
public string[]? get_group_by_cols() {
return _groupby_cols_func();
}
}
private ViewStream _main_stream;
private INonIncGroupByEvaluator _groupby_func;
private BlueRowHasher _row_hasher;
private string[] _groupby_cols;
ViewStream? _main_stream;
INonIncGroupByEvaluator? _groupby_func;
BlueRowHasher? _row_hasher;
string[]? _groupby_cols;
private Stopwatch _timer = new();
private int _n_total_fires = 0, _n_expensive_fires = 0;
IDisposable? subscription;
public GroupByStream(ViewStream main_stream, INonIncGroupByEvaluator groupby_func) {
_main_stream = main_stream;
@@ -58,7 +62,7 @@ namespace bts.BlueOrb {
_row_hasher = new BlueRowHasher(_groupby_cols == null ? 0 : _groupby_cols.Length);
}
public GroupByStream(ViewStream main_stream, Func<string[]> groupby_cols_func,
public GroupByStream(ViewStream main_stream, Func<string[]?> groupby_cols_func,
Func<List<IBlueRow>, List<IBlueRow>> evaluate_func)
: this(main_stream, new DelNonIncGroupByEvaluator(groupby_cols_func, evaluate_func)) { }
@@ -68,34 +72,42 @@ namespace bts.BlueOrb {
// this is the main constructor that does everything
public GroupByStream(ViewStream parent_str, string groupby_cols, string standard_group_by_ops, string optional_sort_col) {
MultiRowOpHelper std_group_by = MultiRowOpHelper.parse_ops(standard_group_by_ops);
Func<string[]> groupby_cols_func = () => {
if (String.IsNullOrEmpty(groupby_cols))
return null;
return groupby_cols.Split(',').Select(x => x.Trim()).ToArray();
};
Func<List<IBlueRow>, List<IBlueRow>> evaluate_func = (group_rows) => {
if (!String.IsNullOrEmpty(optional_sort_col))
group_rows.Sort((r1, r2) => BlueDataUtility.compare_rows(r2, r1, optional_sort_col));
// this si where the group by aggregation happens
IBlueRow rv = MultiRowOpHelper.group_by_compute(group_rows, std_group_by);
IBlueRow? rv = MultiRowOpHelper.group_by_compute(group_rows, std_group_by);
if (rv == null)
return new List<IBlueRow>();
return new IBlueRow[] { rv }.ToList();
};
ViewStream rs = new GroupByStream(parent_str, groupby_cols_func, evaluate_func);
mySetRealSource(rs);
string[]? groupby_cols_func() {
if (string.IsNullOrEmpty(groupby_cols)) {
return null;
}
return groupby_cols.Split(',').Select(x => x.Trim()).ToArray();
}
}
public GroupByStream(ViewStream parent_str, string standard_group_by_text) :
this(parent_str, String.Empty, standard_group_by_text) {
}
protected override void myOnFirstSubscriber() {
Log.isnull(subscription);
subscription = ExceptionAssert.MemberNotNull(_main_stream).Subscribe(_main_stream_onchange);
}
protected override void myOnFirstSubscriber() { _main_stream.onChange += _main_stream_onchange; }
protected override void myOnLastSubscriber() { _main_stream.onChange -= _main_stream_onchange; }
protected override void myOnLastSubscriber() {
subscription?.Dispose();
subscription = null;
}
private void _main_stream_onchange(object nv) {
DataPacket dp = nv as DataPacket;
Log.notnull(_groupby_func);
var dp = (IDataPacket)nv;
///grouping together
_timer.Restart();
IDictionary<int, List<IBlueRow>> grouped_rows = (_groupby_cols == null || _groupby_cols.Length == 0) ?
@@ -109,7 +121,7 @@ namespace bts.BlueOrb {
// Log.log(bts.Log.Level.Info, bts.log.Subsystem.gen, String.Format("Time to group {0} rows into {1} groups = {2}", dp.newRows.Count, grouped_rows.Count, _timer.lastIntervalTime));
/// reducing
_timer.Restart();
IBlueRowCollection total_state = _groupby_func.evaluate(grouped_rows);
IBlueRowCollection? total_state = _groupby_func.evaluate(grouped_rows);
if (total_state == null)
// mayeb returna n empty table ?
return;
@@ -121,7 +133,10 @@ namespace bts.BlueOrb {
Log.DataFlow.info(
$"Time to evaluate {grouped_rows.Count} groups {_timer.ElapsedMilliseconds}ms, ratio {_n_expensive_fires}/{_n_total_fires}");
}
myFireEvent(new DataPacket(total_state, total_state, myLastValue == null ? new BlueTable(total_state.schema) : (myLastValue as DataPacket).newRows));
var deletedRows = myLastValue is null
? new BlueTable(total_state.schema)
: ((IDataPacket)myLastValue).newRows;
myFireEvent(new DataPacket(total_state, total_state, deletedRows));
}
}
}
@@ -1,41 +1,44 @@
namespace bts.BlueOrb {
using BCG;
using RowHash = System.Int32;
using Bts.DataStream;
using Spark.Core.Diagnostics;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Data.Entity.Core.Mapping;
using RowHash = System.Int32;
[DataStreamUserRespresentation("JoinStream")]
public class SimpleJoinStream : ViewStream {
public class JoinBookkeepingData {
// initialized in cons
private readonly List<string> _join_col_names;
private readonly bool _is_left;
readonly string[] _join_col_names;
private readonly BlueRowHasher _hasher;
// initialized on first udpate
private IBlueTableSchema _schema;
private int[] _join_cols;
IBlueTableSchema? _schema;
int[]? _join_cols;
private IDictionary<RowHash, List<IBlueRow>> _hash_row_map = new Dictionary<RowHash, List<IBlueRow>>();
public JoinBookkeepingData(ViewStream vs, List<string> join_cols, bool is_left, BlueRowHasher row_hasher) {
_join_col_names = join_cols.Where(c => !String.IsNullOrEmpty(c)).ToList();
_is_left = is_left;
public JoinBookkeepingData(ViewStream vs, List<string> join_cols, BlueRowHasher row_hasher) {
_join_col_names = join_cols.Where(c => !string.IsNullOrEmpty(c)).ToArray();
_hasher = row_hasher;
}
public IBlueTableSchema schema => _schema;
[NotNullIfNotNull(nameof(_schema))]
public IBlueTableSchema? schema => _schema;
public IDictionary<RowHash, List<IBlueRow>> rows => _hash_row_map;
public List<IBlueRow> get_matching_rows(int hash) {
List<IBlueRow> rv = null;
_hash_row_map.TryGetValue(hash, out rv);
return rv;
}
[MemberNotNull(nameof(_schema))]
public IBlueTableSchema RequireSchema() =>
ExceptionAssert.MemberNotNull(_schema);
public List<IBlueRow>? get_matching_rows(int hash) =>
_hash_row_map.GetValueOrDefault(hash);
private RowHash _get_hash(IBlueRow r) {
if (_join_cols == null || _join_cols.Length == 0) {
@@ -44,16 +47,15 @@
return _hasher.get_hash(r, _join_cols);
}
public void update_data(DataPacket dp) {
public void update_data(IDataPacket dp) {
if (!ready) {
_schema = dp.newRows.schema;
_join_cols = _join_col_names.Count == 0 ? new int[] { } : _join_col_names.Select(n => dp.schema[n].colNo).ToArray();
_join_cols = _schema.ResolveIndices(_join_col_names);
}
_hash_row_map.Clear();
foreach (IBlueRow r in dp.newRows) {
int hash = _get_hash(r);
List<IBlueRow> hash_rows = null;
if (!_hash_row_map.TryGetValue(hash, out hash_rows)) {
if (!_hash_row_map.TryGetValue(hash, out var hash_rows)) {
hash_rows = new List<IBlueRow>();
_hash_row_map.Add(hash, hash_rows);
}
@@ -61,6 +63,7 @@
}
}
[MemberNotNullWhen(true, nameof(_schema))]
public bool ready {
get {
return _schema != null;
@@ -71,8 +74,7 @@
private ViewStream _ls, _rs;
private JoinBookkeepingData _ldata, _rdata;
private ViewStreamDatabase _vsd;
private IBlueTableSchema _schema = null;
IBlueTableSchema? _schema;
public SimpleJoinStream(ViewStream ls, string ljc, ViewStream rs, string rjc) :
this(ViewStreamDatabase.instance, ls, ljc, rs, rjc) { }
@@ -85,8 +87,8 @@
Log.assert(lj_col_list.Count == rj_col_list.Count);
int n_cols = lj_col_list.Count;
BlueRowHasher hasher = new BlueRowHasher(n_cols);
_ldata = new JoinBookkeepingData(ls, lj_col_list, true, hasher);
_rdata = new JoinBookkeepingData(rs, rj_col_list, false, hasher);
_ldata = new JoinBookkeepingData(ls, lj_col_list, hasher);
_rdata = new JoinBookkeepingData(rs, rj_col_list, hasher);
}
protected override void myOnFirstSubscriber() {
@@ -95,13 +97,13 @@
}
private void _ls_onchange(object dp_obj) {
DataPacket dp = dp_obj as DataPacket;
var dp = (IDataPacket)dp_obj;
_ldata.update_data(dp);
_form_and_fire();
}
private void _rs_onchange(object dp_obj) {
DataPacket dp = dp_obj as DataPacket;
var dp = (IDataPacket)dp_obj;
_rdata.update_data(dp);
_form_and_fire();
}
@@ -111,20 +113,24 @@
_rs.onChange -= _rs_onchange;
}
[MemberNotNull(nameof(_schema))]
private void _build_schema() {
if (_schema != null)
return;
List<ColumnInfo> cis = new List<ColumnInfo>();
cis.Add(new ColumnInfo("id", 0, TypeCode.Int32));
foreach (ColumnInfo ci in _ldata.schema.columnInfo) {
string col_name = _rdata.schema.contains_column(ci.colName) ? $"left_{ci.colName}" : ci.colName;
var lschema = Log.notnull(_ldata.schema);
var rschema = Log.notnull(_rdata.schema);
var cis = new List<ColumnInfo> {
new("id", 0, TypeCode.Int32)
};
foreach (ColumnInfo ci in lschema.columnInfo) {
string col_name = rschema.contains_column(ci.colName) ? $"left_{ci.colName}" : ci.colName;
cis.Add(new ColumnInfo(col_name, cis.Count, ci.colType));
}
foreach (ColumnInfo ci in _rdata.schema.columnInfo) {
string col_name = _ldata.schema.contains_column(ci.colName) ? $"right_{ci.colName}" : ci.colName;
foreach (ColumnInfo ci in rschema.columnInfo) {
string col_name = lschema.contains_column(ci.colName) ? $"right_{ci.colName}" : ci.colName;
cis.Add(new ColumnInfo(col_name, cis.Count, ci.colType));
}
_schema = new BlueTableSchema($"{_ldata.schema.tableName}_join_{_rdata.schema.tableName}", cis.ToArray());
_schema = new BlueTableSchema($"{lschema.tableName}_join_{rschema.tableName}", cis.ToArray());
}
private void _form_and_fire() {
@@ -133,34 +139,11 @@
_build_schema();
List<object[]> res_rows = new List<object[]>();
Action<object[], IBlueRow, bool> copy_row = (rval, r, is_left) => {
int offset = 1;
JoinBookkeepingData sdata = _ldata;
if (is_left) {
offset = 1;
sdata = _ldata;
} else {
sdata = _rdata;
offset = 1 + _ldata.schema.columnInfo.Length;
}
for (int i = 0; i < sdata.schema.columnInfo.Length; i++) {
rval[offset + i] = r[i];
}
};
Func<int, IBlueRow, object[]> build_row_array = (id, l_row) => {
object[] rv = new object[_schema.columnNames.Length];
for (int i = 0; i < _schema.columnNames.Length; i++) {
rv[i] = DBNull.Value;
}
rv[0] = id;
copy_row(rv, l_row, true);
return rv;
};
// this is where the join happens
foreach (var kv in _ldata.rows) {
RowHash hash = kv.Key;
List<IBlueRow> l_rows = kv.Value;
List<IBlueRow> r_rows = _rdata.get_matching_rows(hash);
List<IBlueRow>? r_rows = _rdata.get_matching_rows(hash);
foreach (IBlueRow lr in l_rows) {
if (r_rows != null) {
@@ -179,8 +162,33 @@
foreach (object[] rval in res_rows) {
rv.addRow(new BlueRow(_schema, rval));
}
var dp = BlueDataUtility.build_dp(rv, myLastValue as DataPacket);
var dp = BlueDataUtility.build_dp(rv, myLastValue as IDataPacket);
myFireEvent(dp);
object[] build_row_array(int id, IBlueRow l_row) {
object[] rv = new object[_schema.columnNames.Length];
for (int i = 0; i < _schema.columnNames.Length; i++) {
rv[i] = DBNull.Value;
}
rv[0] = id;
copy_row(rv, l_row, true);
return rv;
}
void copy_row(object?[] rval, IBlueRow r, bool is_left) {
int offset = 1;
JoinBookkeepingData sdata = _ldata;
if (is_left) {
offset = 1;
sdata = _ldata;
} else {
sdata = _rdata;
offset = 1 + _ldata.RequireSchema().columnInfo.Length;
}
for (int i = 0; i < sdata.RequireSchema().columnInfo.Length; i++) {
rval[offset + i] = r[i];
}
}
}
}
@@ -45,8 +45,8 @@ namespace bts.BlueOrb {
}
// aggregates multiple rows into one - ie does group_by compute
public static IBlueRow group_by_compute(List<IBlueRow> rows, MultiRowOpHelper parameters) {
if (rows.Count() == 0) {
public static IBlueRow? group_by_compute(List<IBlueRow> rows, MultiRowOpHelper parameters) {
if (rows.Count == 0) {
return null;
}
@@ -73,8 +73,8 @@ namespace bts.BlueOrb {
}
// aggregates multiple rows into one, used by MultiRowRollingMathStream
public static IBlueRow group_by_compute(List<IBlueRow> rows, int start_idx, int n_rows, MultiRowOpHelper parameters) {
if (rows.Count() == 0) {
public static IBlueRow? group_by_compute(List<IBlueRow> rows, int start_idx, int n_rows, MultiRowOpHelper parameters) {
if (rows.Count == 0) {
return null;
}
IBlueRow ir = rows.ElementAt(start_idx);
@@ -104,8 +104,8 @@ namespace bts.BlueOrb {
// rolling_rows are the rolling window of rows. the 0th row is the one thats gettin
// calculated. rows 1 - n-1 are its window rows. the schema is based on the operations.
public IBlueRow rolling_calc(List<IBlueRow> rolling_rows) {
if (rolling_rows.Count() == 0) {
public IBlueRow? rolling_calc(List<IBlueRow> rolling_rows) {
if (rolling_rows.Count == 0) {
return null;
}
IBlueRow ir = rolling_rows.ElementAt(0);
@@ -156,7 +156,6 @@ namespace bts.BlueOrb {
double first = col_vals.First();
double last = col_vals.Last();
return ((first - last) / last) * 100.0;
return col_vals.First() - col_vals.Last();
}
default:
// TODO
@@ -1,8 +1,7 @@
namespace bts.BlueOrb {
using BCG;
using System.Collections.Generic;
using System.Net;
using System;
[DataStreamUserRespresentation("MultiRowRollingMathStream")]
public class MultiRowRollingMathStream : ViewStream {
@@ -24,11 +23,12 @@
}
private void _parent_str_onchange(object dp_obj) {
DataPacket dp = dp_obj as DataPacket;
var dp = (IDataPacket)dp_obj;
var rows = dp.newRows.to_list();
BlueTable out_table = null;
BlueTable? out_table = null;
for (int i = 0; i < rows.Count; i++) {
var out_r = MultiRowOpHelper.group_by_compute(rows, i, _rolling_window_sz, _op);
var out_r = MultiRowOpHelper.group_by_compute(rows, i, _rolling_window_sz, _op)
?? throw new InvalidOperationException("group_by_compute returned null row");
if (out_table == null)
out_table = new BlueTable(out_r.schema);
out_table.addRow(out_r);
@@ -1,5 +1,8 @@
namespace bts.BlueOrb {
using BCG;
using Spark.Core.Diagnostics;
using System;
using System.Collections;
using System.Collections.Generic;
@@ -54,7 +57,7 @@ namespace bts.BlueOrb {
public bool IsReadOnly { get { return true; } }
public object this[object key] {
public object? this[object key] {
get {
if (key is string)
return this[(string)key];
@@ -63,16 +66,15 @@ namespace bts.BlueOrb {
set { throw new NotSupportedException("The IBlueRow is readonly"); }
}
public object this[int index] {
public object? this[int index] {
get {
return this[schema.columnInfo[index].colName];
}
}
public object this[string col_name] {
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)) {
if (_project_data.mapped_to_orig_col_map.TryGetValue(col_name, out var mapped_to_col)) {
return _row[mapped_to_col];
}
return _row[col_name];
@@ -89,7 +91,8 @@ namespace bts.BlueOrb {
}
}
public void Add(object key, object value) { throw new NotSupportedException("The IBlueRow is readonly"); }
public void Add(object key, object? value) =>
throw new NotSupportedException();
public void Clear() { throw new NotSupportedException("The IBlueRow is readonly"); }
@@ -114,7 +117,7 @@ namespace bts.BlueOrb {
private ViewStream _stream;
private string _project_expression;
private ProjectData _project_data = null;
ProjectData? _project_data;
//public ProjectData
public NewProjectStream(ViewStream vs, string project_expression) {
_stream = vs;
@@ -128,9 +131,8 @@ namespace bts.BlueOrb {
return _project_data.out_schema;
}
public IBlueRow map(IBlueRow row) {
return new NewProjectRow(_project_data, row);
}
public IBlueRow map(IBlueRow row) =>
new NewProjectRow(ExceptionAssert.MemberNotNull(_project_data), row);
// this is where most of the logic is, in terms of translating cols
private static ProjectData _create_project_data(IBlueTableSchema input_schema,
@@ -3,7 +3,6 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<Version>$(SparkVersion)</Version>
</PropertyGroup>
<ItemGroup>
@@ -23,16 +23,16 @@ public static class DataStreamExtensions {
public static ViewStream AsViewStream<T>(this IObservable<IDataPacket<T>> source, string? name = null, ILogger? logger = null) where T : IBlueRow =>
source as ViewStream ?? new ObservableViewStream(source.Select(dp => new DataPacket(dp.newRows, dp.addedRows, dp.deletedRows)), name, logger);
public static IObservable<DataPacket> AsObservable(this ViewStream source) {
return source as IObservable<DataPacket> ?? Observable.Create<DataPacket>(Subscribe);
public static IObservable<IDataPacket> AsObservable(this ViewStream source) {
return source as IObservable<IDataPacket> ?? Observable.Create<IDataPacket>(Subscribe);
IDisposable Subscribe(IObserver<DataPacket> observer) {
IDisposable Subscribe(IObserver<IDataPacket> observer) {
source.onChange += OnChange;
return Disposable.Create(() => source.onChange -= OnChange);
void OnChange(object? newValue) =>
observer.OnNext(newValue as DataPacket ?? throw new ArgumentException(
$"Expected DataPacket, got {newValue?.GetType()}", nameof(newValue)));
observer.OnNext(newValue as IDataPacket ?? throw new ArgumentException(
$"Expected IDataPacket, got {newValue?.GetType()}", nameof(newValue)));
}
}
@@ -1,14 +1,13 @@
namespace Bts.DataStream;
using BCG;
using BCG.Extensions;
using BCG.Utilities.General;
using bts;
using bts.collections;
using Bts.DataStreamCore;
using Spark.Core.Collections;
using Spark.Core.Disposables;
using System;
@@ -88,8 +88,7 @@ namespace BCG {
return Task.CompletedTask;
}
private void _on_str(DataPacket dp)
{
void _on_str(IDataPacket dp) {
foreach (IBlueRow r in dp.newRows)
{
string name = r.get<string>("name");
@@ -9,7 +9,7 @@ namespace BCG {
[DataStreamUserRespresentation("remoteQuery")]
public class RemoteQueryStream : ViewStream {
private readonly string _name, _stream_exp;
private PublisherCore _publisher_core = new PublisherCore();
private PublisherCore _publisher_core = PublisherCore.Create();
private ViewStream _source_str;
public RemoteQueryStream(params string[] lines) {
@@ -2,9 +2,6 @@ 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;
@@ -28,4 +25,4 @@ namespace bts {
}
}
}
}
@@ -1,33 +1,28 @@
using Spark.Core.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
namespace BCG {
public class AddColumnsStream : ViewStream {
public static Tuple<string, Type, object> parse_single_tok(string exp) {
public static (string Name, Type Type, object Value) parse_single_tok(string exp) {
string[] toks = exp.Split(':');
string col_name = toks[0].Trim();
string col_value = toks[1].Trim();
Tuple<Type, object> tup = BlueDataUtility.guess_type(col_value);
return Tuple.Create(col_name, tup.Item1, tup.Item2);
return (col_name, tup.Item1, tup.Item2);
}
public static List<Tuple<string, Type, object>> parse_exp(string exp) {
string[] toks = exp.Split(",");
List<Tuple<string, Type, object>> rv = new List<Tuple<string, Type, object>>();
foreach (string s in toks) {
var tup = parse_single_tok(s.Trim());
rv.Add(tup);
}
return rv;
}
public static List<(string Name, Type Type, object Value)> parse_exp(string exp) =>
exp.Split(",").ToList(t => parse_single_tok(t.Trim()));
private Tuple<string, Type, object> _new_col;
private List<Tuple<string, Type, object>> _new_col_map;
private IBlueTableSchema _out_schema;
readonly List<(string Name, Type Type, object Value)> _new_col_map;
IBlueTableSchema? _out_schema;
public AddColumnsStream(ViewStream vs, string col_def) {
_new_col_map = parse_exp(col_def);
ViewStream rs = new MapStream(vs, (IBlueTableSchema s) => _get_schema(s), (IBlueRow r) => _map(r));
ViewStream rs = new MapStream(vs, _get_schema, _map);
mySetRealSource(rs);
}
@@ -44,7 +39,7 @@ namespace BCG {
private IBlueRow _map(IBlueRow r) {
MutableBlueRow rv = new MutableBlueRow(_get_schema(r.schema), r);
foreach (var m in _new_col_map) {
rv.setValue(m.Item1, m.Item3);
rv.setValue(m.Name, m.Value);
}
return rv;
}
@@ -1,9 +1,10 @@
using System;
using mbts;
using Spark.Core.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using mbts;
namespace BCG
{
@@ -33,7 +34,7 @@ namespace BCG
private void _stream_onChange(object newValue)
{
DataPacket dp = newValue as DataPacket;
var dp = (IDataPacket)newValue;
if (dp != null && dp.newRows.Count > 0)
{
_stream.onChange -= _stream_onChange;
@@ -42,8 +43,8 @@ namespace BCG
}
}
public delegate void IncrementValues(object[] current_values, object[] values_to_inc);
public delegate string GetColumnPrefix(object[] transposing_col_values);
public delegate void IncrementValues(object?[] current_values, object?[] values_to_inc);
public delegate string GetColumnPrefix(object?[] transposing_col_values);
public delegate string GetColumnSuffix(string col_name);
private GetColumnSuffix _get_column_suffix = new GetColumnSuffix((cn) => { return cn; });
@@ -51,33 +52,31 @@ namespace BCG
private IncrementValues _increment_values;
private GetColumnPrefix _get_column_prefix;
private IBlueTableSchema _schema;
IBlueTableSchema? _schema;
private string[] _group_by_cols;
private Pair<string, Type>[] _cols_per_transposed;
private string[] _transposing_cols;
private int[] _transposing_col_indices;
int[]? _transposing_col_indices;
private Comparison<Pair<int, object[]>> _transpsed_col_value_comparer_wrapper;
Comparison<Pair<int, object?[]>>? _transpsed_col_value_comparer_wrapper;
public YXTranspositionStream(ViewStream stream, string transposed_cols_group, string cols_per_transposed, string group_by_cols,
IncrementValues increment_values_del, GetColumnPrefix get_column_prefix_del, GetColumnSuffix get_column_suffix_del, Comparison<object[]> transposed_col_value_comparer)
IncrementValues increment_values_del, GetColumnPrefix get_column_prefix_del, GetColumnSuffix get_column_suffix_del, Comparison<object?[]> transposed_col_value_comparer)
: this(stream, transposed_cols_group, cols_per_transposed, group_by_cols, increment_values_del,
get_column_prefix_del, get_column_suffix_del, transposed_col_value_comparer, true)
{ }
public YXTranspositionStream(ViewStream stream, string transposed_cols_group, string cols_per_transposed, string group_by_cols,
IncrementValues increment_values_del, GetColumnPrefix get_column_prefix_del, GetColumnSuffix get_column_suffix_del, Comparison<object[]> transposed_col_value_comparer, bool only_fire_once)
IncrementValues increment_values_del, GetColumnPrefix get_column_prefix_del, GetColumnSuffix get_column_suffix_del, Comparison<object?[]> transposed_col_value_comparer, bool only_fire_once)
{
if (get_column_suffix_del != null)
_get_column_suffix = get_column_suffix_del;
if (transposed_col_value_comparer != null)
{
_transpsed_col_value_comparer_wrapper = new Comparison<Pair<int, object[]>>((p1,p2) =>
{
return transposed_col_value_comparer(p1.second, p2.second);
});
_transpsed_col_value_comparer_wrapper = new((p1, p2) =>
transposed_col_value_comparer(ExceptionAssert.NotNull(p1.second), ExceptionAssert.NotNull(p2.second)));
}
_group_by_cols = group_by_cols.Split(' ');
_transposing_cols = transposed_cols_group.Split(' ');
@@ -106,7 +105,7 @@ namespace BCG
col_info.Add(new ColumnInfo(p.first, col_index++, p.second));
foreach (string tc_prefix in tc_prefixes)
foreach (Pair<string, Type> p in _cols_per_transposed)
col_info.Add(new ColumnInfo(_get_full_column_name(tc_prefix, p.first), col_index++, p.second));
col_info.Add(new ColumnInfo(_get_full_column_name(tc_prefix, p.first ?? string.Empty), col_index++, p.second));
IBlueTableSchema schema = new BlueTableSchema(col_info.ToArray(), "xy_transposed_" + table_name);
if (_schema == null)
_schema = schema;
@@ -130,19 +129,14 @@ namespace BCG
public IBlueRowCollection evaluate(IDictionary<int, List<IBlueRow>> grouped_rows)
{
Dictionary<int, Dictionary<int, object[]>> all_tc_infos_and_values = new Dictionary<int, Dictionary<int, object[]>>();
Dictionary<int, object[]> group_by_cols_value_dict = new Dictionary<int, object[]>();
var all_tc_infos_and_values = new Dictionary<int, Dictionary<int, object?[]>>();
var group_by_cols_value_dict = new Dictionary<int, object?[]>();
BlueRowHasher hasher = new BlueRowHasher(_transposing_cols.Length);
Pair<string, Type>[] group_by_col_info = new Pair<string, Type>[_group_by_cols.Length];
string table_name = string.Empty;
if (grouped_rows.Count > 0)
{
IBlueTableSchema schema = null;
foreach (KeyValuePair<int, List<IBlueRow>> kvp in grouped_rows)
{
schema = kvp.Value[0].schema;
break;
}
var schema = grouped_rows.Values.First()[0].schema;
table_name = schema.tableName;
_transposing_col_indices = BlueDataUtility.get_column_indices(schema, _transposing_cols);
int[] group_by_indices = BlueDataUtility.get_column_indices(schema, _group_by_cols);
@@ -155,23 +149,22 @@ namespace BCG
else
return new BlueTable(new BlueTableSchema(new ColumnInfo[] { new ColumnInfo("id", 0, typeof(int)) }, table_name));
Dictionary<int, string> tc_prefixes = new Dictionary<int, string>();
List<Pair<int, object[]>> tc_values = new List<Pair<int, object[]>>();
var tc_values = new List<Pair<int, object?[]>>();
foreach (KeyValuePair<int, List<IBlueRow>> kvp in grouped_rows)
{
//Dictionary of trans_col_group_hash -> pair: first=trans_col_group_values second=per_transposing_col_values
Dictionary<int, object[]> incrementing_values = new Dictionary<int, object[]>();
var incrementing_values = new Dictionary<int, object?[]>();
foreach (IBlueRow r in kvp.Value)
{
int hash = hasher.get_hash(r, _transposing_col_indices);
object[] values;
if (!incrementing_values.TryGetValue(hash, out values))
if (!incrementing_values.TryGetValue(hash, out var values))
{
incrementing_values.Add(hash, _get_per_transposing_col_values(r));
string prefix = _get_column_prefix(_get_transposing_col_values(r));
if (!tc_prefixes.ContainsKey(hash))
{
tc_prefixes.Add(hash, prefix);
tc_values.Add(new Pair<int,object[]>(hash, _get_transposing_col_values(r)));
tc_values.Add(new(hash, _get_transposing_col_values(r)));
}
}
else
@@ -194,18 +187,18 @@ namespace BCG
_set_schema(prefixes, group_by_col_info, table_name);
BlueTable result = new BlueTable(_schema);
int id = 1;
foreach (KeyValuePair<int, Dictionary<int, object[]>> kvp in all_tc_infos_and_values)
foreach (var kvp in all_tc_infos_and_values)
{
MutableBlueRow mbr = new MutableBlueRow(_schema);
mbr.setValue("id", id++);
for (int i = 0; i < _group_by_cols.Length; i++)
mbr.setValue(_group_by_cols[i], group_by_cols_value_dict[kvp.Key][i]);
foreach (KeyValuePair<int, object[]> tc_cols in kvp.Value)
foreach (var tc_cols in kvp.Value)
{
string prefix = tc_prefixes[tc_cols.Key];
for (int i = 0; i < _cols_per_transposed.Length; i++)
{
string column = _get_full_column_name(prefix, _cols_per_transposed[i].first);
string column = _get_full_column_name(prefix, _cols_per_transposed[i].first ?? string.Empty);
if(mbr.schema.columnNames.Contains(column))
mbr.setValue(column, tc_cols.Value[i]);
}
@@ -217,28 +210,25 @@ namespace BCG
#endregion
private object[] _get_transposing_col_values(IBlueRow row)
{
object[] values = new object[_transposing_cols.Length];
object?[] _get_transposing_col_values(IBlueRow row) {
var values = new object?[_transposing_cols.Length];
for (int i = 0; i < _transposing_cols.Length; i++)
values[i] = row[_transposing_cols[i]];
return values;
}
private object[] _get_per_transposing_col_values(IBlueRow row)
{
object[] values = new object[_cols_per_transposed.Length];
object?[] _get_per_transposing_col_values(IBlueRow row) {
var values = new object?[_cols_per_transposed.Length];
for (int i = 0; i < _cols_per_transposed.Length; i++)
values[i] = row[_cols_per_transposed[i].first];
values[i] = row[ExceptionAssert.NotNull(_cols_per_transposed[i].first)];
return values;
}
private object[] _get_group_by_cols_values(IBlueRow row)
{
object[] values = new object[_group_by_cols.Length];
object?[] _get_group_by_cols_values(IBlueRow row) {
var values = new object?[_group_by_cols.Length];
for (int i = 0; i < values.Length; i++)
values[i] = row[_group_by_cols[i]];
return values;
}
}
}
}
@@ -1,22 +1,19 @@
using System;
using Spark.Core.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BCG
{
public class DerivativeStream : ViewStream
{
private IBlueTableSchema mySchema;
IBlueTableSchema? mySchema;
private string myDerivandColumn;
private string myOutputColumn;
private string myKeyColumn;
private DateTime myLastPacketArrival = DateTime.MinValue;
private ViewStream myDataSource;
private IDictionary<string, double> myPreviousValues;
Dictionary<string, double>? myPreviousValues;
public DerivativeStream(ViewStream input, string keyColumn, string columnToDifferentiate, string outputColName)
{
@@ -39,9 +36,9 @@ namespace BCG
void myDataSource_onChange(object newValue)
{
DataPacket dp = (DataPacket)newValue;
var dp = (IDataPacket)newValue;
if (myLastPacketArrival == DateTime.MinValue)
mySchema = myBuildOutputSchema(dp.schema);
mySchema = myBuildOutputSchema(dp.Schema);
else
{
DateTime now = DateTime.Now;
@@ -55,7 +52,7 @@ namespace BCG
else
{
IBlueRowCollection deleted, added;
BlueDataUtility.computeDifferences(thisVersion, ((DataPacket)myLastValue).newRows, out deleted, out added);
BlueDataUtility.computeDifferences(thisVersion, ((IDataPacket)myLastValue).newRows, out deleted, out added);
myFireEvent(new DataPacket(thisVersion, added, deleted));
}
}
@@ -64,12 +61,13 @@ namespace BCG
protected IBlueRow myMakeRow(IBlueRow r, double timeScale)
{
ExceptionAssert.NotNull(mySchema, myPreviousValues);
object[] outValues = new object[mySchema.columnInfo.Length];
r.Values.CopyTo(outValues, 0);
object derivand = r[myDerivandColumn];
double lastValue = default(double);
if (myPreviousValues.TryGetValue(r[myKeyColumn].ToString(), out lastValue) && derivand != null && derivand != DBNull.Value)
var derivand = r[myDerivandColumn];
var key = getRowKey(r);
if (myPreviousValues.TryGetValue(key, out double lastValue) && derivand != null && derivand != DBNull.Value)
outValues[mySchema.columnInfo.Length - 1] = (Convert.ToDouble(derivand) - lastValue) * timeScale;
else
outValues[mySchema.columnInfo.Length - 1] = 0.0;
@@ -84,16 +82,19 @@ namespace BCG
cols[cols.Length - 1] = new ColumnInfo(myOutputColumn, cols.Length - 1, typeof(double));
return new BlueTableSchema("derviative of " + inSchema.tableName, cols);
}
protected void myStoreNewPacketInfo(DataPacket dp)
{
protected void myStoreNewPacketInfo(IDataPacket dp) {
myPreviousValues = new Dictionary<string, double>();
myLastPacketArrival = DateTime.Now;
foreach (IBlueRow row in dp.newRows)
{
object derivand = row[myDerivandColumn];
var derivand = row[myDerivandColumn];
if (derivand != null && derivand != DBNull.Value)
myPreviousValues[row[myKeyColumn].ToString()] = Convert.ToDouble(derivand);
myPreviousValues[getRowKey(row)] = Convert.ToDouble(derivand);
}
}
string getRowKey(IBlueRow row) =>
row[myKeyColumn]?.ToString() ?? throw new ArgumentException("Row key is null", nameof(row));
}
}
@@ -1,7 +1,9 @@
using System;
using System.Collections;
using mbts;
using Spark.Core.Collections;
using System;
using System.Collections.Generic;
using mbts;
namespace BCG
{
@@ -12,9 +14,9 @@ namespace BCG
{
ViewStream myLStream, myRStream;
DataPacket myLastR = null, myLastL = null;
BlueTable myLastFired = null;
DataPacket? myLastR;
DataPacket? myLastL;
BlueTable? myLastFired;
double myThreshold = .00005;
@@ -24,14 +26,14 @@ namespace BCG
public DiffStream(ViewStream v1, ViewStream v2, double thresh, params string[] ColumnsToMatch) :
this(null, v1, v2, thresh, ColumnsToMatch) { }
public DiffStream(ViewStreamDatabase db, ViewStream v1, ViewStream v2, double thresh, params string[] columnsToMatch)
public DiffStream(ViewStreamDatabase? db, ViewStream v1, ViewStream v2, double thresh, params string[] columnsToMatch)
{
myThreshold = thresh;
myLStream = v1;
myRStream = v2;
myColumnsToMatch = columnsToMatch;
}
public DiffStream(ViewStreamDatabase db, ViewStream v1, ViewStream v2, params string[] columnsToMatch)
public DiffStream(ViewStreamDatabase? db, ViewStream v1, ViewStream v2, params string[] columnsToMatch)
: this(db,v1,v2,.00005,columnsToMatch)
{
}
@@ -50,45 +52,22 @@ namespace BCG
myRStream.onChange -= myRChange;
}
struct ListComparer : IEqualityComparer<List<object>>
{
public bool Equals(List<object> x, List<object> y)
{
if (x.Count != y.Count)
return false;
for (int i = 0; i < x.Count; ++i)
if (!x[i].Equals(y[i]))
return false;
return true;
}
public int GetHashCode(List<object> obj)
{
int ret = 0;
for(int i = 0; i < obj.Count; ++i)
ret ^= obj[i].GetHashCode();
return ret;
}
}
void myHandleCallbacks()
{
DataPacket packet = null;
DataPacket? packet;
if (myLastL == null || myLastR == null)
{
packet = myLastL == null ? myLastR : myLastL;
if (packet != null)
if (packet is not null) {
myFireEvent(packet);
myLastFired = new BlueTable(packet.newRows);
myLastFired = new BlueTable(packet.newRows);
}
return;
}
BlueTable table = new BlueTable(myLastL.newRows.schema);
Dictionary<List<object>, Pair<BlueRow, BlueRow>> rowPairs = new Dictionary<List<object>, Pair<BlueRow, BlueRow>>(new ListComparer());
var rowPairs = new Dictionary<List<object>, Pair<BlueRow, BlueRow>>(EnumerableComparer.Create<object>());
foreach(BlueRow row in myLastL.newRows)
{
@@ -118,11 +97,7 @@ namespace BCG
}
catch (Exception) { }
}
Pair<BlueRow, BlueRow> pair;
rowPairs.TryGetValue(hash, out pair);
rowPairs.TryGetValue(hash, out var pair);
if (pair == null)
pair = new Pair<BlueRow, BlueRow>(null, row);
else
@@ -138,8 +113,7 @@ namespace BCG
if (pair.first == null || pair.second == null)
{
BlueRow row = pair.first == null ? pair.second : pair.first;
var row = pair.first ?? pair.second ?? throw new InvalidOperationException("Both rows in rowPair are null");
Dictionary<string, object> newRow = new Dictionary<string, object>();
foreach (ColumnInfo info in row.schema.columnInfo)
{
@@ -211,4 +185,4 @@ namespace BCG
}
}
}
@@ -14,10 +14,8 @@ namespace BCG
public DistinctRowEvaluator(string colMapExpression, string[] columnNames)
: base (colMapExpression, null, columnNames) {}
public override IBlueRow evaluate (DataPacket packet)
{
myOutputTable = myOutputTable == null ? new GroupByOutputTable (packet.schema) : myOutputTable;
public override IBlueRow? evaluate(IDataPacket packet) {
myOutputTable ??= new GroupByOutputTable(packet.Schema);
string hashString = GroupByStream.getRepString (packet, myGroupByCols);
if (packet.newRows.Count == 0)
//if there are no rows for this group we remove the group from the output table
@@ -5,7 +5,7 @@ namespace BCG
{
public class FileViewStream : ViewStream
{
private DataPacket myDp;
DataPacket? myDp;
public FileViewStream (string dataFileName,
string schemaFileName)
: this (dataFileName, schemaFileName, Int32.MaxValue)
@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BCG.Utilities.General;
using BCG.Utilities.General;
using System;
namespace BCG
{
public class DateBasedFilter: IDynamicStreamFilter, IWorker
@@ -26,20 +25,14 @@ namespace BCG
myReference = myTodaysDate.AddDays(-1 * myNDays);
}
public event FilterChangeDelegate onFilterChange;
public event FilterChangeDelegate? onFilterChange;
public bool filter(IBlueRow r)
{
if (DBNull.Value.Equals(r[myDateColumn]))
{
//return false;
return true; //it can be considered as our assumption whenever datecolumn is db null we return true
}
DateTime t = (DateTime)r[myDateColumn];
bool returnVallue = t < myReference ? false : true;
return returnVallue;
}
public bool filter(IBlueRow r) =>
r[myDateColumn] switch {
DBNull or null => true,
DateTime t => t >= myReference,
_ => throw new ArgumentException("Row has invalid date column value", nameof(r)),
};
public void doWork()
{
@@ -47,7 +40,7 @@ namespace BCG
{
myTodaysDate = DateTime.Today;
myReference = myTodaysDate.AddDays(-1 * myNDays);
onFilterChange();
onFilterChange?.Invoke();
}
}
}
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BCG.Utilities.General;
using BCG.Utilities.General;
using System;
namespace BCG
{
@@ -26,7 +24,7 @@ namespace BCG
#region IDynamicStreamFilter Members
public event FilterChangeDelegate onFilterChange;
public event FilterChangeDelegate? onFilterChange;
#endregion
@@ -34,7 +32,10 @@ namespace BCG
public bool filter(IBlueRow r)
{
DateTime rowDate = DBNull.Value.Equals (r[myDateColName]) ? DateTime.Now.Date : ((DateTime)r[myDateColName]).Date;
DateTime rowDate = r[myDateColName] switch {
DBNull or null => DateTime.Now.Date,
object obj => (DateTime)obj,
};
DateTime today = DateTime.Now.Date;
return rowDate > today ? true : !(today.Subtract(rowDate).Days >= myNPastTodayDays);
}
@@ -48,7 +49,7 @@ namespace BCG
if (DateTime.Now.Date != myLastCheckedTime.Date)
{
myLastCheckedTime = DateTime.Now;
onFilterChange();
onFilterChange?.Invoke();
}
}
@@ -1,18 +1,23 @@
using bts;
using Bts.DataStream;
using Bts.DataStream.Primitives.Filter;
using Bts.DataStreamCore;
using mbts.config;
using Spark.Core.Diagnostics;
using Spark.Core.Disposables;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text.RegularExpressions;
namespace BCG.StreamWorld.Addition {
[DataStreamUserRespresentation(false)]
public class FilterStream : ViewStream {
private ViewStream myBaseStream;
private BlueTable myBaseTable, myStateTable;
BlueTable? myBaseTable;
BlueTable? myStateTable;
private IStreamFilter myFilter;
public FilterStream(ViewStream vs)
@@ -25,8 +30,8 @@ namespace BCG.StreamWorld.Addition {
myBaseStream = vs;
myFilter = filter;
vs.ErrorChanged += OnError;
if (filter is IDynamicStreamFilter)
(filter as IDynamicStreamFilter).onFilterChange += new FilterChangeDelegate(myHandleFilterChange);
if (filter is IDynamicStreamFilter dfilter)
dfilter.onFilterChange += myHandleFilterChange;
}
@@ -36,8 +41,8 @@ namespace BCG.StreamWorld.Addition {
protected override void myOnLastSubscriber() {
myBaseStream.onChange -= new ChangeDelegate(myHandleChanges);
myBaseTable.clear();
myStateTable.clear();
myBaseTable?.clear();
myStateTable?.clear();
}
bool filterRow(IBlueRow r) {
@@ -52,17 +57,14 @@ namespace BCG.StreamWorld.Addition {
private void myHandleChanges(object newValue) {
try {
DataPacket dp = newValue as DataPacket;
if (myStateTable == null) {
bts.Log.assert(myBaseTable == null);
myStateTable = new BlueTable(dp.schema);
myBaseTable = new BlueTable(dp.schema);
}
BlueTable dels = new BlueTable(dp.schema),
adds = new BlueTable(dp.schema);
var dp = (IDataPacket)newValue;
var schema = dp.Schema;
init(schema);
var dels = new BlueTable(schema);
var adds = new BlueTable(schema);
foreach (IBlueRow r in dp.deletedRows) {
myBaseTable.deleteRow(r);
if (myStateTable.containsID((int)r["id"])) {
if (myStateTable.containsID(r.Id())) {
dels.addRow(r);
myStateTable.deleteRow(r);
}
@@ -85,6 +87,7 @@ namespace BCG.StreamWorld.Addition {
set {
myFilter = value;
if (myBaseTable != null) {
ExceptionAssert.NotNull(myStateTable);
IBlueRowCollection oldState = new BlueTable(myStateTable);
myStateTable.clear();
// If the filter throws an exception, we can rethrow it as a StreamFilterException
@@ -112,6 +115,17 @@ namespace BCG.StreamWorld.Addition {
//public string filterString { set { filter = new BooleanExpressionFilter(value); } }
private void myHandleFilterChange() { filter = myFilter; }
[MemberNotNull(nameof(myStateTable), nameof(myBaseTable))]
void init(IBlueTableSchema schema) {
if (myStateTable is null) {
Log.isnull(myBaseTable);
myStateTable = new BlueTable(schema);
myBaseTable = new BlueTable(schema);
} else {
Log.notnull(myBaseTable);
}
}
}
}
@@ -135,29 +149,24 @@ namespace BCG
}
#region IStreamFilter Members
public bool filter(IBlueRow dr)
{
bool rv = true;
for (int i = 0; i < myCols.Length; i++)
{
rv &= myRegExps[i].IsMatch(dr[myCols[i]] is DBNull ? "" : dr[myCols[i]].ToString());
if (!rv)
return rv;
}
return rv;
}
public bool filter(IBlueRow dr) =>
myCols.Zip(myRegExps).All(p => p.Second.IsMatch(dr[p.First] switch {
DBNull or null => string.Empty,
object obj => obj.ToString() ?? string.Empty
}));
#endregion
}
public class FilterStream : ViewStream
{
private BlueTable myLastFiredRows;
private IBlueRowCollection myLastReceivedRows;
private IStreamFilter myFilter;
private ViewStream myParentStream;
private string myFilterString;
private BCG.StreamWorld.Addition.FilterStream myFilterStream;
private bool myUseNewFilter = false;
BlueTable? myLastFiredRows;
IBlueRowCollection? myLastReceivedRows;
IStreamFilter? myFilter;
readonly ViewStream? myParentStream;
string? myFilterString;
readonly StreamWorld.Addition.FilterStream? myFilterStream;
readonly bool myUseNewFilter = false;
IDisposable? subscription;
#region constructors
public delegate bool OnFilter(IBlueRow r);
@@ -187,9 +196,10 @@ namespace BCG
{
myParentStream = vs;
myFilter = filter;
myFilterString = filter.ToString();
if (filter is IDynamicStreamFilter)
(filter as IDynamicStreamFilter).onFilterChange += new FilterChangeDelegate(myHandleFilterChange);
myFilterString = filter.ToString() ?? string.Empty;
if (filter is IDynamicStreamFilter dfilter) {
dfilter.onFilterChange += myHandleFilterChange;
}
}
}
@@ -213,18 +223,20 @@ namespace BCG
#endregion
#region overridden methods
protected override void myOnFirstSubscriber()
{ myParentStream.onChange += new ChangeDelegate(myHandleCallbacks); }
protected override void myOnFirstSubscriber() {
ExceptionAssert.IsNull(subscription);
subscription = ExceptionAssert.NotNull(myParentStream).Subscribe(myHandleCallbacks);
}
protected override void myOnLastSubscriber()
{
myLastFiredRows = null;
myParentStream.onChange -= new ChangeDelegate(myHandleCallbacks);
Disposable.Dispose(ref subscription);
}
protected override void myFireEvent(object o)
{
DataPacket dp = o as DataPacket;
var dp = (IDataPacket)o;
if (myLastValue == null || dp.addedRows.Count + dp.deletedRows.Count > 0)
base.myFireEvent(o);
}
@@ -233,29 +245,30 @@ namespace BCG
private void myHandleCallbacks(object newValue)
{
DataPacket retVal;
DataPacket arrivedPacket = newValue as DataPacket;
var arrivedPacket = (IDataPacket)newValue;
myLastReceivedRows = arrivedPacket.newRows;
try {
if (myLastFiredRows != null)
{
retVal = new DataPacket(myLastFiredRows, new BlueTable(myLastFiredRows.schema),
new BlueTable(myLastFiredRows.schema));
var addedRows = new BlueTable(myLastFiredRows.schema);
var deletedRows = new BlueTable(myLastFiredRows.schema);
retVal = new DataPacket(myLastFiredRows, addedRows, deletedRows);
foreach (IBlueRow r in arrivedPacket.deletedRows)
if (myLastFiredRows.containsID((int)r["id"]))
if (myLastFiredRows.containsID(r.Id()))
{
myLastFiredRows.deleteRow(r);
(retVal.deletedRows as BlueTable).addRow(r);
deletedRows.addRow(r);
}
foreach (IBlueRow r in arrivedPacket.addedRows)
if (filterRow(r))
{
myLastFiredRows.addRow(r);
(retVal.addedRows as BlueTable).addRow(r);
addedRows.addRow(r);
}
}
else
{
myLastFiredRows = new BlueTable(arrivedPacket.schema);
myLastFiredRows = new BlueTable(arrivedPacket.Schema);
retVal = new DataPacket(myLastFiredRows, myLastFiredRows, new BlueTable(myLastFiredRows.schema));
foreach (IBlueRow r in arrivedPacket.newRows)
if (filterRow(r))
@@ -273,7 +286,7 @@ namespace BCG
{
if (myUseNewFilter)
{
myFilterStream.filter = filter;
requireNewFilter().filter = filter;
}
else
{
@@ -302,9 +315,9 @@ namespace BCG
get
{
if (myUseNewFilter)
return myFilterStream.filter;
return requireNewFilter().filter;
else
return myFilter;
return requireOldFilter();
}
}
@@ -317,17 +330,25 @@ namespace BCG
private void myHandleFilterChange()
{
filter = myFilter;
filter = requireOldFilter();
}
bool filterRow(IBlueRow r) {
try {
return myFilter.filter(r);
return requireOldFilter().filter(r);
} catch (Exception ex) {
Log.Gen.error($"FilterStream delegate threw exception: {ex}");
OnError(new StreamFilterException(StreamId, StreamName, null, ex, r));
}
return false;
}
[MemberNotNull(nameof(myFilterStream))]
StreamWorld.Addition.FilterStream requireNewFilter() =>
ExceptionAssert.MemberNotNull(myFilterStream);
[MemberNotNull(nameof(myFilter))]
IStreamFilter requireOldFilter() =>
ExceptionAssert.MemberNotNull(myFilter);
}
}
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BCG.Utilities.General;
using BCG.Utilities.General;
using System;
namespace BCG
{
@@ -29,7 +27,7 @@ namespace BCG
myReference = myCurrentTime.AddSeconds(-1 * myNSecs);
}
public event FilterChangeDelegate onFilterChange;
public event FilterChangeDelegate? onFilterChange;
public bool filter(IBlueRow r)
{
@@ -38,9 +36,8 @@ namespace BCG
//it can be considered as our assumption whenever datecolumn is db null we return true
return true; //dont use this for volparamsched use true
}
DateTime t = (DateTime)r[myDateColumn];
bool returnVallue = t < myReference ? false : true;
return returnVallue;
var t = (DateTime)r[myDateColumn]!;
return t >= myReference;
}
@@ -51,8 +48,7 @@ namespace BCG
myCurrentTime = DateTime.Now;
myReference = myCurrentTime.AddSeconds(-1 * myNSecs);
myLastTimeFilteredApplied = DateTime.Now;
onFilterChange();
onFilterChange?.Invoke();
}
}
}
@@ -1,11 +1,13 @@
using System;
using BCG.Utilities.General;
using Spark.Core.Diagnostics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using BCG.Utilities.General;
using FuzzyRowComparer = System.Func<BCG.IBlueRow, BCG.IBlueRow, double>;
using System.Diagnostics;
namespace BCG
{
@@ -40,12 +42,12 @@ namespace BCG
private IComparer<IBlueRow> myRightCompare;
protected FuzzyRowComparer myFuzzyCompare;
protected TimeSpan myTimeWindow;
protected IBlueTableSchema myLeftSchema;
protected IBlueTableSchema myRightSchema;
protected IBlueTableSchema myOutputSchema;
protected IBlueTableSchema? myLeftSchema;
protected IBlueTableSchema? myRightSchema;
protected IBlueTableSchema? myOutputSchema;
private int myID = 0;
protected TimeWindowTable myStateRows;
protected TimeWindowTable? myStateRows;
private DateTime myNextCull;
const long MinCullIntervalMS = 1000;
@@ -65,7 +67,7 @@ namespace BCG
this.myFuzzyCompare = fuzzyCompare;
}
public virtual IBlueTableSchema OutputSchema
public virtual IBlueTableSchema? OutputSchema
{
get
{
@@ -150,7 +152,7 @@ namespace BCG
int count;
for (count = 0; count < list.Count; count++)
{
if ((DateTime)list[count][timeColumn] > expiry)
if ((DateTime)list[count][timeColumn]! > expiry)
{
// Stop when we find the first row that we can keep. Since this is sorted all others are also kept.
break;
@@ -172,16 +174,16 @@ namespace BCG
this.myFitness = fitness;
}
public IBlueRow myRightRow { get; private set; }
public IBlueRow myLeftRow { get; set; }
public IBlueRow? myLeftRow { get; set; }
public double myFitness { get; private set; }
public IBlueRow myMergedRow { get; set; }
public IBlueRow? myMergedRow { get; set; }
#region IComparable<RowMatch> Members
public int CompareTo(RowMatch other)
{
return myFitness.CompareTo(other.myFitness);
}
public int CompareTo(RowMatch? other) =>
other is null
? 1
: myFitness.CompareTo(other.myFitness);
#endregion
}
@@ -262,12 +264,12 @@ namespace BCG
private void HandleCorrection(List<RowMatch> corrections, BlueTable adds, BlueTable dels)
{
ExceptionAssert.NotNull(myStateRows);
// We already emitted correction.MergedRow so we need to redact that and
// then emit correction.left as an add since it is no longer matched
foreach (RowMatch correction in corrections.Distinct())
{
Debug.Assert(correction.myMergedRow != null);
this.myStateRows.RemoveRow(correction.myMergedRow);
myStateRows.RemoveRow(ExceptionAssert.NotNull(correction.myMergedRow));
adds.addRow(this.MergeRows(correction.myLeftRow, null));
dels.addRow(correction.myMergedRow);
}
@@ -285,7 +287,7 @@ namespace BCG
int r = 0;
for (l = 0, r = 0; l < leftExpired.Length && r < rightExpired.Length; )
{
if ((DateTime)leftExpired[l][this.myLeftTimeColumn] <= (DateTime)rightExpired[r][this.myRightTimeColumn])
if ((DateTime)leftExpired[l][this.myLeftTimeColumn]! <= (DateTime)rightExpired[r][this.myRightTimeColumn]!)
{
// Advance Left
IEnumerable<RowMatch> rm = rightMatches[l];
@@ -332,7 +334,7 @@ namespace BCG
private IBlueRow MergeLeftWithBestRight(IBlueRow leftRow, IEnumerable<RowMatch> rightMatches)
{
IBlueRow merged = null;
IBlueRow? merged = null;
if (rightMatches != null)
{
foreach (RowMatch match in rightMatches)
@@ -366,9 +368,9 @@ namespace BCG
/// Override this function to provide a custom row merge.
/// The overrided function must add a new column called FuzzyJoinOverTimeStream.NEW_TIME_COLUMN which will contain a timestamp for sorting.
/// </summary>
protected virtual IBlueRow MergeRows(IBlueRow left, IBlueRow right)
protected virtual IBlueRow MergeRows(IBlueRow? left, IBlueRow? right)
{
Dictionary<string, object> newRow = new Dictionary<string, object>();
Dictionary<string, object?> newRow = new();
if (left == null && right == null) throw new ArgumentException("oh come on.");
@@ -393,14 +395,15 @@ namespace BCG
}
}
newRow["id"] = this.myID++;
newRow[NEW_TIME_COLUMN] = (left != null) ? left[this.myLeftTimeColumn] : right[this.myRightTimeColumn];
newRow[NEW_TIME_COLUMN] = left is not null
? left[myLeftTimeColumn]
: right![myRightTimeColumn];
return new BlueRow(this.OutputSchema, newRow);
}
private IEnumerable<RowMatch> FindMatches(IBlueRow row, List<IBlueRow> list, List<RowMatch> corrections)
{
List<RowMatch> matches = null;
List<RowMatch>? matches = null;
// Search through all rows in list and compare with the fuzzy comparer
for (int x = 0; x < list.Count; x++)
@@ -421,8 +424,7 @@ namespace BCG
matches.Insert(insertIndex >= 0 ? insertIndex : ~insertIndex, currentMatch);
// Mark the best match for this particular right hand match
RowMatch oldMatch;
if (this.myBestMatch.TryGetValue(match, out oldMatch))
if (this.myBestMatch.TryGetValue(match, out var oldMatch))
{
if (currentMatch.myFitness < oldMatch.myFitness)
{
@@ -441,7 +443,7 @@ namespace BCG
}
}
return matches;
return matches ?? Enumerable.Empty<RowMatch>();
}
}
}
@@ -42,7 +42,7 @@ namespace BCG
return retVal;
}
public abstract IBlueRow evaluate (DataPacket dp) ;
public abstract IBlueRow? evaluate(IDataPacket dp);
#endregion
#region Helper methods
@@ -69,14 +69,7 @@ namespace BCG
protected IBlueRow myProject (IBlueRow r) {return myProject (r, r == null ? Int32.MinValue : (int)r["id"]);}
#endregion
private IBlueRow myProjectRow (IBlueRow r, string colMapExpression)
{
BlueTable auxTable = new BlueTable (r.schema);
auxTable.addRow (r);
BlueRowCollectionStaticStream staticStream = new BlueRowCollectionStaticStream (auxTable);
ProjectStream projStream = new ProjectStream (staticStream, colMapExpression);
return BlueDataUtility.extractRow (projStream.rows, 0);
}
IBlueRow myProjectRow (IBlueRow r, string colMapExpression) =>
new ProjectedRow(r, new ProjectHelper(r.schema, colMapExpression, "GroupByEvaluator_Project"));
}
}
@@ -8,12 +8,13 @@ namespace BCG {
internal class GroupByStream : MethodDrivenStream {
private class MyFuncGroupByEvaluator : IGroupByEvaluator {
private string[] _groupby_cols;
private Func<DataPacket, IBlueRow> _groupby_func;
public MyFuncGroupByEvaluator(IEnumerable<string> groupby_cols, Func<DataPacket, IBlueRow> groupby_func) {
readonly Func<IDataPacket, IBlueRow> _groupby_func;
public MyFuncGroupByEvaluator(IEnumerable<string> groupby_cols, Func<IDataPacket, IBlueRow> groupby_func) {
_groupby_cols = groupby_cols.ToArray();
_groupby_func = groupby_func;
}
public IBlueRow evaluate(DataPacket packet) { return _groupby_func(packet); }
public IBlueRow evaluate(IDataPacket packet) =>
_groupby_func(packet);
public string[] groupByColumns { get { return _groupby_cols; } }
@@ -32,7 +33,7 @@ namespace BCG {
private IBlueTableSchema myOutputSchema;
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<IDataPacket, IBlueRow> groupby_func)
: this(stream, new MyFuncGroupByEvaluator(groupby_cols, groupby_func)) { }
public GroupByStream(ViewStream stream, IGroupByEvaluator groupByEvaluator)
@@ -187,11 +188,11 @@ namespace BCG {
}
}
public static string getRepString(DataPacket dp, string[] colNames) {
public static string getRepString(IDataPacket dp, string[] colNames) {
return BlueDataUtility.rowToString(getRepRow(dp), colNames);
}
public static IBlueRow getRepRow(DataPacket dp) {
public static IBlueRow getRepRow(IDataPacket dp) {
if (dp.newRows.Count > 0)
return BlueDataUtility.extractRow(dp.newRows, 0);
else if (dp.addedRows.Count > 0)
@@ -1,5 +1,3 @@
using System;
namespace BCG
{
/// <summary>
@@ -14,7 +12,7 @@ namespace BCG
/// deletetion) and the added and deletedRows being the increments. If a group has
/// to be totally removed then a null should be returned
/// </summary>
IBlueRow evaluate (DataPacket packet);
IBlueRow? evaluate(IDataPacket packet);
/// <summary>
/// Returns the columns (belonging to the original schema) on which this IGroupByEvaluator
@@ -14,9 +14,8 @@ namespace BCG {
public MaxGroupByEvaluator(string colMapEpression, string outputCol, string[] groupByCols)
: base(colMapEpression, outputCol, groupByCols) { }
public override IBlueRow evaluate(DataPacket dp) {
myOutputTable = myOutputTable == null ? new GroupByOutputTable(dp.schema) :
myOutputTable;
public override IBlueRow? evaluate(IDataPacket dp) {
myOutputTable ??= new GroupByOutputTable(dp.Schema);
string hashString = BlueDataUtility.rowToString(GroupByStream.getRepRow(dp), myGroupByCols);
IBlueRow currMaxRow = myOutputTable.getRow(hashString);
IBlueRow maxRow = BlueDataUtility.computeMaxRow(dp.deletedRows, myOutputColumn);
@@ -1,7 +1,3 @@
using System;
using BCG.Utilities;
namespace BCG {
public class MinGroupByEvaluator : MaxGroupByEvaluator {
public MinGroupByEvaluator(string outputCol, string[] groupByCols)
@@ -10,8 +6,8 @@ namespace BCG {
public MinGroupByEvaluator(string colMapEpression, string outputCol, string[] groupByCols) :
base(colMapEpression, outputCol, groupByCols) { }
public override IBlueRow evaluate(DataPacket dp) {
myOutputTable = myOutputTable == null ? new GroupByOutputTable(dp.schema) : myOutputTable;
public override IBlueRow? evaluate(IDataPacket dp) {
myOutputTable ??= new GroupByOutputTable(dp.Schema);
string stringRep = BlueDataUtility.rowToString(GroupByStream.getRepRow(dp), myGroupByCols);
IBlueRow currMinRow = myOutputTable.getRow(stringRep);
IBlueRow minRow = BlueDataUtility.computeMinRow(dp.deletedRows, myOutputColumn);
@@ -1,14 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace BCG
{
public interface INonIncGroupByEvaluator
{
IBlueRowCollection evaluate(IDictionary<int, List<IBlueRow>> grouped_rows);
string[] get_group_by_cols();
IBlueRowCollection? evaluate(IDictionary<int, List<IBlueRow>> grouped_rows);
string[]? get_group_by_cols();
}
}
@@ -1,46 +1,51 @@
using System;
using bts;
using bts.SilverPine;
using Bts.DataStreamCore;
using Spark.Core.Diagnostics;
using Spark.Core.Disposables;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;
using bts;
using bts.SilverPine;
namespace BCG {
//[DataStreamUserRespresentation("AggregateStream")]
public class NonIncGroupByStream : ViewStream {
private class DelNonIncGroupByEvaluator : INonIncGroupByEvaluator {
Func<string[]> _groupby_cols_func;
Func<List<IBlueRow>, List<IBlueRow>> _evaluate_func;
public DelNonIncGroupByEvaluator(Func<string[]> groupby_cols_func,
Func<string[]?> _groupby_cols_func;
Func<List<IBlueRow>, List<IBlueRow>?> _evaluate_func;
public DelNonIncGroupByEvaluator(Func<string[]?> groupby_cols_func,
Func<List<IBlueRow>, List<IBlueRow>> evaluate_func) {
_groupby_cols_func = groupby_cols_func;
_evaluate_func = evaluate_func;
}
public IBlueRowCollection evaluate(IDictionary<int, List<IBlueRow>> grouped_rows) {
BlueTable rv = null;
public IBlueRowCollection? evaluate(IDictionary<int, List<IBlueRow>> grouped_rows) {
BlueTable? rv = null;
foreach (var kv in grouped_rows) {
List<IBlueRow> g_rows = kv.Value;
List<IBlueRow> out_rows = _evaluate_func.Invoke(g_rows);
var out_rows = _evaluate_func(g_rows);
if (out_rows != null && out_rows.Count > 0) {
rv = rv ?? new BlueTable(out_rows.ElementAt(0).schema);
rv.addRows(out_rows);
}
rv.addRows(out_rows);
}
return rv;
}
public string[] get_group_by_cols() {
public string[]? get_group_by_cols() {
return _groupby_cols_func();
}
}
private ViewStream _main_stream;
private INonIncGroupByEvaluator _groupby_func;
private BlueRowHasher _row_hasher;
private string[] _groupby_cols;
readonly ViewStream? _main_stream;
readonly INonIncGroupByEvaluator? _groupby_func;
BlueRowHasher? _row_hasher;
readonly string[]? _groupby_cols;
private Stopwatch _timer = new();
private int _n_total_fires = 0, _n_expensive_fires = 0;
IDisposable? subscription;
public NonIncGroupByStream(ViewStream main_stream, INonIncGroupByEvaluator groupby_func) {
_main_stream = main_stream;
@@ -49,7 +54,7 @@ namespace BCG {
_row_hasher = new BlueRowHasher(_groupby_cols == null ? 0 : _groupby_cols.Length);
}
public NonIncGroupByStream(ViewStream main_stream, Func<string[]> groupby_cols_func,
public NonIncGroupByStream(ViewStream main_stream, Func<string[]?> groupby_cols_func,
Func<List<IBlueRow>, List<IBlueRow>> evaluate_func)
: this(main_stream, new DelNonIncGroupByEvaluator(groupby_cols_func, evaluate_func)) { }
@@ -58,7 +63,7 @@ namespace BCG {
public NonIncGroupByStream(ViewStream parent_str, string groupby_col, string standard_group_by_text, string optional_sort_col) {
MultiRowOpHelper std_group_by = MultiRowOpHelper.parse(standard_group_by_text);
Func<string[]> groupby_cols_func = () => {
Func<string[]?> groupby_cols_func = () => {
return String.IsNullOrEmpty(groupby_col) ? null : new string[] { groupby_col };
};
Func<List<IBlueRow>, List<IBlueRow>> evaluate_func = (group_rows) => {
@@ -75,12 +80,17 @@ namespace BCG {
}
protected override void myOnFirstSubscriber() { _main_stream.onChange += _main_stream_onchange; }
protected override void myOnFirstSubscriber() {
ExceptionAssert.IsNull(subscription);
ExceptionAssert.NotNull(_main_stream).Subscribe(_main_stream_onchange);
}
protected override void myOnLastSubscriber() { _main_stream.onChange -= _main_stream_onchange; }
protected override void myOnLastSubscriber() =>
Disposable.Dispose(ref subscription);
private void _main_stream_onchange(object nv) {
DataPacket dp = nv as DataPacket;
ExceptionAssert.NotNull(_groupby_func);
var dp = (IDataPacket)nv;
///grouping together
_timer.Restart();
IDictionary<int, List<IBlueRow>> grouped_rows = (_groupby_cols == null || _groupby_cols.Length == 0) ?
@@ -94,7 +104,7 @@ namespace BCG {
// Log.log(bts.Log.Level.Info, bts.log.Subsystem.gen, String.Format("Time to group {0} rows into {1} groups = {2}", dp.newRows.Count, grouped_rows.Count, _timer.lastIntervalTime));
/// reducing
_timer.Restart();
IBlueRowCollection total_state = _groupby_func.evaluate(grouped_rows);
var total_state = _groupby_func.evaluate(grouped_rows);
_timer.Stop();
if (total_state is null) {
Log.Gen.warn("NonIncGroupByStream _groupby_func.evaluate returned null (ignoring last update).");
@@ -108,8 +118,12 @@ namespace BCG {
$"Time to evaluate {grouped_rows.Count} groups {_timer.ElapsedMilliseconds}ms, ratio {_n_expensive_fires}/{_n_total_fires}");
}
// TODO,
if (total_state != null)
myFireEvent(new DataPacket(total_state, total_state, myLastValue == null ? new BlueTable(total_state.schema) : (myLastValue as DataPacket).newRows));
if (total_state != null) {
var deletedRows = myLastValue is null
? new BlueTable(total_state.schema)
: ((IDataPacket)myLastValue).newRows;
myFireEvent(new DataPacket(total_state, total_state, deletedRows));
}
}
}
}
@@ -1,6 +1,6 @@
using System;
using BCG.Utilities;
using System.Collections;
using System.Collections.Generic;
namespace BCG
{
@@ -11,12 +11,10 @@ namespace BCG
/// </summary>
public class RowDictionaryTable : IBlueRowCollection
{
protected IDictionary myRowCollections = new Hashtable ();
protected BlueTable myLinearCollection;
protected string[] myCols;
protected readonly Dictionary<string, BlueTable> myRowCollections = new();
protected readonly BlueTable myLinearCollection;
protected readonly string[] myCols;
protected IBlueTableSchema mySchema;
protected RowDictionaryTable () {}
public RowDictionaryTable (IBlueRowCollection rows, params string[] cols)
: this (rows.schema, cols)
@@ -40,7 +38,7 @@ namespace BCG
public virtual void addRow (IBlueRow row)
{
BlueTable rows = (BlueTable)getGroup (row);
var rows = getMutableGroup(row);
if (rows == null)
{
//i.e we dont have any group for this row => we need to create a new group
@@ -53,7 +51,7 @@ namespace BCG
public virtual void removeRow (IBlueRow row)
{
BlueTable rowGroup = (BlueTable)getGroup (row);
var rowGroup = requireMutableGroup(row);
// BlueEventLog.logAssert (rowGroup != null && rowGroup.Count > 0);
rowGroup.deleteRow (row);
myLinearCollection.deleteRow (row);
@@ -65,7 +63,7 @@ namespace BCG
public void removeGroup (IBlueRow representativeRow)
{
IBlueRowCollection rowGroup = getGroup (representativeRow);
var rowGroup = requireGroup(representativeRow);
// BlueEventLog.logAssert (rowGroup != null && rowGroup.Count > 0);
foreach (IBlueRow row in rowGroup)
myLinearCollection.deleteRow (row);
@@ -85,24 +83,31 @@ namespace BCG
/// <returns></returns>
//public IBlueRowCollection getGroup (IBlueRow row) {return getGroup (
public IBlueRowCollection getGroup (IBlueRow r) {return getGroup (myRowToString (r));}
public IBlueRowCollection? getGroup (IBlueRow r) =>
getGroup(myRowToString(r));
public ICollection getGroups () {return myRowCollections.Values;}
private bool myAreRowsEqual (IBlueRow r1, IBlueRow r2)
{
bool retVal = true;
foreach (string col in myCols)
retVal &= r1[col].Equals(r2[col]);
return retVal;
}
public IBlueRowCollection? getGroup(string repString) =>
getMutableGroup(repString);
public IBlueRowCollection getGroup (string repString)
{
IBlueRowCollection retVal = myRowCollections[repString] != null ?
(IBlueRowCollection) myRowCollections[repString] : null;
return retVal;
}
BlueTable? getMutableGroup(IBlueRow row) =>
getMutableGroup(myRowToString(row));
BlueTable? getMutableGroup(string group) =>
myRowCollections.GetValueOrDefault(group);
IBlueRowCollection requireGroup(IBlueRow row) =>
requireGroup(myRowToString(row));
IBlueRowCollection requireGroup(string group) =>
getGroup(group) ?? throw new ArgumentException("No table for group", nameof(group));
BlueTable requireMutableGroup(IBlueRow row) =>
requireMutableGroup(myRowToString(row));
BlueTable requireMutableGroup(string group) =>
getMutableGroup(group) ?? throw new ArgumentException("No table for group", nameof(group));
private string myRowToString (IBlueRow r) {return BlueDataUtility.rowToString (r, myCols);}
@@ -1,5 +1,3 @@
using System;
namespace BCG {
/// <summary>
/// Computes the sum for a given column
@@ -10,8 +8,8 @@ namespace BCG {
public SumGroupByEvaluator(string colMapEpression, string outputCol, string[] groupByCols)
: base(colMapEpression, outputCol, groupByCols) { }
public override IBlueRow evaluate(DataPacket dp) {
myOutputTable = myOutputTable == null ? new GroupByOutputTable(dp.schema) : myOutputTable;
public override IBlueRow evaluate(IDataPacket dp) {
myOutputTable ??= new GroupByOutputTable(dp.Schema);
IBlueRow sumRow = BlueDataUtility.computeSum(dp.newRows, myOutputColumn);
return sumRow;
@@ -33,7 +31,7 @@ namespace BCG {
#region IGroupByEvaluator Members
public IBlueRow evaluate(DataPacket packet) { return BlueDataUtility.computeSum(packet.newRows, myOutputCols); }
public IBlueRow evaluate(IDataPacket packet) => BlueDataUtility.computeSum(packet.newRows, myOutputCols);
public string[] groupByColumns { get { return myGroupByCols; } }
@@ -51,9 +49,8 @@ namespace BCG {
public SumGroupByEvaluator(string colMapEpression, string outputCol, string[] groupByCols)
: base(colMapEpression, outputCol, groupByCols) { }
public override IBlueRow evaluate(DataPacket dp) {
myOutputTable = myOutputTable == null ? new GroupByOutputTable(dp.schema) : myOutputTable;
public override IBlueRow evaluate(IDataPacket dp) {
myOutputTable ??= new GroupByOutputTable(dp.Schema);
IBlueRow sumRow = BlueDataUtility.computeSum<T>(dp.newRows, myOutputColumn);
return sumRow;
}
@@ -68,7 +65,7 @@ namespace BCG {
#region IGroupByEvaluator Members
public IBlueRow evaluate(DataPacket packet) { return BlueDataUtility.computeSum<T>(packet.newRows, myOutputCols); }
public IBlueRow evaluate(IDataPacket packet) => BlueDataUtility.computeSum<T>(packet.newRows, myOutputCols);
public string[] groupByColumns { get { return myGroupByCols; } }
@@ -1,5 +1,3 @@
using System;
namespace BCG
{
[DataStreamUserRespresentation (false)]
@@ -17,6 +15,7 @@ namespace BCG
protected override void myInitFiredPacket ()
{
requireSchema();
myLastFiredPacket = new DataPacket ();
myLastFiredPacket.newRows = new JoinForeignTable (mySchema);
myLastFiredPacket.addedRows = new BlueTable (mySchema);
@@ -25,6 +24,10 @@ namespace BCG
public override void onTableClear (bool isLeft)
{
if (myLastFiredPacket is null) {
return;
}
requireSchema();
//incase of natural join, left or right wont matter, the end result zeroes out
myLastFiredPacket.deletedRows = myLastFiredPacket.newRows;
myLastFiredPacket.newRows = new JoinForeignTable (mySchema);
@@ -1,5 +1,7 @@
using Spark.Core.Diagnostics;
using System;
using System.Collections;
using System.Diagnostics.CodeAnalysis;
namespace BCG
{
@@ -13,12 +15,10 @@ namespace BCG
protected JoinOperand myLeftOperand, myRightOperand;
protected int myLeftJoinColOrdinal, myRightJoinColOrdinal;
protected ViewStream myLeftStream, myRightStream;
protected JoinTableSchema mySchema;
protected DataPacket myLastFiredPacket;
protected JoinTableSchema? mySchema;
protected DataPacket? myLastFiredPacket;
protected bool myOnceFired = false;
public IBlueTableSchema schema {get{return mySchema;}}
public InternalJoinStream (ViewStream vsLeft, string jcLeft, ViewStream vsRight, string jcRight)
{
myLeftStream = vsLeft;
@@ -27,6 +27,9 @@ namespace BCG
myRightOperand = new JoinOperand (jcRight, false);
}
public IBlueTableSchema schema =>
requireSchema();
protected override void myOnFirstSubscriber()
{
myLeftOperand.master = this;
@@ -62,29 +65,32 @@ namespace BCG
{
myLeftJoinColOrdinal = myLeftOperand.joinColOridinal;
myRightJoinColOrdinal = myRightOperand.joinColOridinal;
myLeftOperand.RequireInitialized();
myRightOperand.RequireInitialized();
mySchema = new JoinTableSchema (myLeftOperand.operandSchema, myLeftOperand.joinCol,
myRightOperand.operandSchema, myRightOperand.joinCol);
myInitFiredPacket ();
}
}
[MemberNotNull(nameof(mySchema), nameof(myLastFiredPacket))]
protected virtual void myInitFiredPacket ()
{
var schema = requireSchema();
myLastFiredPacket = new DataPacket ();
myLastFiredPacket.newRows = new JoinTable (mySchema);
myLastFiredPacket.addedRows = new BlueTable (mySchema);
myLastFiredPacket.deletedRows = new BlueTable (mySchema);
myLastFiredPacket.newRows = new JoinTable (schema);
myLastFiredPacket.addedRows = new BlueTable (schema);
myLastFiredPacket.deletedRows = new BlueTable (schema);
}
public IBlueTableSchema getSchema (bool isLeft)
{
IBlueTableSchema retVal;
retVal = isLeft ? myLeftOperand.operandSchema : myRightOperand.operandSchema;
return retVal;
}
public IBlueTableSchema? getSchema (bool isLeft) =>
isLeft ? myLeftOperand.operandSchema : myRightOperand.operandSchema;
public void endSession ()
{
if (myLastFiredPacket is null) {
return;
}
if (!myOnceFired)
{
myOnceFired = true;
@@ -97,13 +103,17 @@ namespace BCG
protected virtual void myInit ()
{
myLeftOperand.init ();
myRightOperand.init ();
myLeftOperand.Reset ();
myRightOperand.Reset ();
myLastFiredPacket = null;
}
public virtual void onTableClear (bool isLeft)
{
if (myLastFiredPacket is null) {
return;
}
requireSchema();
//incase of natural join, left or right wont matter, the end result zeroes out
myLastFiredPacket.deletedRows = myLastFiredPacket.newRows;
myLastFiredPacket.newRows = new JoinTable (mySchema);
@@ -112,15 +122,19 @@ namespace BCG
public virtual void deleteRows (IBlueRowCollection rows, bool isLeft)
{
var last = myLastFiredPacket;
if (last is null) {
return;
}
JoinOperand thisOp, otherOp;
int joinColOrdinal;
myAssignAccordingly (out thisOp, out otherOp, out joinColOrdinal, isLeft);
foreach (IBlueRow row in rows)
{
thisOp.deleteRow (row);
if (otherOp.getMatchingRows (row[joinColOrdinal]).Count == 0)
if (otherOp.getMatchingRows(getJoinKey(row, joinColOrdinal)).Count == 0)
continue; //row does not participate in join
((JoinTable)(myLastFiredPacket.newRows)).deleteRow (isLeft, row, myLastFiredPacket);
((JoinTable)last.newRows).deleteRow(isLeft, row, last);
}
}
@@ -135,10 +149,12 @@ namespace BCG
otherOp = myLeftOperand;
joinColOrdinal = myRightJoinColOrdinal;
}
var schema = requireSchema();
myLastFiredPacket ??= new DataPacket(new BlueTable(schema), new BlueTable(schema), new BlueTable(schema));
foreach (IBlueRow row in rows)
{
thisOp.addRow (row);
RowList matchedNodes = otherOp.getMatchingRows (row[joinColOrdinal]);
RowList matchedNodes = otherOp.getMatchingRows(getJoinKey(row, joinColOrdinal));
if (matchedNodes.Count == 0)
continue; //this row did not participate in the join
if (isLeft)
@@ -146,10 +162,22 @@ namespace BCG
((JoinTable)myLastFiredPacket.newRows).addRow (row, matchedNode.row, myLastFiredPacket);
else
foreach (RowNode matchedNode in matchedNodes)
((JoinTable)myLastFiredPacket.newRows).addRow (matchedNode.row, row, myLastFiredPacket);
((JoinTable)myLastFiredPacket.newRows).addRow(ExceptionAssert.NotNull(matchedNode.row), row, myLastFiredPacket);
}
}
[MemberNotNull(nameof(mySchema))]
protected JoinTableSchema requireSchema() =>
ExceptionAssert.NotNull(mySchema);
[MemberNotNull(nameof(myLastFiredPacket))]
protected DataPacket requireLastFiredPacket() {
if (myLastFiredPacket is null) {
myInitFiredPacket();
}
return myLastFiredPacket;
}
private void myAssignAccordingly (out JoinOperand thisOp, out JoinOperand otherOp, out int joinColOrdinal, bool isLeft)
{
if (isLeft)
@@ -166,6 +194,9 @@ namespace BCG
}
}
object getJoinKey(IBlueRow row, int joinColOrdinal) =>
row[joinColOrdinal] ?? throw new ArgumentException("Row has null join key", nameof(row));
/**************************************TEST METHOD(S)*********************************************/
/// <summary>
/// Used for testing purposes only. This enables the test to work without a DataSource (PubServer,
@@ -173,8 +204,7 @@ namespace BCG
/// </summary>
/// <param name="leftPacket"></param>
/// <param name="rightPacket"></param>
public void test (DataPacket dp, bool isLeft)
{
public void test(IDataPacket dp, bool isLeft) {
JoinOperand jo = isLeft ? myLeftOperand : myRightOperand;
jo.changeHandler (dp);
}
@@ -1,5 +1,6 @@
using System;
using System.Collections;
using Spark.Core.Diagnostics;
using System.Collections.Generic;
namespace BCG
{
@@ -8,7 +9,7 @@ namespace BCG
/// </summary>
internal class JoinDeletionIndex
{
IDictionary myIndex = new Hashtable ();
Dictionary<object, RowList> myIndex = new();
private string myOpIdName ;
private bool myIsLeft;
@@ -28,10 +29,8 @@ namespace BCG
/// <param name="row">JoinRow to add</param>
public void add (JoinRow row)
{
object o = row[myOpIdName];
if (myIndex[o] == null)
myIndex[o] = new RowList ();
RowNode nodeAdded = ((RowList)myIndex[o]).add (row);
object o = ExceptionAssert.NotNull(row[myOpIdName]);
RowNode nodeAdded = myIndex.GetOrAdd(o, _ => new()).add(row);
if (myIsLeft)
row.leftNode = nodeAdded;
else
@@ -43,7 +42,10 @@ namespace BCG
/// To remove a node, if node does not exist exception is thrown
/// </summary>
/// <param name="node"></param>
public void remove (RowNode node) {((RowList)myIndex[node.row[myOpIdName]]).remove (node);}
public void remove (RowNode node) {
var nodeId = ExceptionAssert.NotNull(node.row?[myOpIdName]);
myIndex[nodeId].remove(node);
}
public RowList getMatchingRows (object key) {
RowList retVal = (RowList)myIndex[key];
@@ -1,19 +1,18 @@
using System;
using BCG.Utilities;
using bts;
using Bts.DataStreamCore;
namespace BCG
{
internal class JoinForeignTable : JoinTable
{
public JoinForeignTable (JoinTableSchema schema) : base (schema) {}
public override void addRow (IBlueRow leftRow, IBlueRow rightRow, DataPacket dp)
{
JoinRow newRow = new JoinRow (leftRow, rightRow, mySchema);
Log.assert(myIdIndex[leftRow["id"]] == null);
myIdIndex[leftRow["id"]] = newRow;
public override void addRow(IBlueRow leftRow, IBlueRow? rightRow, IDataPacket dp) {
var newRow = new JoinRow(leftRow, rightRow, mySchema);
int leftId = leftRow.Id();
Log.assert(myIdIndex[leftId] == null);
myIdIndex[leftId] = newRow;
((BlueTable)(dp.addedRows)).addRow (newRow);
myLeftIndex.add (newRow);
myRightIndex.add (newRow);
@@ -1,11 +1,12 @@
using System;
using System.Collections;
using BCG.Utilities;
using bts;
using Bts.ColumnMapExpressions;
using Spark.Core.Diagnostics;
using System;
using System.Collections;
namespace BCG
{
/// <summary>
@@ -37,7 +38,8 @@ namespace BCG
private JoinTableSchema myJoinSchema;
private IBlueTableSchema myLeftSchema, myRightSchema;
private string myLeftColExpression, myRightColExpression;
private string[] myUserRules, myResolvedNames;
string[] myUserRules;
string[]? myResolvedNames;
private IDictionary myFinalMap = new Hashtable ();
@@ -87,16 +89,18 @@ namespace BCG
/// </summary>
private void myFormUserRules ()
{
var leftExp = ColumnMapExpression.Parse(myLeftColExpression) ?? throw new InvalidOperationException("Failed to parse left column expression");
var rightExp = ColumnMapExpression.Parse(myRightColExpression) ?? throw new InvalidOperationException("Failed to parse right column expression");
if (DataStreamLoadFileConfig.instance.useStaticParser)
{
myFormUserRules(true, ColumnMapExpression.Parse(myLeftColExpression));
myFormUserRules(false, ColumnMapExpression.Parse(myRightColExpression));
myFormUserRules(true, leftExp);
myFormUserRules(false, rightExp);
}
else
{
// TODO (maybe): Actually use non-static parser (unclear what advantages it will have)
myFormUserRules(true, ColumnMapExpression.Parse(myLeftColExpression));
myFormUserRules(false, ColumnMapExpression.Parse(myRightColExpression));
myFormUserRules(true, leftExp);
myFormUserRules(false, rightExp);
}
}
@@ -115,13 +119,7 @@ namespace BCG
OriginalNameInfo oni = myOriginalColInfo[i];
if (oni.isLeft == isLeft)
{
if (userMap[oni.colName] != null)
{
if ((string)userMap[oni.colName] != oni.colName)
myUserRules[i] = (string)userMap[oni.colName];
else
myUserRules[i] = oni.colName;
}
myUserRules[i] = userMap[oni.colName] as string ?? oni.colName;
}
}
else
@@ -131,10 +129,13 @@ namespace BCG
OriginalNameInfo oni = myOriginalColInfo[i];
if (oni.isLeft == isLeft)
{
if (userMap[oni.colName] == null)
var colName = userMap[oni.colName] as string;
// myUserRules[i] = userMap[oni.colName] as string
if (colName is null) {
myUserRules[i] = oni.colName;
else if ((string)userMap[oni.colName] != oni.colName)
myUserRules[i] = (string)userMap[oni.colName];
} else if (colName != oni.colName) {
myUserRules[i] = colName;
}
}
}
}
@@ -165,26 +166,12 @@ namespace BCG
private void myFormFinalMap ()
{
ExceptionAssert.NotNull(myResolvedNames);
foreach (string resolvedName in myResolvedNames)
if (resolvedName != null)
myFinalMap [resolvedName] = myJoinNames[Array.IndexOf (myResolvedNames, resolvedName)];
}
/// <summary>
/// Utility method to invert a hashtable
/// </summary>
/// <param name="arg"></param>
/// <returns></returns>
private IDictionary reciprocateDictionary (IDictionary arg)
{
IDictionary retVal = new Hashtable ();
foreach (DictionaryEntry de in arg)
retVal[de.Value] = de.Key;
return retVal;
}
/// <summary>
/// Utility method to find all occurances of an obkect in an IList
/// </summary>
@@ -194,9 +181,11 @@ namespace BCG
private ArrayList myFindAllInCollection (IList list, object obj)
{
ArrayList retVal = new ArrayList ();
for (int i = 0; i < list.Count; i++)
if (list[i] != null && list[i].Equals (obj))
for (int i = 0; i < list.Count; i++) {
if (Equals(list[i], obj)) {
retVal.Add (i);
}
}
return retVal;
}
@@ -1,6 +1,7 @@
using Spark.Core.Diagnostics;
using System;
using System.Collections;
using BCG.Utilities;
using System.Diagnostics.CodeAnalysis;
namespace BCG
{
@@ -11,34 +12,46 @@ namespace BCG
public class JoinOperand
{
private string myJoinCol;
private DataPacket myLastArrivedPacket;
private JoinOperand myOtherOperand;
IDataPacket? myLastArrivedPacket;
JoinOperand? myOtherOperand;
private bool myIsLeft;
private JoinOperandRowIndex myRowIndex;
private InternalJoinStream myMaster;
private IBlueTableSchema myOpSchema;
JoinOperandRowIndex? myRowIndex;
InternalJoinStream? myMaster;
public JoinOperand (string joinCol, bool isLeft)
{
myJoinCol = joinCol;
myIsLeft = isLeft;
}
internal void changeHandler (object o)
{
DataPacket temp = (DataPacket)o;
if (myLastArrivedPacket != null)
mySubsequentChangeHandler ((DataPacket)o);
else
myFirstChangeHandler ((DataPacket)o);
[MemberNotNullWhen(true, nameof(myMaster), nameof(myLastArrivedPacket), nameof(operandSchema), nameof(myOtherOperand), nameof(myRowIndex))]
bool isInitialized {
get {
if (myLastArrivedPacket is null) {
return false;
}
ExceptionAssert.NotNull(myMaster, myLastArrivedPacket, operandSchema, myOtherOperand, myRowIndex);
return true;
}
}
private void myFirstChangeHandler (DataPacket arrivedDp)
internal void changeHandler (object o)
{
var dp = (IDataPacket)o;
if (isInitialized) {
mySubsequentChangeHandler (dp);
} else {
myFirstChangeHandler(dp);
}
}
[MemberNotNull(nameof(myLastArrivedPacket), nameof(operandSchema), nameof(myOtherOperand), nameof(myRowIndex))]
bool myFirstChangeHandler(IDataPacket arrivedDp) {
ExceptionAssert.NotNull(myMaster);
myLastArrivedPacket = arrivedDp;
myOpSchema = myLastArrivedPacket.newRows.schema;
operandSchema = myLastArrivedPacket.newRows.schema;
myOtherOperand = myMaster.getOtherOperand (this);
myRowIndex = new JoinOperandRowIndex (myOpSchema[myJoinCol].colNo, myOpSchema["id"].colNo);
myRowIndex = new JoinOperandRowIndex (operandSchema[myJoinCol].colNo, operandSchema["id"].colNo);
if (myOtherOperand.hasReceivedData)
{
//the other operand has already received data, so the join would
@@ -49,14 +62,16 @@ namespace BCG
myMaster.addRows (myLastArrivedPacket.newRows, myIsLeft);
myMaster.endSession ();
}
else
else {
myRowIndex = new JoinOperandRowIndex (myLastArrivedPacket.newRows,
myOpSchema[myJoinCol].colNo,
myOpSchema["id"].colNo);
operandSchema[myJoinCol].colNo,
operandSchema["id"].colNo);
}
return true;
}
private void mySubsequentChangeHandler (DataPacket arrivedDp)
{
void mySubsequentChangeHandler (IDataPacket arrivedDp) {
RequireInitialized();
myLastArrivedPacket = arrivedDp;
if (!myOtherOperand.hasReceivedData)
{
@@ -85,29 +100,46 @@ namespace BCG
myMaster.endSession ();
}
internal void addRow (IBlueRow row) {myRowIndex.add (row);}
internal void addRow (IBlueRow row) =>
ExceptionAssert.NotNull(myRowIndex).add(row);
internal void deleteRow (IBlueRow row) {myRowIndex.remove (row);}
internal void deleteRow (IBlueRow row) {
RequireInitialized();
myRowIndex.remove (row);
}
internal IBlueTableSchema operandSchema {get{return myOpSchema;}}
internal IBlueTableSchema? operandSchema { get; private set; }
internal InternalJoinStream master {set{myMaster = value;}}
internal string joinCol {get{return myJoinCol;}}
internal int joinColOridinal {get{return myOpSchema[myJoinCol].colNo;}}
internal int joinColOridinal {
get {
RequireInitialized();
return operandSchema[myJoinCol].colNo;
}
}
internal RowList getMatchingRows (object key) {return (RowList) myRowIndex.getMatchingRows (key);}
internal RowList getMatchingRows (object key) {
RequireInitialized();
return myRowIndex.getMatchingRows(key);
}
internal bool hasReceivedData {get{return myLastArrivedPacket != null;}}
internal void init ()
{
internal void Reset() {
///should be brought back to the the state before the first callback
///(ie the state after construction)
myRowIndex = null;
myLastArrivedPacket = null;
}
[MemberNotNull(nameof(myMaster), nameof(myLastArrivedPacket), nameof(operandSchema), nameof(myOtherOperand), nameof(myRowIndex))]
internal void RequireInitialized() {
if (!isInitialized) {
throw new InvalidOperationException("Internal state not properly initialized");
}
}
}
}
@@ -1,6 +1,6 @@
using System;
using System.Collections;
using BCG.Utilities;
using Spark.Core.Diagnostics;
using System.Collections.Generic;
namespace BCG
{
@@ -11,8 +11,10 @@ namespace BCG
/// </summary>
internal class JoinOperandRowIndex
{
private IDictionary myJoinColDict = new Hashtable (), myIdDict = new Hashtable ();
private int myJoinColOrdinal, myIdColOrdinal;
readonly Dictionary<object, RowList> myJoinColDict = new();
readonly Dictionary<int, RowNode> myIdDict = new();
readonly int myJoinColOrdinal;
readonly int myIdColOrdinal;
/// <summary>
///
@@ -34,19 +36,14 @@ namespace BCG
public void add (IBlueRow row)
{
RowList list;
if (myJoinColDict[row[myJoinColOrdinal]] == null)
myJoinColDict[row[myJoinColOrdinal]] = list = new RowList ();
else
list = (RowList)myJoinColDict[row[myJoinColOrdinal]];
myIdDict[row[myIdColOrdinal]] = list.add (row);
myIdDict[getId(row)] = myJoinColDict.GetOrAdd(getJoinKey(row), _ => new()).add(row);
}
public void remove (IBlueRow row)
{
RowNode node = (RowNode)myIdDict[row[myIdColOrdinal]];
((RowList)myJoinColDict[row[myJoinColOrdinal]]).remove (node);
myIdDict.Remove (row[myIdColOrdinal]);
var id = getId(row);
myJoinColDict[getJoinKey(row)].remove(myIdDict[id]);
myIdDict.Remove(id);
}
public RowList getMatchingRows (object key)
@@ -62,5 +59,11 @@ namespace BCG
myJoinColDict.Clear ();
myIdDict.Clear ();
}
object getJoinKey(IBlueRow row) =>
ExceptionAssert.NotNull(row[myJoinColOrdinal]);
int getId(IBlueRow row) =>
(int)row[myIdColOrdinal]!;
}
}
@@ -1,17 +1,21 @@
using System;
using BCG.Utilities;
using System.Collections;
using bts;
using Bts.DataStreamCore;
using System;
using System.Collections;
namespace BCG
{
internal class JoinRow : IBlueRow
{
private RowNode myLeftNode, myRightNode;
protected IBlueRow myLeftRow, myRightRow;
RowNode? myLeftNode;
RowNode? myRightNode;
protected IBlueRow myLeftRow;
protected IBlueRow? myRightRow;
protected int myId;
protected JoinTableSchema mySchema;
private object[] myValues;
private object?[] myValues;
#region Constructor(s)
@@ -21,8 +25,8 @@ namespace BCG
/// <param name="leftRow">left row of the join</param>
/// <param name="rightRow">right row of the join</param>
/// <param name="schema">schema of the joined row</param>
public JoinRow (IBlueRow leftRow, IBlueRow rightRow, JoinTableSchema schema)
: this ((int)leftRow["id"], leftRow, rightRow, schema) {}
public JoinRow (IBlueRow leftRow, IBlueRow? rightRow, JoinTableSchema schema)
: this(leftRow.Id(), leftRow, rightRow, schema) { }
/// <summary>
/// Constructs a row assigning it the ID provioded as the first argument
@@ -31,8 +35,7 @@ namespace BCG
/// <param name="leftRow">left row of the join</param>
/// <param name="rightRow">right row of the join</param>
/// <param name="schema">schema of the joined row</param>
public JoinRow (int id, IBlueRow leftRow, IBlueRow rightRow, JoinTableSchema schema)
{
public JoinRow (int id, IBlueRow leftRow, IBlueRow? rightRow, JoinTableSchema schema) {
myId = id;
myLeftRow = leftRow;
myRightRow = rightRow;
@@ -48,13 +51,13 @@ namespace BCG
public bool isPartialJoin{get{return myRightRow == null;}}
public RowNode leftNode
public RowNode? leftNode
{
get{return myLeftNode;}
set{myLeftNode = value;}
}
public RowNode rightNode
public RowNode? rightNode
{
get{return myRightNode;}
set{myRightNode = value;}
@@ -85,7 +88,7 @@ namespace BCG
/// The key can either be the string corrsponding to the column name or
/// the order of the column
/// </summary>
public virtual object this [object key]
public virtual object? this[object key]
{
get
{
@@ -96,7 +99,7 @@ namespace BCG
set {throw new NotSupportedException ("The IBlueRow is read only");}
}
public object this [int index]
public object? this[int index]
{
get
{
@@ -119,7 +122,8 @@ namespace BCG
}
}
public object this [string colName] {get{return this[mySchema[colName].colNo];}}
public object? this[string colName] =>
this[mySchema[colName].colNo];
public ICollection Keys{get{return mySchema.columnNames;}}
@@ -133,7 +137,8 @@ namespace BCG
}
}
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");}
@@ -1,20 +1,26 @@
using System;
using System.Data;
using System.Collections;
using System.Text.RegularExpressions;
using BCG.Utilities;
using BCG.Utilities.General;
using bts;
using Bts.DataStreamCore;
using Spark.Core.Diagnostics;
using Spark.Core.Disposables;
using System;
using System.Collections;
namespace BCG
{
public class JoinStream : ViewStream
{
protected InternalJoinStream? myIjs;
protected readonly InternalJoinStream? myIjs;
protected readonly ColumnMap? myLeftCm;
protected readonly ColumnMap? myRightCm;
protected readonly bool myIsProject = true;
protected ProjectStream? myPs;
protected ColumnMap? myLeftCm, myRightCm;
protected bool myIsProject = true;
private bool myUseSuperJoin = DataStreamLoadFileConfig.instance.useNewJoin;
readonly bool myUseSuperJoin = DataStreamLoadFileConfig.instance.useNewJoin;
IDisposable? internalSubscription;
IDisposable? projectSubscription;
protected JoinStream () {}
public JoinStream (ViewStream v1, string joinCol1, ColumnMap cm1,
@@ -111,47 +117,61 @@ namespace BCG
{
if (myPs == null)
{
JoinNameResolver resolver = new JoinNameResolver ((JoinTableSchema)myIjs.schema, myIjs.getSchema (true), myLeftCm.columnExpression,
myIjs.getSchema (false), myRightCm.columnExpression);
ExceptionAssert.NotNull(myIjs, myLeftCm, myRightCm);
var leftSchema = myIjs.getSchema(true) ?? throw new InvalidOperationException("Left schema is null");
var rightSchema = myIjs.getSchema(true) ?? throw new InvalidOperationException("Right schema is null");
var joinSchema = (JoinTableSchema)myIjs.schema;
JoinNameResolver resolver = new JoinNameResolver(
joinSchema, leftSchema, myLeftCm.columnExpression, rightSchema, myRightCm.columnExpression);
IDictionary map = resolver.getMap ();
map["id"] = "id";
Disposable.Dispose(ref projectSubscription);
myPs = new ProjectStream (myIjs, map);
myPs.onChange += new DataStream.ChangeDelegate (myProjectChangeHandler);
projectSubscription = myPs.Subscribe(myProjectChangeHandler);
return;
}
else
Log.assert(false, "This call back should not have been called");
}
else
myFireEvent ((o as ICloneable).Clone());
else {
myFireEvent(cloneDataPacket(o));
}
}
private void myProjectChangeHandler (object o)
{
if (myIjs.myOnChangeDelegate.GetInvocationList().Length > 1)
myIjs.onChange -= new DataStream.ChangeDelegate (myInternalJoinChangeHandler);
myFireEvent ((o as ICloneable).Clone());
ExceptionAssert.NotNull(myIjs);
if (myIjs.numberOfSubscribers > 1) {
Disposable.Dispose(ref internalSubscription);
}
myFireEvent(cloneDataPacket(o));
}
protected override void myOnFirstSubscriber ()
{
myIjs.onChange += new DataStream.ChangeDelegate (myInternalJoinChangeHandler);
Log.isnull(internalSubscription);
internalSubscription = ExceptionAssert.NotNull(myIjs).Subscribe(myInternalJoinChangeHandler);
}
protected override void myOnLastSubscriber ()
{
// how does this relate to the -= in myProjectChangeHandler?
myIjs.onChange -= new DataStream.ChangeDelegate (myInternalJoinChangeHandler);
Disposable.Dispose(ref internalSubscription);
// if there is a project after the ijs we need to
// unsubscribe to it otherwise references will be kept and
// a memory leak will occur
if (myPs != null)
myPs.onChange -= new DataStream.ChangeDelegate (myProjectChangeHandler);
Disposable.Dispose(ref projectSubscription);
myPs = null;
}
object cloneDataPacket(object dpObj) {
var rv = (dpObj as ICloneable)?.Clone();
if (rv is null) {
var dp = (IDataPacket)dpObj;
rv = new DataPacket(new BlueTable(dp.newRows), new BlueTable(dp.addedRows), new BlueTable(dp.deletedRows));
}
return rv;
}
/**************************************TEST METHOD(S)*********************************************/
/// <summary>
/// Used for testing purposes only. This enables the test to work without a DataSource (PubServer,
@@ -159,7 +179,9 @@ namespace BCG
/// </summary>
/// <param name="leftPacket"></param>
/// <param name="rightPacket"></param>
public void test (DataPacket dp, bool isLeft) {myIjs.test (dp, isLeft);}
public void test (DataPacket dp, bool isLeft) {
ExceptionAssert.NotNull(myIjs).test(dp, isLeft);
}
/***********************************************************************************************/
}
}
@@ -1,14 +1,17 @@
using Bts.DataStreamCore;
using Spark.Core.Diagnostics;
using System;
using System.Collections;
using System.IO;
using BCG.Utilities.General;
using System.Collections.Generic;
namespace BCG
{
internal class JoinTable : IBlueRowCollection
{
protected JoinTableSchema mySchema;
protected IDictionary myIdIndex = new Hashtable ();
protected readonly Dictionary<int, IBlueRow> myIdIndex = new();
protected JoinDeletionIndex myLeftIndex, myRightIndex;
private int myNewRowId;
@@ -19,19 +22,16 @@ namespace BCG
myRightIndex = new JoinDeletionIndex (mySchema.getRenamedName ("id", false), false);
}
public IBlueRow this [int id]
{
get
{
if (myIdIndex[id] == null)
throw new BlueDataException ("ID " + id.ToString() + " does not exist in table " + mySchema.tableName);
return (IBlueRow)myIdIndex[id];
public IBlueRow this [int id] {
get {
var rowObj = myIdIndex[id]
?? throw new BlueDataException($"ID {id} does not exist in table {mySchema.tableName}");
return (IBlueRow)rowObj;
}
}
#region JoinTable members
public virtual void addRow (IBlueRow leftRow, IBlueRow rightRow, DataPacket dp)
{
public virtual void addRow(IBlueRow leftRow, IBlueRow? rightRow, IDataPacket dp) {
JoinRow newRow = new JoinRow (myNewRowId, leftRow, rightRow, mySchema);
myIdIndex[myNewRowId ++] = newRow;
((BlueTable)(dp.addedRows)).addRow (newRow);
@@ -40,7 +40,7 @@ namespace BCG
myRightIndex.add (newRow);
}
public virtual void deleteRow (bool isLeft, IBlueRow deletedRow, DataPacket dp)
public virtual void deleteRow (bool isLeft, IBlueRow deletedRow, IDataPacket dp)
{
JoinDeletionIndex thisIndex = myRightIndex, otherIndex = myLeftIndex;
if (isLeft)
@@ -48,17 +48,17 @@ namespace BCG
thisIndex = myLeftIndex;
otherIndex = myRightIndex;
}
RowList matchingNodes = thisIndex.getMatchingRows (deletedRow["id"]);
RowList matchingNodes = thisIndex.getMatchingRows(deletedRow.Id());
foreach (RowNode node in matchingNodes)
{
JoinRow row = (JoinRow)node.row;
RowNode correspondingNode = isLeft ? row.rightNode : row.leftNode;
var row = ExceptionAssert.Argument.Is<JoinRow>(node.row);
RowNode? correspondingNode = isLeft ? row.rightNode : row.leftNode;
if (correspondingNode != null)
otherIndex.remove (correspondingNode); //in case of partial left joinss
myIdIndex.Remove (row["id"]);
myIdIndex.Remove(row.Id());
((BlueTable)dp.deletedRows).addRow (row);
}
thisIndex.removeAll (deletedRow["id"]);
thisIndex.removeAll(deletedRow.Id());
}
#endregion
#region ICollection members
@@ -68,7 +68,11 @@ namespace BCG
public object SyncRoot{get{return this;}}
public void CopyTo (Array array, int index) {myIdIndex.Values.CopyTo (array, index);}
public void CopyTo (Array array, int index) {
foreach (var row in myIdIndex.Values) {
array.SetValue(row, index++);
}
}
#endregion
#region IEnumerable members
@@ -1,9 +1,8 @@
using System;
using System.Collections;
using BCG.Utilities;
using bts;
using System.Collections.Generic;
using System.Linq;
namespace BCG
{
/// <summary>
@@ -13,10 +12,11 @@ namespace BCG
public class JoinTableSchema : BlueTableSchema
{
private string myLeftJc = "", myRightJc = "", myLeftId = "", myRightId = "";
private IDictionary myLeftNameToAlias = new Hashtable ();
private IDictionary myRightNameToAlias = new Hashtable ();
private IDictionary myAliasToLeftName = new Hashtable(),
myAliasToRightName = new Hashtable();
readonly Dictionary<string, string> myLeftNameToAlias = new();
readonly Dictionary<string, string> myRightNameToAlias = new();
readonly Dictionary<string, string> myAliasToLeftName = new();
readonly Dictionary<string, string> myAliasToRightName = new();
/// <summary>
/// Constructs the schema of the Jointable with the schema of the left and right tables. Incase of
/// a name being there in both the shemas it prefixes the name with "L." or "R." accordingly. Column "id"
@@ -85,9 +85,9 @@ namespace BCG
renamed = false;
}
myIndexByColName["id"] = new ColumnInfo("id", myIndexByColName.Count, typeof(int));
myIndexByColOrder[myIndexByColOrder.Length - 1] = (ColumnInfo)myIndexByColName["id"];
myAliasToLeftName = ProjectHelper.invertDic(myLeftNameToAlias);
myAliasToRightName = ProjectHelper.invertDic(myRightNameToAlias);
myIndexByColOrder[myIndexByColOrder.Length - 1] = myIndexByColName["id"];
myAliasToLeftName = myLeftNameToAlias.ToDictionary(kv => kv.Value, kv => kv.Key);
myAliasToRightName = myRightNameToAlias.ToDictionary(kv => kv.Value, kv => kv.Key);
}
public string leftJoinCol {get{return myLeftJc;}}
@@ -1,17 +1,21 @@
using bts;
using bts.collections;
using Bts.DataStreamCore;
using mbts;
using Spark.Core.Diagnostics;
using Spark.Core.Disposables;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Cryptography;
using System.Diagnostics.CodeAnalysis;
namespace BCG {
public class NonIncJoinBookkeeper : IDisposable {
public Action on_new_data;
public event Action? on_new_data;
private readonly NonIncJoinSpec _join_spec;
private readonly int _join_position;
private readonly int _start_index_in_output;
@@ -20,13 +24,14 @@ namespace BCG {
private readonly bool _is_tag_along;
private int _n_total_fires = 0, _n_expensive_fires = 0;
private IBlueTableSchema _schema = null;
IBlueTableSchema? _schema;
private IDictionary<int, IBlueRow> _row_map = new Dictionary<int, IBlueRow>();
private List<Pair<int, IBlueRow>> _row_list = new List<Pair<int, IBlueRow>>();
private IBlueRow _solitary_row = null;
IBlueRow? _solitary_row;
private int[] _join_col_indices = null,
_data_col_indices = null;
int[]? _join_col_indices;
int[]? _data_col_indices;
IDisposable? subscription;
public NonIncJoinBookkeeper(NonIncJoinSpec the_join_spec, int join_position, int start_index_in_output, BlueRowHasher row_hasher) {
_join_spec = the_join_spec;
@@ -38,7 +43,7 @@ namespace BCG {
}
private bool _filled_missing_data = false;
private void _fill_missing_data(DataPacket dp) {
void _fill_missing_data(IDataPacket dp) {
if (_filled_missing_data)
return;
Func<string[], bool> null_or_empty = (str_arr) => {
@@ -52,17 +57,17 @@ namespace BCG {
return true;
};
Func<string[], string[]> remove_bad_cols = (col_names) => {
HashSet<string> schema_col_map = new HashSet<string>(dp.schema.columnNames);
HashSet<string> schema_col_map = new HashSet<string>(dp.Schema.columnNames);
List<string> cols_list = new List<string>(col_names);
cols_list.RemoveWhere(c => !schema_col_map.Contains(c));
return cols_list.ToArray();
};
if (null_or_empty(_join_spec.data_col_names)) {
_join_spec.data_col_names = dp.schema.columnNames;
_join_spec.data_col_names = dp.Schema.columnNames;
}
_join_spec.data_col_names = remove_bad_cols(_join_spec.data_col_names);
if (null_or_empty(_join_spec.data_col_names)) {
_join_spec.data_col_names = dp.schema.columnNames;
_join_spec.data_col_names = dp.Schema.columnNames;
}
if (null_or_empty(_join_spec.projected_col_names)) {
_join_spec.projected_col_names = _join_spec.data_col_names;
@@ -70,20 +75,16 @@ namespace BCG {
}
public void init() {
_join_spec.stream.onChange += _on_stream_cb;
ExceptionAssert.MemberIsNull(subscription);
subscription = ExceptionAssert.MemberNotNull(_join_spec.stream).Subscribe(_on_stream_cb);
}
public void _on_stream_cb(object dp_obj) {
//Log.Gen.info($"NonIncJoinBookkeeper._on_stream_cb dp_obj: {dp_obj}");
var timer = Stopwatch.StartNew();
DataPacket dp = (DataPacket)dp_obj;
var dp = (IDataPacket)dp_obj;
_fill_missing_data(dp);
if (_schema == null) {
_schema = dp.schema;
_join_col_indices = BlueDataUtility.get_column_indices(_schema, _join_spec.join_col_names);
_data_col_indices = BlueDataUtility.get_column_indices(_schema, _join_spec.data_col_names);
}
init(dp);
if (_is_left_most) {
_row_list.Clear();
foreach (IBlueRow r in dp.newRows)
@@ -108,44 +109,68 @@ namespace BCG {
on_new_data();
}
[MemberNotNullWhen(true, nameof(_schema))]
public bool is_ready { get { return _schema != null; } }
public void constribute_cols_to_schema(List<ColumnInfo> cis) {
requireReady();
for (int i = 0; i < _join_spec.data_col_names.Length; i++)
cis.Add(new ColumnInfo(_join_spec.projected_col_names[i], cis.Count, _schema[_join_spec.data_col_names[i]].colType));
}
public List<Pair<int, IBlueRow>> get_list() { return _row_list; }
public void copy_master_row_to_output_row(int row_index, object[] output_row) {
IBlueRow this_row = _row_list[row_index].second;
BlueDataUtility.copy_to_row(this_row, _data_col_indices, output_row, _start_index_in_output);
}
public void copy_master_row_to_output_row(int row_index, object?[] output_row) =>
copyRow(ExceptionAssert.NotNull(_row_list[row_index].second), output_row);
public void copy_matching_row_to_output_row(int row_hash, object[] output_row) {
public void copy_matching_row_to_output_row(int row_hash, object?[] output_row) {
if (_is_tag_along) {
if (_solitary_row != null)
BlueDataUtility.copy_to_row(_solitary_row, _data_col_indices, output_row, _start_index_in_output);
copyRow(_solitary_row, output_row);
else
copy_dbnull_to_output_row(output_row);
} else {
IBlueRow this_row = null;
if (_row_map.TryGetValue(row_hash, out this_row))
BlueDataUtility.copy_to_row(this_row, _data_col_indices, output_row, _start_index_in_output);
if (_row_map.TryGetValue(row_hash, out var this_row))
copyRow(this_row, output_row);
else
copy_dbnull_to_output_row(output_row);
}
}
private void copy_dbnull_to_output_row(object[] output_row) {
void copy_dbnull_to_output_row(object?[] output_row) {
requireDataColIndices();
for (int i = 0; i < _data_col_indices.Length; i++)
output_row[i + _start_index_in_output] = DBNull.Value;
}
#region IDisposable
public void Dispose() { _join_spec.stream.onChange -= _on_stream_cb; }
public void Dispose() =>
Disposable.Dispose(ref subscription);
#endregion
void copyRow(IBlueRow src, object?[] dst) {
requireDataColIndices();
BlueDataUtility.copy_to_row(src, _data_col_indices, dst, _start_index_in_output);
}
[MemberNotNull(nameof(_schema), nameof(_join_col_indices), nameof(_data_col_indices))]
void init(IDataPacket dp) {
_schema ??= dp.Schema;
_join_col_indices ??= BlueDataUtility.get_column_indices(_schema, _join_spec.join_col_names);
_data_col_indices ??= BlueDataUtility.get_column_indices(_schema, _join_spec.data_col_names);
}
[MemberNotNull(nameof(_data_col_indices))]
int[] requireDataColIndices() =>
ExceptionAssert.NotNull(_data_col_indices);
[MemberNotNull(nameof(_schema))]
void requireReady() {
if (!is_ready) {
throw new InvalidOperationException("Not ready");
}
}
}
}
@@ -1,22 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using mbts;
using mbts;
using System;
using System.Collections.Generic;
namespace BCG {
// this a collection of data, theres no joining logic in here
public class NonIncJoinSpec {
public ViewStream stream;
public ViewStream? stream;
// join col names are the names on which the streams are joined (for equality),
// data col names are the names in the original stream
// projected col names are their new names, ie if its x:l_x, then x is in the
// data_col_names and l_x in projected cols
public string[] join_col_names, data_col_names, projected_col_names;
public string[] join_col_names;
public string[] data_col_names;
public string[] projected_col_names;
public NonIncJoinSpec() { }
public NonIncJoinSpec() {
join_col_names = Array.Empty<string>();
data_col_names = Array.Empty<string>();
projected_col_names = Array.Empty<string>();
}
public NonIncJoinSpec(ViewStream the_stream, string[] the_join_col_names, string[] the_data_col_names)
: this(the_stream, the_join_col_names, the_data_col_names, the_data_col_names) { }
@@ -5,18 +5,19 @@ using mbts;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
namespace BCG {
[DataStreamUserRespresentation("fastJoin")]
public class NonIncJoinStream : ViewStream, BCG.Utilities.General.IWorker {
private readonly NonIncJoinSpec[] _join_specs;
private readonly INonIncJoinInlineMapper _output_mapper;
readonly INonIncJoinInlineMapper? _output_mapper;
private readonly BlueRowHasher _row_hasher;
private readonly TimeSpan _throttle_period;
private readonly ViewStreamDatabase _vsd;
private List<NonIncJoinBookkeeper> _book_keeping_data = new List<NonIncJoinBookkeeper>();
private IBlueTableSchema _output_schema = null;
IBlueTableSchema? _output_schema;
private DateTime _last_fire_time = DateTime.MinValue;
private bool _is_dirty = false;
@@ -35,10 +36,10 @@ namespace BCG {
params Triplet<ViewStream, string, string>[] join_specs)
: this(vsd, NonIncJoinSpec.from_triplet(join_specs), output_mapper, throttles_ms) { }
public NonIncJoinStream(NonIncJoinSpec[] join_specs, INonIncJoinInlineMapper output_mapper, int throttles_ms = 0)
public NonIncJoinStream(NonIncJoinSpec[] join_specs, INonIncJoinInlineMapper? output_mapper, int throttles_ms = 0)
: this(ViewStreamDatabase.instance, join_specs, output_mapper, throttles_ms) { }
public NonIncJoinStream(ViewStreamDatabase vsd, NonIncJoinSpec[] join_specs, INonIncJoinInlineMapper output_mapper, int throttles_ms = 0) {
public NonIncJoinStream(ViewStreamDatabase vsd, NonIncJoinSpec[] join_specs, INonIncJoinInlineMapper? output_mapper, int throttles_ms = 0) {
_join_specs = join_specs;
_output_mapper = output_mapper;
_row_hasher = new BlueRowHasher(_join_specs[0].join_col_names.Length);
@@ -88,6 +89,7 @@ namespace BCG {
return rv;
}
[MemberNotNull(nameof(_output_schema))]
private void _construct_schema() {
if (_output_schema == null) {
List<ColumnInfo> cis = new List<ColumnInfo>(new ColumnInfo[] { new ColumnInfo("id", 0, typeof(int)) });
@@ -2,11 +2,12 @@ namespace bts {
using BCG;
using BCG.Utilities.General;
using Spark.Core.Diagnostics;
using Spark.Core.Disposables;
using System;
using System.Diagnostics;
using ZstdSharp.Unsafe;
// functon that joins the 2 rows and returns the outputput row. The function
// can return a null which means the 2 rows dont need to be joined
using JoinFunc = System.Func<BCG.IBlueRow, BCG.IBlueRow, BCG.IBlueRow>;
@@ -16,6 +17,10 @@ namespace bts {
private bool _dirty = false;
private Stopwatch _stopwatch = new Stopwatch();
private ViewStreamDatabase _vsd = ViewStreamDatabase.instance;
IDisposable? subscription;
IBlueRowCollection? leftRows;
IBlueRowCollection? rightRows;
public ProximityJoinStream(ViewStream lvs, ViewStream rvs, JoinFunc join_func) {
_lvs = lvs;
_rvs = rvs;
@@ -23,46 +28,56 @@ namespace bts {
}
protected override void myOnFirstSubscriber() {
_lvs.onChange += _handle_data;
_rvs.onChange += _handle_data;
_lvs.onChange += OnLeftChange;
_rvs.onChange += OnRightChange;
subscription = Disposable.Create(Unsubscribe);
_vsd.addWorker(this);
void OnLeftChange(object dp_obj) {
leftRows = ExceptionAssert.Argument.Is<IDataPacket>(dp_obj).newRows;
_dirty = true;
doWork();
}
void OnRightChange(object dp_obj) {
rightRows = ExceptionAssert.Argument.Is<IDataPacket>(dp_obj).newRows;
_dirty = true;
doWork();
}
void Unsubscribe() {
_lvs.onChange -= OnLeftChange;
_rvs.onChange -= OnRightChange;
}
}
protected override void myOnLastSubscriber() {
_lvs.onChange -= _handle_data;
_rvs.onChange -= _handle_data;
subscription?.Dispose();
subscription = null;
_vsd.removeWorker(this);
}
private void _handle_data(object dp_obj) {
_dirty = true;
doWork();
}
public void doWork() {
Func<bool> all_data_revcd = () => {
return _lvs.rows != null && _rvs.rows != null;
};
_stopwatch.Start();
if (_dirty && all_data_revcd()) {
_dirty = false;
BlueTable rv = null;
foreach (IBlueRow lr in _lvs.rows) {
foreach (IBlueRow rr in _rvs.rows) {
IBlueRow resr = _join_func(lr, rr);
if (resr == null)
continue;
rv = rv ?? new BlueTable(resr.schema);
rv.addRow(resr);
}
}
_stopwatch.Stop();
Log.Gen.info($"ProximityJoinStream left_count: {_lvs.rows.Count} right_count: {_rvs.rows.Count} result_count: {rv.Count} time: {_stopwatch.ElapsedMilliseconds} msecs");
var dp = BlueDataUtility.build_dp_inc(rv, myLastValue as DataPacket);
myFireEvent(dp);
if (!_dirty || leftRows is null || rightRows is null) {
return;
}
_stopwatch.Start();
_dirty = false;
BlueTable? rv = null;
foreach (IBlueRow lr in leftRows) {
foreach (IBlueRow rr in rightRows) {
IBlueRow resr = _join_func(lr, rr);
if (resr == null)
continue;
rv = rv ?? new BlueTable(resr.schema);
rv.addRow(resr);
}
}
_stopwatch.Stop();
Log.Gen.info($"ProximityJoinStream left_count: {leftRows.Count} right_count: {rightRows.Count} result_count: {rv?.Count ?? 0} time: {_stopwatch.ElapsedMilliseconds} msecs");
var dp = BlueDataUtility.build_dp_inc(rv, myLastValue as DataPacket);
myFireEvent(dp);
}
}
}
}
@@ -1,3 +1,5 @@
using Spark.Core.Diagnostics;
using System;
using System.Collections;
@@ -9,7 +11,7 @@ namespace BCG
/// </summary>
internal class RowList : ICollection
{
private RowNode myFirstPtr;
RowNode? myFirstPtr;
private int myCount = 0;
#region ICollection methods
@@ -67,19 +69,19 @@ namespace BCG
}
else if (node.isFirst)
{
myFirstPtr = myFirstPtr.next;
myFirstPtr.previous = null;
myFirstPtr = ExceptionAssert.NotNull(myFirstPtr).next;
ExceptionAssert.NotNull(myFirstPtr).previous = null;
return;
}
else if (node.isLast)
{
node.previous.next = null;
ExceptionAssert.NotNull(node.previous).next = null;
return;
}
else if (!node.isFirst && !node.isLast)
{
node.previous.next = node.next;
node.next.previous = node.previous;
ExceptionAssert.NotNull(node.previous).next = node.next;
ExceptionAssert.NotNull(node.next).previous = node.previous;
return;
}
else
@@ -91,14 +93,16 @@ namespace BCG
internal class RowListEnumerator : IEnumerator
{
private RowNode myPointer;
RowNode? myPointer;
private RowList myList;
private int myPos = -1;
public RowListEnumerator (RowList list) {myList = list;}
public object Current {get{return myPointer;}}
public object? Current => myPointer;
public bool MoveNext()
{
myPointer = myPos == -1 ? myList.myFirstPtr : myPointer.next;
myPointer = myPos == -1
? myList.myFirstPtr
: ExceptionAssert.NotNull(myPointer).next;
myPos ++;
return myPointer != null;
}
@@ -108,28 +112,24 @@ namespace BCG
internal class RowNode
{
private IBlueRow myRow;
private RowNode myNext;
private RowNode myPrevious;
private RowList myList;
public RowNode (IBlueRow row){myRow = row;}
public RowNode (IBlueRow row, RowList list) : this (row) {myList = list;}
public bool isLast {get{return myNext == null;}}
public bool isFirst {get{return myPrevious == null;}}
public RowList list {get{return myList;}}
public IBlueRow row
{
get{return myRow;}
set{myRow = value;}
}
public RowNode next {
get{return myNext;}
set{myNext = value;}
}
public RowNode previous {
get{return myPrevious;}
set{myPrevious = value;}
}
public RowNode (IBlueRow row) =>
this.row = row;
public RowNode (IBlueRow row, RowList list)
: this(row) =>
this.list = list;
public bool isLast => next is null;
public bool isFirst => previous is null;
public RowList? list { get; }
public IBlueRow? row { get; set; }
public RowNode? next { get; set; }
public RowNode? previous { get; set; }
public RowList RequireList() =>
ExceptionAssert.MemberNotNull(list);
public IBlueRow RequireRow() =>
ExceptionAssert.MemberNotNull(row);
}
}
@@ -1,125 +1,17 @@
using Bts.DataStreamCore;
using mbts;
using Spark.Core.Collections;
using Spark.Core.Diagnostics;
using System;
using System.Collections;
using System.Collections.Generic;
using mbts;
using Spark.Core.Collections;
using System.Diagnostics.CodeAnalysis;
namespace BCG
{
internal class SingleRowJoinDicionary<TKey, TValue> : IDictionary<TKey, TValue>
{
private TKey myKey;
private TValue myValue;
#region IDictionary<TKey,TValue> Members
public void Add(TKey key, TValue value)
{
myKey = key;
myValue = value;
}
public bool ContainsKey(TKey key)
{
return myKey.Equals(key);
}
public ICollection<TKey> Keys
{
get { return new TKey[] { myKey }; }
}
public bool Remove(TKey key)
{
bool rv = myKey.Equals(key);
myKey = default(TKey);
return rv;
}
public bool TryGetValue(TKey key, out TValue value)
{
bool rv = false;
value = (rv = myKey.Equals(key)) ? myValue : default(TValue);
return rv;
}
public ICollection<TValue> Values
{
get { throw new Exception("The method or operation is not implemented."); }
}
public TValue this[TKey key]
{
get
{
throw new Exception("The method or operation is not implemented.");
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
#endregion
#region ICollection<KeyValuePair<TKey,TValue>> Members
public void Add(KeyValuePair<TKey, TValue> item)
{
throw new Exception("The method or operation is not implemented.");
}
public void Clear()
{
throw new Exception("The method or operation is not implemented.");
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
throw new Exception("The method or operation is not implemented.");
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
throw new Exception("The method or operation is not implemented.");
}
public int Count
{
get { throw new Exception("The method or operation is not implemented."); }
}
public bool IsReadOnly
{
get { throw new Exception("The method or operation is not implemented."); }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
}
#region Helper class to deal with stream projections
public class JoinProjectHelper
@@ -167,7 +59,7 @@ namespace BCG
{
Pair<string, bool> p = myAliasToOriginal[col];
isLeft = p.second;
return p.first;
return ExceptionAssert.NotNull(p.first);
}
}
@@ -178,10 +70,11 @@ namespace BCG
public class SuperJoinRow : IBlueRow
{
private JoinProjectHelper myHelper;
private IBlueRow myLeftRow, myRightRow;
IBlueRow myLeftRow;
IBlueRow? myRightRow;
int myID;
public SuperJoinRow(int id, IBlueRow leftRow, IBlueRow rightRow, JoinProjectHelper joinProjectHelper)
public SuperJoinRow(int id, IBlueRow leftRow, IBlueRow? rightRow, JoinProjectHelper joinProjectHelper)
{
myID = id;
myLeftRow = leftRow;
@@ -189,21 +82,22 @@ namespace BCG
myHelper = joinProjectHelper;
}
public int leftID { get { return (int)myLeftRow["id"]; } }
public int leftID => myLeftRow.Id();
public int rightID { get { return (int)myRightRow["id"]; } }
public int rightID => myRightRow.Id();
public IBlueRow leftRow { get { return myLeftRow; } }
public IBlueRow rightRow { get { return myRightRow; } }
public IBlueRow? rightRow => myRightRow;
#region IBlueRow Members
public IBlueTableSchema schema { get { return myHelper.schema; } }
public object this[int index] { get { return this[schema[index].colName]; } }
public object? this[int index] =>
this[schema[index].colName];
public object this[string colName]
public object? this[string colName]
{
get
{
@@ -229,7 +123,7 @@ namespace BCG
public bool Contains(object key)
{
return myLeftRow.Contains(key) || myRightRow.Contains(key);
return myLeftRow.Contains(key) || (myRightRow?.Contains(key) ?? false);
}
public System.Collections.IDictionaryEnumerator GetEnumerator() { return new BlueRowDictionaryEnumerator(this); }
@@ -242,11 +136,11 @@ namespace BCG
public void Remove(object key) { throw new NotSupportedException("IBlueRow is readonly"); }
public System.Collections.ICollection Values
public ICollection Values
{
get
{
List<object> rv = new List<object>();
var rv = new List<object?>(Keys.Count);
foreach (string col in Keys)
rv.Add(this[col]);
return rv;
@@ -291,9 +185,10 @@ namespace BCG
myLeftUnmatchedRowsDels = new Dictionary<int, IBlueRow>();
private bool myManageUnmappedLeftRows = false;
protected string myLeftProj = String.Empty, myRightProj = String.Empty;
protected IBlueTableSchema myLeftSchema, myRightSchema;
protected JoinProjectHelper myJoinProjectHelper;
protected BlueTable myState;
protected IBlueTableSchema? myLeftSchema;
protected IBlueTableSchema? myRightSchema;
protected JoinProjectHelper? myJoinProjectHelper;
protected BlueTable? myState;
protected int myID;
protected ViewStream myLeftStream, myRightStream;
protected string myLeftKeyCol, myRightKeyCol;
@@ -346,23 +241,19 @@ namespace BCG
private void myHandleLeftStreamChanges(object newValue)
{
myHandleStreamChanges(newValue as DataPacket, true);
myHandleStreamChanges((IDataPacket)newValue, true);
}
private void myHandleRightStreamChanges(object newValue)
{
myHandleStreamChanges(newValue as DataPacket, false);
myHandleStreamChanges((IDataPacket)newValue, false);
}
private void myHandleStreamChanges(DataPacket dp, bool isLeft)
private void myHandleStreamChanges(IDataPacket dp, bool isLeft)
{
myInitSchema(dp.schema, isLeft);
BlueTable dels = null, adds = null;
if (myState != null)
{
dels = new BlueTable(myState.schema);
adds = new BlueTable(myState.schema);
}
myInitSchema(dp.Schema, isLeft);
var dels = new BlueTable(myState.schema);
var adds = new BlueTable(myState.schema);
myDeleteRows(dp.deletedRows, isLeft, myState, dels);
myAddRows(dp.addedRows, isLeft, myState, adds);
if (myState != null)
@@ -373,6 +264,7 @@ namespace BCG
}
}
[MemberNotNull(nameof(myState))]
private void myInitSchema(IBlueTableSchema schema, bool isLeft)
{
if (myState == null)
@@ -402,6 +294,7 @@ namespace BCG
private void myAddRows(IBlueRowCollection addedRows, bool isLeft, BlueTable state, BlueTable addedRowsOut)
{
ExceptionAssert.NotNull(myJoinProjectHelper);
object thisKeyCol = isLeft ? myLeftKeyCol : myRightKeyCol,
otherSideKeyCol = isLeft ? myRightKeyCol : myLeftKeyCol;
Dictionary<object, IDictionary<int, IBlueRow>> thisKeyToRows = isLeft ? myLeftKeyToLeftRows : myRightKeyToRightRows,
@@ -410,8 +303,8 @@ namespace BCG
otherIDToResultRows = isLeft ? myRightIDToResultRows : myLeftIDToResultRows;
foreach (IBlueRow r in addedRows)
{
object currentKey = r[thisKeyCol];
int currentID = (int)r["id"];
object currentKey = ExceptionAssert.NotNull(r[thisKeyCol]);
int currentID = r.Id();
///add it to 1.
if (!thisKeyToRows.ContainsKey(currentKey))
thisKeyToRows.Add(currentKey, new Dictionary<int, IBlueRow>());
@@ -422,14 +315,14 @@ namespace BCG
ICollection<IBlueRow> matchingRows = otherSideKeyToRows[currentKey].Values;
foreach (IBlueRow mr in matchingRows)
{
int mrID = (int)mr["id"];
int mrID = mr.Id();
SuperJoinRow rr = new SuperJoinRow(myID++, isLeft ? r : mr, isLeft ? mr : r, myJoinProjectHelper);
state.addRow(rr);
addedRowsOut.addRow(rr);
///add to 3.
if (!thisIDToResultRows.ContainsKey(currentID))
thisIDToResultRows.Add(currentID, new Dictionary<int, SuperJoinRow>());
thisIDToResultRows[currentID].Add((int)rr["id"], rr);
thisIDToResultRows[currentID].Add(rr.Id(), rr);
///add to 4.
if (!otherIDToResultRows.ContainsKey(mrID))
{
@@ -437,7 +330,7 @@ namespace BCG
if (myManageUnmappedLeftRows && !isLeft)
myTakeCareOfUnmatachedLeftRows(mr, false);
}
otherIDToResultRows[mrID].Add((int)rr["id"], rr);
otherIDToResultRows[mrID].Add(rr.Id(), rr);
}
}
else
@@ -458,22 +351,22 @@ namespace BCG
otherIDToResultRows = isLeft ? myRightIDToResultRows : myLeftIDToResultRows;
foreach (IBlueRow r in deletedRows)
{
int id = (int)r["id"];
object key = r[thisKeyCol];
int id = r.Id();
object key = ExceptionAssert.NotNull(r[thisKeyCol]);
///delete it from 1.
thisKeyToRows[key].Remove(id);
if (thisKeyToRows[key].Count == 0)
thisKeyToRows.Remove(key);
///form return rows and delete from 3.
if (thisIDToResultRows.ContainsKey(id))
if (thisIDToResultRows.TryGetValue(id, out IDictionary<int, SuperJoinRow>? removedResultRowMap))
{
ICollection removedResultRows = thisIDToResultRows[id].Values as ICollection;
var removedResultRows = (ICollection)removedResultRowMap.Values;
thisIDToResultRows.Remove(id);
foreach (SuperJoinRow rr in removedResultRows)
{
///delete from 4.
int otherId = isLeft ? rr.rightID : rr.leftID;
otherIDToResultRows[otherId].Remove((int)rr["id"]);
otherIDToResultRows[otherId].Remove(rr.Id());
if (otherIDToResultRows[otherId].Count == 0)
otherIDToResultRows.Remove(otherId);
delRowsOut.addRow(rr);
@@ -493,7 +386,7 @@ namespace BCG
private void myTakeCareOfUnmatachedLeftRows(IBlueRow leftRow, bool add)
{
int lid = (int)leftRow["id"];
int lid = leftRow.Id();
if (add)
myLeftUnmatchedRowsAdds.Add(lid, leftRow);
else
@@ -501,7 +394,7 @@ namespace BCG
if (myLeftUnmatchedRowsAdds.ContainsKey(lid))
myLeftUnmatchedRowsAdds.Remove(lid);
else
myLeftUnmatchedRowsDels.Add((int)leftRow["id"], leftRow);
myLeftUnmatchedRowsDels.Add(lid, leftRow);
}
}
}
@@ -522,44 +415,49 @@ namespace BCG
protected override void myFireEvent(object o)
{
myHandleJoinResults(myLeftUnmatchedRowsDels, myLeftUnmatchedRowsAdds, o as DataPacket);
myHandleJoinResults(myLeftUnmatchedRowsDels, myLeftUnmatchedRowsAdds, (IDataPacket)o);
}
private void myHandleJoinResults(Dictionary<int, IBlueRow> unmatchedLeftRowsDels,
Dictionary<int, IBlueRow> unmatchedLeftRowAdds, DataPacket resultPacket)
{
BlueTable dels = resultPacket.deletedRows as BlueTable,
adds = resultPacket.addedRows as BlueTable;
void myHandleJoinResults(Dictionary<int, IBlueRow> unmatchedLeftRowsDels, Dictionary<int, IBlueRow> unmatchedLeftRowAdds, IDataPacket resultPacket) {
ExceptionAssert.NotNull(myJoinProjectHelper);
var dels = resultPacket.deletedRows;
var adds = resultPacket.addedRows;
foreach (IBlueRow lr in unmatchedLeftRowsDels.Values)
{
///an lr will be here if its actually deleted or
///a right row is added, so now it has a partner
///and is no longer unmatched.
///in both cases the half row that this lr
///created needs to be removed from this
///class's state and added to dels
///it means a right is added
int lid = (int)lr["id"];
SuperJoinRow rr = myLeftIDToHalfRows[lid];
myLeftIDToHalfRows.Remove(lid);
myState.deleteRow(rr);
dels.addRow(rr);
if (unmatchedLeftRowsDels.Count > 0) {
ExceptionAssert.NotNull(myState);
var mutableDels = (BlueTable)dels;
foreach (IBlueRow lr in unmatchedLeftRowsDels.Values) {
///an lr will be here if its actually deleted or
///a right row is added, so now it has a partner
///and is no longer unmatched.
///in both cases the half row that this lr
///created needs to be removed from this
///class's state and added to dels
///it means a right is added
int lid = lr.Id();
SuperJoinRow rr = myLeftIDToHalfRows[lid];
myLeftIDToHalfRows.Remove(lid);
myState.deleteRow(rr);
mutableDels.addRow(rr);
}
}
foreach (IBlueRow lr in unmatchedLeftRowAdds.Values)
{
///an lr will be here if its added with no
///matching right, or a right matching row
///is gone so it is unmatched now.
///in both cases a half row needs to be
///added to this class's state and added
///to adds
int lid = (int)lr["id"];
SuperJoinRow rr = new SuperJoinRow(myID++, lr, null, myJoinProjectHelper);
myLeftIDToHalfRows.Add(lid, rr);
myState.addRow(rr);
adds.addRow(rr);
if (unmatchedLeftRowAdds.Count > 0) {
ExceptionAssert.NotNull(myState);
var mutableAdds = (BlueTable)adds;
foreach (IBlueRow lr in unmatchedLeftRowAdds.Values) {
///an lr will be here if its added with no
///matching right, or a right matching row
///is gone so it is unmatched now.
///in both cases a half row needs to be
///added to this class's state and added
///to adds
int lid = lr.Id();
SuperJoinRow rr = new SuperJoinRow(myID++, lr, null, myJoinProjectHelper);
myLeftIDToHalfRows.Add(lid, rr);
myState.addRow(rr);
mutableAdds.addRow(rr);
}
}
base.myFireEvent(new DataPacket(myState, adds, dels));
}
@@ -1,6 +1,4 @@
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;
@@ -20,7 +18,7 @@ namespace BCG {
}
private void _on_str_update(object dp_obj) {
DataPacket dp = dp_obj as DataPacket;
var dp = (IDataPacket)dp_obj;
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);
@@ -28,4 +26,4 @@ namespace BCG {
}
}
}
}
@@ -1,6 +1,9 @@
using Bts.DataStreamCore;
using Spark.Core.Diagnostics;
using System;
using System.Collections;
using BCG.Utilities;
using System.Collections.Generic;
namespace BCG
{
@@ -11,9 +14,11 @@ namespace BCG
[DataStreamUserRespresentation (false)]
public class LeftInternalJoinStream : InternalJoinStream
{
protected DataPacket myLeftDataPacket, myRightDataPacket;
protected IDataPacket? myLeftDataPacket;
protected IDataPacket? myRightDataPacket;
//Container to contain all the left rows that are orphaned during a deletion operation
private IDictionary myLeftOrphanedRows;
Dictionary<int, RowNode>? myLeftOrphanedRows;
public LeftInternalJoinStream (ViewStream vsLeft, string jcLeft, ViewStream vsRight, string jcRight) :
base (vsLeft, jcLeft, vsRight, jcRight) {}
@@ -62,7 +67,9 @@ namespace BCG
private void myTestAndFire (bool isLeft)
{
JoinOperand jo = isLeft ? myLeftOperand : myRightOperand;
DataPacket dp = isLeft ? myLeftDataPacket : myRightDataPacket;
var dp = isLeft
? ExceptionAssert.NotNull(myLeftDataPacket)
: ExceptionAssert.NotNull(myRightDataPacket);
//to test whether both have received call backs
if (myLeftOperand.hasReceivedData)
jo.changeHandler (dp);
@@ -80,11 +87,13 @@ namespace BCG
/// <param name="isLeft"></param>
public override void addRows (IBlueRowCollection rows, bool isLeft)
{
ExceptionAssert.NotNull(myLastFiredPacket);
foreach (IBlueRow row in rows)
myAddRow (row, isLeft);
if (!isLeft)
foreach (RowNode node in myLeftOrphanedRows.Values)
((JoinTable)myLastFiredPacket.newRows).addRow (node.row, null, myLastFiredPacket);
foreach (RowNode node in ExceptionAssert.NotNull(myLeftOrphanedRows).Values) {
((JoinTable)myLastFiredPacket.newRows).addRow(node.RequireRow(), null, myLastFiredPacket);
}
}
/// <summary>
@@ -94,17 +103,19 @@ namespace BCG
/// <param name="isLeft"></param>
public override void deleteRows (IBlueRowCollection rows, bool isLeft)
{
myLeftOrphanedRows = new Hashtable ();
myLeftOrphanedRows = new();
foreach (IBlueRow row in rows)
myDeleteRow (row, isLeft);
}
private void myAddRow (IBlueRow row, bool isLeft)
{
ExceptionAssert.NotNull(myLastFiredPacket);
if (isLeft)
{
myLeftOperand.addRow (row);
RowList matchedRows = myRightOperand.getMatchingRows (row[myLeftJoinColOrdinal]);
var joinKey = ExceptionAssert.NotNull(row[myLeftJoinColOrdinal]);
RowList matchedRows = myRightOperand.getMatchingRows(joinKey);
if (matchedRows.Count == 0)
((JoinTable)myLastFiredPacket.newRows).addRow (row, null, myLastFiredPacket);
else
@@ -113,22 +124,25 @@ namespace BCG
}
else
{
RowList matchedRows = myLeftOperand.getMatchingRows (row[myRightJoinColOrdinal]);
int rightMatchingRowCount = myRightOperand.getMatchingRows (row[myRightJoinColOrdinal]).Count;
var joinKey = ExceptionAssert.NotNull(row[myRightJoinColOrdinal]);
RowList matchedRows = myLeftOperand.getMatchingRows(joinKey);
int rightMatchingRowCount = myRightOperand.getMatchingRows(joinKey).Count;
myRightOperand.addRow (row);
int newRightMatchingRowCount = myRightOperand.getMatchingRows (row[myRightJoinColOrdinal]).Count;
int newRightMatchingRowCount = myRightOperand.getMatchingRows(joinKey).Count;
if (matchedRows.Count != 0){
foreach (RowNode matchedNode in matchedRows)
{
ExceptionAssert.NotNull(matchedNode.row);
//if the left rows were orphaned in this transaction (ie in this callback), they should
//just be removed from the orphanedlist and we dont need to worry about the consistency of
//the jointable as a new row will replace it
if (rightMatchingRowCount == 0 && newRightMatchingRowCount > 0)
{
if (myLeftOrphanedRows[matchedNode.row["id"]] == null)
((JoinTable)myLastFiredPacket.newRows).deleteRow (true, matchedNode.row, myLastFiredPacket);
else
myLeftOrphanedRows.Remove (matchedNode.row["id"]);
ExceptionAssert.NotNull(myLeftOrphanedRows);
int matchedId = matchedNode.row.Id();
if (!myLeftOrphanedRows.Remove(matchedId)) {
((JoinTable)myLastFiredPacket.newRows).deleteRow(true, matchedNode.row, myLastFiredPacket);
}
}
//they were orphaned by a previous transaction and hence the orphans need to be
//removed from the Jointable and the complete row added
@@ -141,41 +155,52 @@ namespace BCG
private void myDeleteRow (IBlueRow row, bool isLeft)
{
var last = requireLastFiredPacket();
if (isLeft)
{
myLeftOperand.deleteRow (row);
((JoinTable)myLastFiredPacket.newRows).deleteRow (true, row, myLastFiredPacket);
((JoinTable)last.newRows).deleteRow (true, row, myLastFiredPacket);
}
else
{
RowList matchedRows = myLeftOperand.getMatchingRows (row[myRightJoinColOrdinal]);
int rightMatchingRowCount = myRightOperand.getMatchingRows (row[myRightJoinColOrdinal]).Count;
var rightJoinKey = row[myRightJoinColOrdinal] ?? throw new InvalidOperationException("RightJoinKey is null");
RowList matchedRows = myLeftOperand.getMatchingRows(rightJoinKey);
int rightMatchingRowCount = myRightOperand.getMatchingRows(rightJoinKey).Count;
myRightOperand.deleteRow (row);
int newRightMatchingRowCount = myRightOperand.getMatchingRows (row[myRightJoinColOrdinal]).Count;
int newRightMatchingRowCount = myRightOperand.getMatchingRows(rightJoinKey).Count;
if (matchedRows.Count != 0)
{
if (rightMatchingRowCount > 0 && newRightMatchingRowCount == 0)
if (rightMatchingRowCount > 0 && newRightMatchingRowCount == 0) {
ExceptionAssert.MemberNotNull(myLeftOrphanedRows);
//ie all the matchedRows were joined with 'this' right row (method arg), and hence they need to
//be handled specially, ie joined with nulls, if there are no right rows with this
//joincolumn value being inserted.
ExceptionAssert.NotNull(myLeftOrphanedRows);
foreach (RowNode matchedNode in matchedRows)
{
// BlueEventLog.logAssert (myLeftOrphanedRows[matchedNode.row["id"]] == null);
myLeftOrphanedRows[matchedNode.row["id"]] = matchedNode;
myLeftOrphanedRows[matchedNode.row.Id()] = matchedNode;
}
((JoinTable)myLastFiredPacket.newRows).deleteRow (false, row, myLastFiredPacket);
}
((JoinTable)last.newRows).deleteRow (false, row, myLastFiredPacket);
}
}
}
public override void onTableClear (bool isLeft)
{
if (myLastFiredPacket is null) {
return;
}
requireSchema();
myLastFiredPacket.deletedRows = myLastFiredPacket.newRows;
myLastFiredPacket.newRows = new JoinTable (mySchema);
myLastFiredPacket.addedRows = new BlueTable (mySchema);
if (!isLeft)
if (!isLeft) {
ExceptionAssert.MemberNotNull(myLeftDataPacket);
foreach (IBlueRow row in myLeftDataPacket.newRows)
((JoinTable)myLastFiredPacket.newRows).addRow (row, null, myLastFiredPacket);
}
}
}
@@ -30,7 +30,7 @@ namespace BCG
/// <summary>
/// Node containing the referencedRow
/// </summary>
IBlueRow referencedRow {get;}
IBlueRow? referencedRow { get; }
/// <summary>
/// removes all referenced or referencing nodes (indicated by the bool), p.s. theres only one referenced row
@@ -15,12 +15,14 @@ namespace BCG
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
IBlueRow getRow (int id);
IBlueRow? getRow(int id);
/// <summary>
/// Gets all the rows in the node
/// </summary>
/// <returns></returns>
IBlueRow[] getRows ();
IBlueRow?[] getRows();
/// <summary>
/// Replaces the row with the given id, with the row passed as the second arg
/// </summary>
@@ -1,7 +1,5 @@
using System;
using System.Collections;
using BCG.Utilities;
using BCG;
namespace BCG
{
@@ -56,13 +54,18 @@ namespace BCG
/// The key can either be the string corrsponding to the column name or
/// the order of the column
/// </summary>
public virtual object this [object key]
public virtual object? this [object key]
{
get {return key is string ? this [key as string] : this [(int)key];}
// get {return key is string ? this [key as string] : this [(int)key];}
get => key switch {
string colName => this[colName],
int colIndex => this[colIndex],
_ => throw new ArgumentException("Must be string or int", nameof(key)),
};
set {throw new NotSupportedException ("The IBlueRow is read only");}
}
public virtual object this [int index]
public virtual object? this [int index]
{
get
{
@@ -77,7 +80,8 @@ namespace BCG
}
}
public object this [string colName] {get{return this[mySchema[colName].colNo];}}
public object? this [string colName] =>
this[mySchema[colName].colNo];
public ICollection Keys{get{return mySchema.columnNames;}}
@@ -1,6 +1,6 @@
using System;
using Spark.Core.Diagnostics;
using System.Collections;
using BCG.Utilities;
namespace BCG
{
@@ -70,7 +70,8 @@ namespace BCG
}
else
{
SimpleNode sn = n as SimpleNode;
var sn = (SimpleNode)n;
ExceptionAssert.NotNull(sn.prev);
sn.prev.next = sn.next;
if (sn.next != null)
sn.next.prev = sn.prev;
@@ -81,7 +82,7 @@ namespace BCG
public int count {get {return myFirst.listCount;}}
public IBlueRow referencedRow {get {return myFirst.row;}}
public IBlueRow? referencedRow => myFirst.row;
public void removeAll (bool isReD)
{
@@ -110,10 +111,11 @@ namespace BCG
public class LightForeignJoinRowListEnumerator : IEnumerator
{
private ILightForeignJoinRowList myList;
private SimpleNode myPtr, myFirst;
private SimpleNode? myPtr;
private SimpleNode myFirst;
public LightForeignJoinRowListEnumerator (ILightForeignJoinRowList list, SimpleNode first)
{myList = list; myFirst = first;}
public object Current {get{return myPtr.row;}}
public object? Current => myPtr?.row;
public bool MoveNext() {return (myPtr = myPtr == null ? myFirst : myPtr.next) != null;}
public void Reset() {myPtr = null;}
public ILightForeignJoinRowList list {get {return myList;}}
@@ -51,7 +51,7 @@ namespace BCG
public void CopyTo (Array array, int index) {throw new NotSupportedException ("");}
public object SyncRoot {get{return null;}}
public object SyncRoot => this;
#endregion
@@ -1,5 +1,4 @@
using System;
using BCG.Utilities;
namespace BCG
{
@@ -13,8 +12,7 @@ namespace BCG
: base (reDRow, rinGRow, schema)
{}
public override object this [int index]
{
public override object? this [int index] {
get
{
if (index == mySchema.columnNames.Length - 1)
@@ -1,5 +1,3 @@
using System;
namespace BCG
{
/// <summary>
@@ -9,15 +7,15 @@ namespace BCG
/// </summary>
public class SimpleNode : INode
{
public IBlueRow row;
public SimpleNode next, prev;
public IBlueRow? row;
public SimpleNode? next;
public SimpleNode? prev;
public SimpleNode (IBlueRow r)
: this (r, null, null)
{}
public SimpleNode (IBlueRow r, SimpleNode nx, SimpleNode pv)
{
public SimpleNode(IBlueRow r, SimpleNode? nx, SimpleNode? pv) {
row = r;
next = nx;
prev = pv;
@@ -25,13 +23,15 @@ namespace BCG
#region INode Members
public IBlueRow getRow (int id) {return row;}
public IBlueRow? getRow(int id) =>
row;
public IBlueRow[] getRows() {return new IBlueRow[] {row};}
public IBlueRow?[] getRows() =>
new[] {row};
public void replace (int id, IBlueRow nr) {row = nr;}
#endregion
}
}
}
@@ -1,14 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Amazon.Runtime.Internal.Util;
using BCG;
using BCG.Utilities;
using bts;
using System;
using System.Collections.Generic;
namespace BCG {
public class LiteralStream : ViewStream {
@@ -42,14 +36,14 @@ namespace BCG {
return new BlueRow(map);
};
string[] row_arr = rows.Split(';', StringSplitOptions.TrimEntries);
BlueTable table = null;
BlueTable? table = null;
foreach (string json_string in row_arr) {
IBlueRow r = //BlueDataUtility.convert_json_to_row(json_string, table == null ? 0 : table.Count);
get_row(json_string, table == null ? 0 : table.Count);
table = table ?? new BlueTable(r.schema);
table ??= new BlueTable(r.schema);
table.addRow(r);
}
ViewStream str = new BlueTableStream(table);
ViewStream str = new BlueTableStream(table ?? throw new ArgumentException("No rows specified, unable to determine schema"));
str = new SchemaGuesserStream(str);
mySetRealSource(str);
}
@@ -2,6 +2,8 @@ using BCG;
using MongoDB.Driver.Core.WireProtocol.Messages;
using Spark.Core.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -37,7 +39,7 @@ namespace bts {
}
void _handle_stream_update(object dp_obj) {
DataPacket dp = dp_obj as DataPacket;
var dp = ExceptionAssert.Argument.Is<IDataPacket>(dp_obj);
IDictionary<int, List<IBlueRow>> groups = !String.IsNullOrEmpty(_group_by_col) ?
BlueDataUtility.group_together(dp.newRows, new string[] { _group_by_col })
:
@@ -1,10 +1,8 @@
using bts;
using Bts.DataStream;
using Bts.DataStreamCore;
using mbts.config;
using mbts.utils;
using Spark.Core.Diagnostics;
using System;
@@ -22,6 +20,7 @@ namespace BCG {
protected IStreamMapper? myMapper;
protected IChangeableStreamMapper? myChangeableMapper;
private bool myUseNewMap = false;
IDisposable? subscription;
public class FuncWrapper : IStreamMapper {
private Func<IBlueTableSchema, IBlueTableSchema> _schema_map_func;
@@ -118,13 +117,13 @@ namespace BCG {
protected override void myOnFirstSubscriber() {
myStream.onChange += new DataStream.ChangeDelegate(myChangeHandler);
subscription = myStream.Subscribe(myChangeHandler);
}
protected override void myOnLastSubscriber() {
myInit();
if (myStream != null)
myStream.onChange -= new DataStream.ChangeDelegate(myChangeHandler);
subscription?.Dispose();
subscription = null;
}
protected override void myOnTableClear() {
@@ -1,6 +1,6 @@
using Bts.DataStreamCore;
using mbts.utils;
using Spark.Core.Diagnostics;
using System;
using System.Collections.Generic;
@@ -93,9 +93,9 @@ namespace BCG {
}
private void myHandleData(object newValue) {
var dp = ExceptionAssert.Cast(newValue).To<DataPacket>();
myRows ??= new BlueTable(myMapper.getOutputSchema(dp.schema));
myBaseRows ??= new BlueTable(dp.schema);
var dp = ExceptionAssert.Cast(newValue).To<IDataPacket>();
myRows ??= new BlueTable(myMapper.getOutputSchema(dp.Schema));
myBaseRows ??= new BlueTable(dp.Schema);
BlueDataUtility.absorbChanges(myBaseRows, dp.deletedRows, dp.addedRows);
var dels = new BlueTable(myRows.schema);
var adds = new BlueTable(myRows.schema);
@@ -1,12 +1,12 @@
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;
using mbts.utils;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace bts {
// listens to the underlying stream, and writes each seriialized packet in a
@@ -31,16 +31,10 @@ namespace bts {
}
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);
var dp = (IDataPacket)dp_obj;
byte[] ser_data = n_updates == 0
? _serializer.serialize(new(new StreamIOMessage.CreateMessage(dp.newRows)))
: _serializer.serialize(new(new StreamIOMessage.MultipleRemoveAddMessage(dp.deletedRows, dp.addedRows)));
_n_updates++;
string file_name = $"{_folder}\\{_n_updates}.bin";
_write_to_file(ser_data, file_name);
@@ -62,7 +56,7 @@ namespace bts {
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;
BlueTable? _state;
public DataPacketReplayStream(string folder_path, string fire_period)
:
@@ -98,6 +92,7 @@ namespace bts {
break;
}
case StreamIOMessage.StreamOp.MULTIPLE_REMOVE_ADD: {
Log.notnull(_state);
var mra = msg.multiple_remove_add_message;
foreach (IBlueRow r in mra.removed_rows)
_state.deleteRow(r);
@@ -139,4 +134,4 @@ namespace bts {
});
}
}
}
}
@@ -1,7 +1,3 @@
using System;
namespace BCG {
// Keeps adding changing rows to the stream, hence preserving the history
// and creating a time series, for example this can be used to make bbo updates
@@ -9,7 +5,7 @@ namespace BCG {
public class DebugStream : ViewStream {
private ViewStream _stream;
private IBlueRowCollection _last_recv_rows = null;
IBlueRowCollection? _last_recv_rows;
public DebugStream(ViewStream stream) {
_stream = stream;
@@ -23,7 +19,7 @@ namespace BCG {
}
private void _onstream_change(object o) {
DataPacket dp = o as DataPacket;
var dp = (IDataPacket)o;
BlueDataUtility.validate_table_schema(dp.newRows);
BlueDataUtility.validate_table_schema(dp.addedRows);
if (_last_recv_rows == null) {
@@ -45,4 +41,4 @@ namespace BCG {
}
}
}
}
@@ -70,7 +70,7 @@ namespace bts
private readonly int _msg_size;
private readonly TimeSpan _publish_period;
private DateTime _last_publish_time = DateTime.MinValue;
private PublisherCore _pub_core = new PublisherCore();
private PublisherCore _pub_core = PublisherCore.Create();
private BlueTable _table;
private int _n_pubs = 0;
private readonly int _max_pubs;
@@ -224,4 +224,4 @@ namespace bts
}
}
}
}
@@ -1,14 +1,13 @@
using BCG;
using BCG.Utilities.General;
using System.Collections.Generic;
using Bts.PubSub;
using Bts.PubSub.Routing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using bts.api;
using Bts.PubSub.Routing;
namespace bts
{
@@ -17,9 +16,9 @@ namespace bts
{
public class PayloadMessage
{
public readonly string msg_id;
public readonly string? msg_id;
public readonly Int64 timestamp = 0;
public readonly byte[] payload = null;
public readonly byte[]? payload = null;
public static byte[] create_data(int payload_size, byte payload_byte)
{
@@ -53,10 +52,10 @@ namespace bts
{
var str = new MemoryStream();
BinaryWriter bw = new BinaryWriter(str);
bw.Write(msg_id);
bw.Write(msg_id ?? string.Empty);
bw.Write(timestamp);
bw.Write(payload.Length);
bw.Write(payload);
bw.Write(payload?.Length ?? 0);
bw.Write(payload ?? Array.Empty<byte>());
str.Position = 0;
var bytes = str.ToArray();
return bytes;
@@ -64,7 +63,9 @@ namespace bts
public static PayloadMessage deserialize(byte[] ser_bytes)
{
var str = new MemoryStream(ser_bytes);
var str = new MemoryStream(ser_bytes) {
Position = 0
};
BinaryReader br = new BinaryReader(str);
string guid = br.ReadString();
Int64 timestamp_ = br.ReadInt64();
@@ -73,18 +74,15 @@ namespace bts
return new PayloadMessage(guid, timestamp_, payload);
}
}
//public void
private readonly int _msg_size;
private readonly TimeSpan _publish_period;
private DateTime _last_publish_time = DateTime.MinValue;
private PublisherCore _pub_core;
private ISubscriberCore _sub_core;
PublisherCore? _pub_core;
ISubscriberCore? _sub_core;
private BlueTable _table;
private int _n_pubs = 0;
private readonly int _max_pubs;
private int _n_updates = 0;
private ViewStreamDatabase _vsd;
private PayloadMessage _last_sent_msg, _last_recvd_msg;
PayloadMessage? _last_sent_msg;
PayloadMessage? _last_recvd_msg;
private const byte _payload_byte = (byte)'A';
private readonly string _tag_name;
private readonly int _payload_sz;
@@ -96,11 +94,17 @@ namespace bts
};
IOState _state = IOState.SEND;
public PubsubEchoTestStream(string server_url, TimeSpan publish_period, int payload_size, string tag_name, ViewStreamDatabase vsd) {
_router = new PubSubRouter(new PubSubRouterConfig() {
PublisherRoutes = new() { new(server_url, ".*") },
SubscriberRoutes = new() { new(server_url, ".*") },
});
public PubsubEchoTestStream()
: this(new PubSubRouter(), TimeSpan.FromSeconds(1), 8, "ECHO_TEST", ViewStreamDatabase.instance) { }
public PubsubEchoTestStream(string server_url, TimeSpan publish_period, int payload_size, string tag_name)
: this(server_url, publish_period, payload_size, tag_name, ViewStreamDatabase.instance) { }
public PubsubEchoTestStream(string server_url, TimeSpan publish_period, int payload_size, string tag_name, ViewStreamDatabase vsd)
: this(createRouter(server_url), publish_period, payload_size, tag_name, vsd) { }
public PubsubEchoTestStream(IPubSubRouter router, TimeSpan publish_period, int payload_size, string tag_name, ViewStreamDatabase vsd) {
_router = router;
_vsd = vsd;
_payload_sz = payload_size;
var schema = BlueDataUtility.form_schema("PubSubTest",
@@ -121,7 +125,7 @@ namespace bts
protected override void myOnFirstSubscriber()
{
_pub_core = new PublisherCore(_router);
_pub_core = PublisherCore.Create(_router);
_sub_core = new SubscriberCore(_router);
_sub_core.subscribe(_tag_name);
_vsd.addWorker(this);
@@ -131,23 +135,30 @@ namespace bts
protected override void myOnLastSubscriber()
{
_vsd.removeWorker(this);
_sub_core.unsubscribe(_tag_name);
Log.notnull(_sub_core).unsubscribe(_tag_name);
}
static PubSubRouter createRouter(string serverUrl) =>
new(new PubSubRouterConfig() {
PublisherRoutes = new() { new(serverUrl, ".*") },
SubscriberRoutes = new() { new(serverUrl, ".*") },
});
private void _fire_dp_after_send()
{
Log.notnull(_last_sent_msg);
// as soon as the data is published, its reflected in the stream state
Log.assert(_last_sent_msg != null);
BlueRow r = new BlueRow(_table.schema, _table.Count, _last_sent_msg.msg_id, _last_sent_msg.timestamp, DBNull.Value, DBNull.Value,
DBNull.Value, DBNull.Value);
_table.addRow(r);
var dp_out = BlueDataUtility.build_dp_inc(_table, myLastValue as DataPacket);
var dp_out = BlueDataUtility.build_dp_inc(_table, (myLastValue as IDataPacket)?.newRows);
myFireEvent(dp_out);
}
private void _fire_dp_after_recv()
{
Log.assert(_last_recvd_msg != null);
Log.notnull(_last_recvd_msg);
Log.notnull(_last_sent_msg);
// update the last publish row
int id = _table.Count - 1;
IBlueRow last_row = _table[id];
@@ -156,8 +167,10 @@ namespace bts
BlueRow nr = new BlueRow(_table.schema, id, _last_sent_msg.msg_id, _last_sent_msg.timestamp, _last_recvd_msg.msg_id, recv_ts,
String.Compare(_last_recvd_msg.msg_id, _last_sent_msg.msg_id) == 0, recv_ts - _last_recvd_msg.timestamp);
_table.addRow(nr);
var dp_out = BlueDataUtility.build_dp_inc(_table, myLastValue as DataPacket);
myFireEvent(dp_out);
var dp_out = BlueDataUtility.build_dp_inc(_table, (myLastValue as IDataPacket)?.newRows);
if (dp_out.HasChanges()) {
myFireEvent(dp_out);
}
}
private string _get_next_id()
@@ -167,28 +180,16 @@ namespace bts
private void _publish_next_packet()
{
Log.notnull(_pub_core);
var bytes = PayloadMessage.create_data(_payload_sz, _payload_byte);
_last_sent_msg = new PayloadMessage(_get_next_id(), epoch_now(), bytes);
var ser_bytes = _last_sent_msg.serialize();
_n_pubs++;
_pub_core.publish("Blob", _tag_name, ser_bytes);
_last_publish_time = DateTime.Now;
}
public void doWork()
{
Func<IEnumerable<PubSubServerMessage>, PayloadMessage> find_packet = (updates) =>
{
foreach (var u in updates)
{
var recv_msg = PayloadMessage.deserialize(u.data);
if (recv_msg.msg_id == _last_sent_msg.msg_id)
{
return recv_msg;
}
}
return null;
};
switch (_state)
{
case IOState.SEND:
@@ -202,7 +203,7 @@ namespace bts
}
break;
case IOState.RECV:
var updates = _sub_core.get_updates(TimeSpan.Zero);
var updates = Log.notnull(_sub_core).get_updates(TimeSpan.Zero);
updates = updates.Where(u => u.tag == _tag_name);
var recv_msg = find_packet(updates);
if (recv_msg != null)
@@ -214,6 +215,19 @@ namespace bts
}
break;
}
PayloadMessage? find_packet(IEnumerable<PubSubServerMessage> updates) {
if (_last_sent_msg is null) {
return null;
}
foreach (var u in updates) {
var recv_msg = PayloadMessage.deserialize(Log.notnull(u.data));
if (recv_msg.msg_id == _last_sent_msg.msg_id) {
return recv_msg;
}
}
return null;
}
}
public static long epoch_now()
@@ -1,5 +1,7 @@
using bts;
using Spark.Core.Diagnostics;
using System;
using System.Collections.Generic;
using System.IO;
@@ -197,7 +199,6 @@ namespace BCG {
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();
@@ -375,7 +376,7 @@ namespace BCG {
StreamIOSerializationController ser_controller = new StreamIOSerializationController();
StreamIODeserializationController deser_controller = new StreamIODeserializationController();
IBlueTableSchema schema_p = null;
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";
@@ -619,7 +620,7 @@ namespace BCG {
private static TestResult _run_single_tag_data_test_clean() {
// var tagHandlerFactory
// create message
var test_name = MethodBase.GetCurrentMethod()?.Name;
var test_name = MethodBase.GetCurrentMethod()?.Name ?? string.Empty;
var schema = create_schema_with_all_types();
var tag = "DS_" + schema.tableName;
BlueTable table = new BlueTable(schema);
@@ -695,14 +696,14 @@ namespace BCG {
}
public static PublishMsg build_pub_msg(IBlueRow added_row, IBlueRow removed_row, bool is_create,
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;
return (added_row != null ? added_row : ExceptionAssert.NotNull(removed_row)).schema;
};
bts.StreamIOMessage str_io_msg = null;
StreamIOMessage? str_io_msg;
if (is_create) {
Log.assert(added_row != null);
ExceptionAssert.NotNull(added_row);
var aux_new = new BlueTable(added_row.schema);
aux_new.addRow(added_row);
var cr_msg = new bts.StreamIOMessage.CreateMessage(aux_new);
@@ -729,7 +730,7 @@ namespace BCG {
return pub_msg;
}
public static IBlueTableSchema create_schema_with_all_types(HashSet<Type> excluded_col_map = null) {
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();
@@ -800,7 +801,6 @@ namespace BCG {
return BitConverter.ToUInt64(ulongBuffer, 0);
default:
throw new ArgumentException($"Unsupported TypeCode: {type_code}");
return null;
}
}
#endregion
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BCG
{
@@ -16,7 +13,7 @@ namespace BCG
private string myInColumn;
private string myOutValue;
private object[] myMuxedValues;
private BlueTableSchema mySchema;
BlueTableSchema? mySchema;
public MuxStream(ViewStream inStream, string outColumn, string outValue, string inColumn, params object[] muxedValues)
{
@@ -49,7 +46,7 @@ namespace BCG
if (Array.IndexOf(myMuxedValues, r[myInColumn]) != -1) // muxable value?
r.setValue(myOutColumn, myOutValue);
else
r.setValue(myOutColumn, row[myInColumn].ToString());
r.setValue(myOutColumn, row[myInColumn]?.ToString());
return r;
}
@@ -1,11 +1,8 @@
using mbts;
using System;
using System.Collections;
using BCG;
using BCG.Utilities;
using System.Collections.Generic;
using mbts;
namespace BCG
{
public class NullToConstantMapper : IStreamMapper
@@ -27,17 +24,11 @@ namespace BCG
#region IDynamicStreamMapper Members
public IBlueRow map(IBlueRow row)
{
if(row[myField].Equals(DBNull.Value))
{
Hashtable newRow = new Hashtable(row);
newRow[myField]= myConstant;
return new BlueRow(row.schema, newRow);
}
else
return row;
}
public IBlueRow map(IBlueRow row) =>
row[myField] switch {
null or DBNull => new BlueRow(row.schema, new Hashtable(row) { { myField, myConstant } }),
_ => row,
};
#endregion
@@ -69,10 +60,11 @@ namespace BCG
Hashtable newRow = new Hashtable(row);
foreach(ColumnInfo info in row.schema.columnInfo)
{
if(row[info.colName].Equals(DBNull.Value))
{
change = true;
newRow[info.colName] = Convert.ChangeType(myConstant, info.colType);
switch (row[info.colName]) {
case null or DBNull:
change = true;
newRow[info.colName] = Convert.ChangeType(myConstant, info.colType);
break;
}
}
if(change)
@@ -19,15 +19,15 @@ namespace BCG
public IBlueTableSchema schema { get { return mySchema; } }
public object this[int index] { get { return myRow[index]; } }
public object? this[int index] { get { return myRow[index]; } }
public object this[string colName] { get { return myRow[colName]; } }
public object? this[string colName] { get { return myRow[colName]; } }
#endregion
#region IDictionary Members
public void Add(object key, object value)
public void Add(object key, object? value)
{
throw new Exception("The method or operation is not implemented.");
}
@@ -54,7 +54,7 @@ namespace BCG
public ICollection Values { get { return myRow.Values; } }
public object this[object key]
public object? this[object key]
{
get { return myRow[key]; }
set { throw new Exception("The method or operation is not implemented."); }
@@ -82,7 +82,7 @@ namespace BCG
}
private string myNewName;
private IBlueTableSchema mySchema;
IBlueTableSchema? mySchema;
public ChangeTableNameStream (ViewStream vs, string name)
{
@@ -1,9 +1,9 @@
using Bts.ColumnMapExpressions;
using Spark.Core.Diagnostics;
using System;
using System.Collections;
using System.Data;
using System.Text.RegularExpressions;
using BCG.Utilities;
using Bts.ColumnMapExpressions;
namespace BCG
{
@@ -56,7 +56,7 @@ namespace BCG
{
IDictionary retVal = new Hashtable ();
foreach (DictionaryEntry de in dic)
retVal[de.Value] = de.Key;
retVal[ExceptionAssert.NotNull(de.Value)] = de.Key;
return retVal;
}
@@ -1,13 +1,11 @@
using Bts.ColumnMapExpressions;
using Bts.DataStream;
using mbts.config;
using Spark.Core.Diagnostics;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
// using BCG.Evaluator.ColumnMapExpression;
namespace BCG
{
@@ -26,7 +24,7 @@ namespace BCG
/// <param name="isch">original(unprojected) schema</param>
/// <param name="exp">expression defining the mapping</param>
/// <param name="tableName">table name of the new schema</param>
internal ProjectHelper (IBlueTableSchema isch, string exp, string tableName)
internal ProjectHelper (IBlueTableSchema isch, string exp, string? tableName)
: this (isch, myGetDictionary (isch, exp), tableName)
{}
@@ -36,7 +34,7 @@ namespace BCG
/// <param name="origToAlias">dictionary mapping unprojected names to their projected names, dropped cols should not be there</param>
/// <param name="tableName">table name of the new schema</param>
internal ProjectHelper (
IBlueTableSchema isch, IDictionary<string, string> origToAlias, string tableName)
IBlueTableSchema isch, IDictionary<string, string> origToAlias, string? tableName)
{
ArrayList colMapAl = new ArrayList (),
colInfoAl = new ArrayList ();
@@ -61,7 +59,7 @@ namespace BCG
schema = new BlueTableSchema (tableName == null ? isch.tableName : tableName,
colInfoAl.ToArray (typeof(ColumnInfo)) as ColumnInfo[]);
colMap = colMapAl.ToArray (typeof(int)) as int[];
colMap = (int[])colMapAl.ToArray(typeof(int));
}
/// <summary>
@@ -74,8 +72,8 @@ namespace BCG
private static IDictionary<string, string> myGetDictionary (IBlueTableSchema isch, string exp)
{
IDictionary<string, string> origToAlias = new Dictionary<string, string>();
var e = ColumnMapExpression.Parse(exp);
var e = ColumnMapExpression.Parse(exp)
?? throw new ArgumentException("Failed to parse ColumnMapExpression", nameof(exp));
if (e.IsInclusive) {
origToAlias = e.Columns.ToDictionary();
origToAlias["id"] = "id";
@@ -95,7 +93,7 @@ namespace BCG
{
IDictionary retVal = new Hashtable (dic.Count);
foreach (DictionaryEntry de in dic)
retVal.Add (de.Value, de.Key);
retVal.Add(ExceptionAssert.NotNull(de.Value), de.Key);
return retVal;
}
}
@@ -1,6 +1,10 @@
namespace BCG {
using Spark.Core.Collections;
using Bts.DataStreamCore;
using Spark.Core.Collections;
using Spark.Core.Diagnostics;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
@@ -8,10 +12,13 @@ namespace BCG {
[DataStreamUserRespresentation("oldproject")]
public class ProjectStream : ViewStream
{
private ProjectHelper myHelper;
private string myColExp, myTableName;
private ViewStream myVs;
private IDictionary<string, string> myDic;
private ProjectHelper? myHelper;
readonly string? myColExp;
readonly string? myTableName;
readonly ViewStream? myVs;
private IDictionary<string, string>? myDic;
IDisposable? subscription;
/// <summary>
/// </summary>
/// <param name="vs">stream to susbsribe to as the input stream</param>
@@ -52,19 +59,18 @@ namespace BCG {
myDic = dic.ToDictionary(kv => kv.Value, kv => kv.Key);
}
protected override void myOnFirstSubscriber()
{
myVs.onChange += new BCG.DataStream.ChangeDelegate (myHandleChange);
}
protected override void myOnFirstSubscriber() =>
subscription = ExceptionAssert.MemberNotNull(myVs).Subscribe(myHandleChange);
protected override void myOnLastSubscriber()
{
myVs.onChange -= new BCG.DataStream.ChangeDelegate (myHandleChange);;
subscription?.Dispose();
subscription = null;
}
internal void myHandleChange (object newValue)
{
DataPacket dp = newValue as DataPacket;
var dp = (IDataPacket)newValue;
if (myHelper != null)
{
IBlueRowCollection dels, adds;
@@ -79,8 +85,8 @@ namespace BCG {
else
{ //first time a callback is received
myHelper = myDic == null ?
new ProjectHelper (dp.schema, myColExp, myTableName) :
new ProjectHelper (dp.schema, myDic, myTableName);
new ProjectHelper(dp.Schema, ExceptionAssert.MemberNotNull(myColExp), myTableName) :
new ProjectHelper (dp.Schema, myDic, myTableName);
IBlueRowCollection temp;
myFireEvent (new DataPacket (temp = new ProjectedTable (dp.newRows, myHelper),
@@ -1,6 +1,5 @@
using System;
using System.Collections;
using BCG.Utilities;
namespace BCG
{
@@ -22,9 +21,11 @@ namespace BCG
#region IBlueRow Members
public object this [string colName] {get {return this[myHelper.schema[colName].colNo];}}
public object? this [string colName] =>
this[myHelper.schema[colName].colNo];
public object this [int index] {get {return myRow[myHelper.colMap[index]];}}
public object? this [int index] =>
myRow[myHelper.colMap[index]];
public IBlueTableSchema schema {get {return myHelper.schema;}}
@@ -36,9 +37,13 @@ namespace BCG
public IDictionaryEnumerator GetEnumerator() {return new BlueRowDictionaryEnumerator (this);}
object System.Collections.IDictionary.this[object key]
object? IDictionary.this[object key]
{
get {return key is int ? this[(int)key] : this[key as string];}
get => key switch {
int i => this[i],
string s => this[s],
_ => throw new ArgumentException("Must be int or string", nameof(key)),
};
set {throw new ApplicationException ("Is read only");}
}
@@ -58,7 +63,8 @@ namespace BCG
}
}
public void Add (object key, object value) {throw new ApplicationException ("Is read only");}
public void Add(object key, object? value) =>
throw new NotSupportedException();
public ICollection Keys {get {return myHelper.schema.columnNames;}}
@@ -78,7 +84,7 @@ namespace BCG
array.SetValue (this[ci.colNo], index ++);
}
public object SyncRoot {get {return null;}}
public object SyncRoot => this;
#endregion
@@ -1,3 +1,5 @@
using Bts.DataStreamCore;
using System;
using System.Collections;
@@ -42,7 +44,7 @@ namespace BCG
public void CopyTo (Array array, int index)
{
foreach (IBlueRow r in myRows)
array.SetValue (this[(int)r["id"]], index++);
array.SetValue(this[r.Id()], index++);
}
@@ -72,14 +74,10 @@ namespace BCG
public void Reset() {myMaster.Reset();}
public object Current
{
get
{
return myMaster.Current == null ? null :
new ProjectedRow (myMaster.Current as IBlueRow, myHelper);
}
}
public object? Current =>
myMaster.Current is null
? null
: new ProjectedRow((IBlueRow)myMaster.Current, myHelper);
public bool MoveNext() {return myMaster.MoveNext ();}
@@ -1,25 +1,16 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Diagnostics;
using System.Collections;
using System.IO;
using System.Text;
using BCG;
using System.Linq;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.SQLite;
using System.Runtime.InteropServices;
namespace bts.BlueOrb{
public static class SQLiteHelper {
public static string location = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "C:\\BlueOrb_Data\\" : Path.Combine(Environment.GetEnvironmentVariable("HOME"), "BlueOrb_Data");
public static string location = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
? "C:\\BlueOrb_Data\\"
: Path.Combine(Environment.GetEnvironmentVariable("HOME") ?? string.Empty, "BlueOrb_Data");
public static string db_name = "stream_data.db";
public static DataTable execute_select_query(string connection_string, string query) {
Loaded 100 of 786 files, more files were not shown because too many files have changed in this diff. Show more