diff --git a/Source/Libraries/GSF.SortedTreeStore/Properties/AssemblyInfo.cs b/Source/Libraries/GSF.SortedTreeStore/Properties/AssemblyInfo.cs
index 3d440f5cf5..93791201d8 100755
--- a/Source/Libraries/GSF.SortedTreeStore/Properties/AssemblyInfo.cs
+++ b/Source/Libraries/GSF.SortedTreeStore/Properties/AssemblyInfo.cs
@@ -44,4 +44,5 @@
[assembly: InternalsVisibleTo("GSF.SortedTreeStore.Test")]
[assembly: InternalsVisibleTo("openHistorian.Adapters")]
[assembly: InternalsVisibleTo("openHistorian.PerformanceTests")]
-[assembly: InternalsVisibleTo("ArchiveIntegrityChecker")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("ArchiveIntegrityChecker")]
+[assembly: InternalsVisibleTo("OHTransfer")]
\ No newline at end of file
diff --git a/Source/Libraries/GSF.SortedTreeStore/Snap/Services/Reader/SequentialReaderStream'2.cs b/Source/Libraries/GSF.SortedTreeStore/Snap/Services/Reader/SequentialReaderStream'2.cs
index d63c7ae4ea..fdbe5ffb08 100755
--- a/Source/Libraries/GSF.SortedTreeStore/Snap/Services/Reader/SequentialReaderStream'2.cs
+++ b/Source/Libraries/GSF.SortedTreeStore/Snap/Services/Reader/SequentialReaderStream'2.cs
@@ -202,9 +202,20 @@ private bool ReadCatchAll(TKey key, TValue value)
m_pointCount = 0;
}
- TryAgain:
+ long retries = 0;
+
+ TryAgain:
if (!m_timedOut)
{
+ retries++;
+
+ if (retries >= 10000)
+ {
+ m_workerThreadSynchronization.PulseSafeToCallback();
+ Interlocked.Add(ref Stats.PointsScanned, retries);
+ retries = 0;
+ }
+
if (m_keyMatchIsUniverse)
{
if (m_firstTableScanner is null)
diff --git a/Source/Tools/OHTransfer/App.config b/Source/Tools/OHTransfer/App.config
new file mode 100644
index 0000000000..193aecc675
--- /dev/null
+++ b/Source/Tools/OHTransfer/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Tools/OHTransfer/OHTransfer.Designer.cs b/Source/Tools/OHTransfer/OHTransfer.Designer.cs
new file mode 100644
index 0000000000..f0cccb4dfc
--- /dev/null
+++ b/Source/Tools/OHTransfer/OHTransfer.Designer.cs
@@ -0,0 +1,417 @@
+namespace OHTransfer
+{
+ partial class OHTransfer
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(OHTransfer));
+ this.groupBoxMessages = new System.Windows.Forms.GroupBox();
+ this.textBoxMessageOutput = new System.Windows.Forms.TextBox();
+ this.groupBoxTransferConfiguration = new System.Windows.Forms.GroupBox();
+ this.textBoxSourceFiles = new System.Windows.Forms.TextBox();
+ this.labelSourceFilesLocation = new System.Windows.Forms.Label();
+ this.buttonOpenSourceFilesLocation = new System.Windows.Forms.Button();
+ this.labelToUTC = new System.Windows.Forms.Label();
+ this.labelFromUTC = new System.Windows.Forms.Label();
+ this.labelToDate = new System.Windows.Forms.Label();
+ this.dateTimePickerTo = new System.Windows.Forms.DateTimePicker();
+ this.labelFromDate = new System.Windows.Forms.Label();
+ this.dateTimePickerFrom = new System.Windows.Forms.DateTimePicker();
+ this.textBoxDestinationCSVMeasurements = new System.Windows.Forms.TextBox();
+ this.labelDestinationCSVMeasurements = new System.Windows.Forms.Label();
+ this.buttonOpenDestinationCSVMeasurementsFile = new System.Windows.Forms.Button();
+ this.textBoxSourceCSVMeasurements = new System.Windows.Forms.TextBox();
+ this.labelSourceCSVMeasurements = new System.Windows.Forms.Label();
+ this.buttonOpenSourceCSVMeasurementsFile = new System.Windows.Forms.Button();
+ this.textBoxDestinationFiles = new System.Windows.Forms.TextBox();
+ this.labelDestinationFilesLocation = new System.Windows.Forms.Label();
+ this.buttonOpenDestinationFilesLocation = new System.Windows.Forms.Button();
+ this.folderBrowserDialog = new System.Windows.Forms.FolderBrowserDialog();
+ this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+ this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
+ this.progressBar = new System.Windows.Forms.ProgressBar();
+ this.buttonGo = new System.Windows.Forms.Button();
+ this.buttonCancel = new System.Windows.Forms.Button();
+ this.groupBoxMessages.SuspendLayout();
+ this.groupBoxTransferConfiguration.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // groupBoxMessages
+ //
+ this.groupBoxMessages.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.groupBoxMessages.Controls.Add(this.textBoxMessageOutput);
+ this.groupBoxMessages.Location = new System.Drawing.Point(15, 196);
+ this.groupBoxMessages.Name = "groupBoxMessages";
+ this.groupBoxMessages.Size = new System.Drawing.Size(777, 304);
+ this.groupBoxMessages.TabIndex = 3;
+ this.groupBoxMessages.TabStop = false;
+ this.groupBoxMessages.Text = "Messages";
+ //
+ // textBoxMessageOutput
+ //
+ this.textBoxMessageOutput.BackColor = System.Drawing.SystemColors.WindowText;
+ this.textBoxMessageOutput.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.textBoxMessageOutput.Font = new System.Drawing.Font("Lucida Console", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.textBoxMessageOutput.ForeColor = System.Drawing.SystemColors.Window;
+ this.textBoxMessageOutput.Location = new System.Drawing.Point(3, 16);
+ this.textBoxMessageOutput.Multiline = true;
+ this.textBoxMessageOutput.Name = "textBoxMessageOutput";
+ this.textBoxMessageOutput.ReadOnly = true;
+ this.textBoxMessageOutput.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.textBoxMessageOutput.Size = new System.Drawing.Size(771, 285);
+ this.textBoxMessageOutput.TabIndex = 0;
+ this.textBoxMessageOutput.TabStop = false;
+ //
+ // groupBoxTransferConfiguration
+ //
+ this.groupBoxTransferConfiguration.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.groupBoxTransferConfiguration.Controls.Add(this.textBoxSourceFiles);
+ this.groupBoxTransferConfiguration.Controls.Add(this.labelSourceFilesLocation);
+ this.groupBoxTransferConfiguration.Controls.Add(this.buttonOpenSourceFilesLocation);
+ this.groupBoxTransferConfiguration.Controls.Add(this.labelToUTC);
+ this.groupBoxTransferConfiguration.Controls.Add(this.labelFromUTC);
+ this.groupBoxTransferConfiguration.Controls.Add(this.labelToDate);
+ this.groupBoxTransferConfiguration.Controls.Add(this.dateTimePickerTo);
+ this.groupBoxTransferConfiguration.Controls.Add(this.labelFromDate);
+ this.groupBoxTransferConfiguration.Controls.Add(this.dateTimePickerFrom);
+ this.groupBoxTransferConfiguration.Controls.Add(this.textBoxDestinationCSVMeasurements);
+ this.groupBoxTransferConfiguration.Controls.Add(this.labelDestinationCSVMeasurements);
+ this.groupBoxTransferConfiguration.Controls.Add(this.buttonOpenDestinationCSVMeasurementsFile);
+ this.groupBoxTransferConfiguration.Controls.Add(this.textBoxSourceCSVMeasurements);
+ this.groupBoxTransferConfiguration.Controls.Add(this.labelSourceCSVMeasurements);
+ this.groupBoxTransferConfiguration.Controls.Add(this.buttonOpenSourceCSVMeasurementsFile);
+ this.groupBoxTransferConfiguration.Controls.Add(this.textBoxDestinationFiles);
+ this.groupBoxTransferConfiguration.Controls.Add(this.labelDestinationFilesLocation);
+ this.groupBoxTransferConfiguration.Controls.Add(this.buttonOpenDestinationFilesLocation);
+ this.groupBoxTransferConfiguration.Location = new System.Drawing.Point(18, 12);
+ this.groupBoxTransferConfiguration.Name = "groupBoxTransferConfiguration";
+ this.groupBoxTransferConfiguration.Size = new System.Drawing.Size(775, 178);
+ this.groupBoxTransferConfiguration.TabIndex = 1;
+ this.groupBoxTransferConfiguration.TabStop = false;
+ this.groupBoxTransferConfiguration.Text = "Transfer Configuration";
+ //
+ // textBoxSourceFiles
+ //
+ this.textBoxSourceFiles.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.textBoxSourceFiles.Location = new System.Drawing.Point(178, 25);
+ this.textBoxSourceFiles.Name = "textBoxSourceFiles";
+ this.textBoxSourceFiles.Size = new System.Drawing.Size(547, 20);
+ this.textBoxSourceFiles.TabIndex = 1;
+ //
+ // labelSourceFilesLocation
+ //
+ this.labelSourceFilesLocation.AutoSize = true;
+ this.labelSourceFilesLocation.Location = new System.Drawing.Point(73, 28);
+ this.labelSourceFilesLocation.Name = "labelSourceFilesLocation";
+ this.labelSourceFilesLocation.Size = new System.Drawing.Size(105, 13);
+ this.labelSourceFilesLocation.TabIndex = 0;
+ this.labelSourceFilesLocation.Text = "&Source files location:";
+ this.labelSourceFilesLocation.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // buttonOpenSourceFilesLocation
+ //
+ this.buttonOpenSourceFilesLocation.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonOpenSourceFilesLocation.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.buttonOpenSourceFilesLocation.Location = new System.Drawing.Point(726, 22);
+ this.buttonOpenSourceFilesLocation.Name = "buttonOpenSourceFilesLocation";
+ this.buttonOpenSourceFilesLocation.Size = new System.Drawing.Size(28, 23);
+ this.buttonOpenSourceFilesLocation.TabIndex = 2;
+ this.buttonOpenSourceFilesLocation.Text = "...";
+ this.buttonOpenSourceFilesLocation.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ this.buttonOpenSourceFilesLocation.UseVisualStyleBackColor = true;
+ this.buttonOpenSourceFilesLocation.Click += new System.EventHandler(this.buttonOpenSourceFilesLocation_Click);
+ //
+ // labelToUTC
+ //
+ this.labelToUTC.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.labelToUTC.AutoSize = true;
+ this.labelToUTC.Location = new System.Drawing.Point(727, 144);
+ this.labelToUTC.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
+ this.labelToUTC.Name = "labelToUTC";
+ this.labelToUTC.Size = new System.Drawing.Size(29, 13);
+ this.labelToUTC.TabIndex = 17;
+ this.labelToUTC.Text = "UTC";
+ this.labelToUTC.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelFromUTC
+ //
+ this.labelFromUTC.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.labelFromUTC.AutoSize = true;
+ this.labelFromUTC.Location = new System.Drawing.Point(517, 144);
+ this.labelFromUTC.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
+ this.labelFromUTC.Name = "labelFromUTC";
+ this.labelFromUTC.Size = new System.Drawing.Size(29, 13);
+ this.labelFromUTC.TabIndex = 16;
+ this.labelFromUTC.Text = "UTC";
+ this.labelFromUTC.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelToDate
+ //
+ this.labelToDate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.labelToDate.AutoSize = true;
+ this.labelToDate.Location = new System.Drawing.Point(559, 144);
+ this.labelToDate.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
+ this.labelToDate.Name = "labelToDate";
+ this.labelToDate.Size = new System.Drawing.Size(23, 13);
+ this.labelToDate.TabIndex = 14;
+ this.labelToDate.Text = "&To:";
+ this.labelToDate.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // dateTimePickerTo
+ //
+ this.dateTimePickerTo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.dateTimePickerTo.CustomFormat = "yyyy-MM-dd HH:mm:ss";
+ this.dateTimePickerTo.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+ this.dateTimePickerTo.Location = new System.Drawing.Point(584, 141);
+ this.dateTimePickerTo.Name = "dateTimePickerTo";
+ this.dateTimePickerTo.Size = new System.Drawing.Size(142, 20);
+ this.dateTimePickerTo.TabIndex = 15;
+ //
+ // labelFromDate
+ //
+ this.labelFromDate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.labelFromDate.AutoSize = true;
+ this.labelFromDate.Location = new System.Drawing.Point(339, 144);
+ this.labelFromDate.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
+ this.labelFromDate.Name = "labelFromDate";
+ this.labelFromDate.Size = new System.Drawing.Size(33, 13);
+ this.labelFromDate.TabIndex = 12;
+ this.labelFromDate.Text = "&From:";
+ this.labelFromDate.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // dateTimePickerFrom
+ //
+ this.dateTimePickerFrom.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.dateTimePickerFrom.CustomFormat = "yyyy-MM-dd HH:mm:ss";
+ this.dateTimePickerFrom.Format = System.Windows.Forms.DateTimePickerFormat.Custom;
+ this.dateTimePickerFrom.Location = new System.Drawing.Point(375, 141);
+ this.dateTimePickerFrom.Name = "dateTimePickerFrom";
+ this.dateTimePickerFrom.Size = new System.Drawing.Size(142, 20);
+ this.dateTimePickerFrom.TabIndex = 13;
+ //
+ // textBoxDestinationCSVMeasurements
+ //
+ this.textBoxDestinationCSVMeasurements.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.textBoxDestinationCSVMeasurements.Location = new System.Drawing.Point(179, 109);
+ this.textBoxDestinationCSVMeasurements.Name = "textBoxDestinationCSVMeasurements";
+ this.textBoxDestinationCSVMeasurements.Size = new System.Drawing.Size(547, 20);
+ this.textBoxDestinationCSVMeasurements.TabIndex = 10;
+ //
+ // labelDestinationCSVMeasurements
+ //
+ this.labelDestinationCSVMeasurements.AutoSize = true;
+ this.labelDestinationCSVMeasurements.Location = new System.Drawing.Point(19, 112);
+ this.labelDestinationCSVMeasurements.Name = "labelDestinationCSVMeasurements";
+ this.labelDestinationCSVMeasurements.Size = new System.Drawing.Size(159, 13);
+ this.labelDestinationCSVMeasurements.TabIndex = 9;
+ this.labelDestinationCSVMeasurements.Text = "&Destination CSV Measurements:";
+ this.labelDestinationCSVMeasurements.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // buttonOpenDestinationCSVMeasurementsFile
+ //
+ this.buttonOpenDestinationCSVMeasurementsFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonOpenDestinationCSVMeasurementsFile.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.buttonOpenDestinationCSVMeasurementsFile.Location = new System.Drawing.Point(726, 108);
+ this.buttonOpenDestinationCSVMeasurementsFile.Name = "buttonOpenDestinationCSVMeasurementsFile";
+ this.buttonOpenDestinationCSVMeasurementsFile.Size = new System.Drawing.Size(28, 23);
+ this.buttonOpenDestinationCSVMeasurementsFile.TabIndex = 11;
+ this.buttonOpenDestinationCSVMeasurementsFile.Text = "...";
+ this.buttonOpenDestinationCSVMeasurementsFile.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ this.buttonOpenDestinationCSVMeasurementsFile.UseVisualStyleBackColor = true;
+ this.buttonOpenDestinationCSVMeasurementsFile.Click += new System.EventHandler(this.buttonOpenDestinationCSVMeasurementsFile_Click);
+ //
+ // textBoxSourceCSVMeasurements
+ //
+ this.textBoxSourceCSVMeasurements.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.textBoxSourceCSVMeasurements.Location = new System.Drawing.Point(179, 80);
+ this.textBoxSourceCSVMeasurements.Name = "textBoxSourceCSVMeasurements";
+ this.textBoxSourceCSVMeasurements.Size = new System.Drawing.Size(547, 20);
+ this.textBoxSourceCSVMeasurements.TabIndex = 7;
+ //
+ // labelSourceCSVMeasurements
+ //
+ this.labelSourceCSVMeasurements.AutoSize = true;
+ this.labelSourceCSVMeasurements.Location = new System.Drawing.Point(38, 83);
+ this.labelSourceCSVMeasurements.Name = "labelSourceCSVMeasurements";
+ this.labelSourceCSVMeasurements.Size = new System.Drawing.Size(140, 13);
+ this.labelSourceCSVMeasurements.TabIndex = 6;
+ this.labelSourceCSVMeasurements.Text = "&Source CSV Measurements:";
+ this.labelSourceCSVMeasurements.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // buttonOpenSourceCSVMeasurementsFile
+ //
+ this.buttonOpenSourceCSVMeasurementsFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonOpenSourceCSVMeasurementsFile.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.buttonOpenSourceCSVMeasurementsFile.Location = new System.Drawing.Point(726, 79);
+ this.buttonOpenSourceCSVMeasurementsFile.Name = "buttonOpenSourceCSVMeasurementsFile";
+ this.buttonOpenSourceCSVMeasurementsFile.Size = new System.Drawing.Size(28, 23);
+ this.buttonOpenSourceCSVMeasurementsFile.TabIndex = 8;
+ this.buttonOpenSourceCSVMeasurementsFile.Text = "...";
+ this.buttonOpenSourceCSVMeasurementsFile.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ this.buttonOpenSourceCSVMeasurementsFile.UseVisualStyleBackColor = true;
+ this.buttonOpenSourceCSVMeasurementsFile.Click += new System.EventHandler(this.buttonOpenSourceCSVMeasurementsFile_Click);
+ //
+ // textBoxDestinationFiles
+ //
+ this.textBoxDestinationFiles.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.textBoxDestinationFiles.Location = new System.Drawing.Point(178, 53);
+ this.textBoxDestinationFiles.Name = "textBoxDestinationFiles";
+ this.textBoxDestinationFiles.Size = new System.Drawing.Size(547, 20);
+ this.textBoxDestinationFiles.TabIndex = 4;
+ //
+ // labelDestinationFilesLocation
+ //
+ this.labelDestinationFilesLocation.AutoSize = true;
+ this.labelDestinationFilesLocation.Location = new System.Drawing.Point(54, 56);
+ this.labelDestinationFilesLocation.Name = "labelDestinationFilesLocation";
+ this.labelDestinationFilesLocation.Size = new System.Drawing.Size(124, 13);
+ this.labelDestinationFilesLocation.TabIndex = 3;
+ this.labelDestinationFilesLocation.Text = "&Destination files location:";
+ this.labelDestinationFilesLocation.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // buttonOpenDestinationFilesLocation
+ //
+ this.buttonOpenDestinationFilesLocation.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonOpenDestinationFilesLocation.Font = new System.Drawing.Font("Arial", 10F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.buttonOpenDestinationFilesLocation.Location = new System.Drawing.Point(726, 50);
+ this.buttonOpenDestinationFilesLocation.Name = "buttonOpenDestinationFilesLocation";
+ this.buttonOpenDestinationFilesLocation.Size = new System.Drawing.Size(28, 23);
+ this.buttonOpenDestinationFilesLocation.TabIndex = 5;
+ this.buttonOpenDestinationFilesLocation.Text = "...";
+ this.buttonOpenDestinationFilesLocation.TextAlign = System.Drawing.ContentAlignment.TopCenter;
+ this.buttonOpenDestinationFilesLocation.UseVisualStyleBackColor = true;
+ this.buttonOpenDestinationFilesLocation.Click += new System.EventHandler(this.buttonOpenDestinationFilesLocation_Click);
+ //
+ // toolTip
+ //
+ this.toolTip.AutomaticDelay = 200;
+ this.toolTip.AutoPopDelay = 20000;
+ this.toolTip.InitialDelay = 200;
+ this.toolTip.ReshowDelay = 40;
+ //
+ // openFileDialog
+ //
+ this.openFileDialog.DefaultExt = "csv";
+ this.openFileDialog.Filter = "\"CSV files|*.csv|All files|*.*";
+ //
+ // progressBar
+ //
+ this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.progressBar.Location = new System.Drawing.Point(15, 506);
+ this.progressBar.Name = "progressBar";
+ this.progressBar.Size = new System.Drawing.Size(697, 23);
+ this.progressBar.TabIndex = 4;
+ //
+ // buttonGo
+ //
+ this.buttonGo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonGo.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.buttonGo.Location = new System.Drawing.Point(718, 506);
+ this.buttonGo.Name = "buttonGo";
+ this.buttonGo.Size = new System.Drawing.Size(75, 23);
+ this.buttonGo.TabIndex = 2;
+ this.buttonGo.Text = "&Go!";
+ this.buttonGo.UseVisualStyleBackColor = true;
+ this.buttonGo.Click += new System.EventHandler(this.buttonGo_Click);
+ //
+ // buttonCancel
+ //
+ this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.buttonCancel.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.buttonCancel.Location = new System.Drawing.Point(718, 506);
+ this.buttonCancel.Name = "buttonCancel";
+ this.buttonCancel.Size = new System.Drawing.Size(75, 23);
+ this.buttonCancel.TabIndex = 5;
+ this.buttonCancel.Text = "&Cancel";
+ this.buttonCancel.UseVisualStyleBackColor = true;
+ this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
+ //
+ // OHTransfer
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(804, 541);
+ this.Controls.Add(this.progressBar);
+ this.Controls.Add(this.buttonGo);
+ this.Controls.Add(this.groupBoxTransferConfiguration);
+ this.Controls.Add(this.groupBoxMessages);
+ this.Controls.Add(this.buttonCancel);
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+ this.MinimumSize = new System.Drawing.Size(720, 480);
+ this.Name = "OHTransfer";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "openHistorian Data Transfer";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.OHTransfer_FormClosing);
+ this.Load += new System.EventHandler(this.OHTransfer_Load);
+ this.groupBoxMessages.ResumeLayout(false);
+ this.groupBoxMessages.PerformLayout();
+ this.groupBoxTransferConfiguration.ResumeLayout(false);
+ this.groupBoxTransferConfiguration.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ private System.Windows.Forms.GroupBox groupBoxMessages;
+ private System.Windows.Forms.TextBox textBoxMessageOutput;
+ private System.Windows.Forms.GroupBox groupBoxTransferConfiguration;
+ private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog;
+ private System.Windows.Forms.ToolTip toolTip;
+ private System.Windows.Forms.TextBox textBoxDestinationCSVMeasurements;
+ private System.Windows.Forms.Label labelDestinationCSVMeasurements;
+ private System.Windows.Forms.Button buttonOpenDestinationCSVMeasurementsFile;
+ private System.Windows.Forms.TextBox textBoxSourceCSVMeasurements;
+ private System.Windows.Forms.Label labelSourceCSVMeasurements;
+ private System.Windows.Forms.OpenFileDialog openFileDialog;
+ private System.Windows.Forms.ProgressBar progressBar;
+ private System.Windows.Forms.Button buttonGo;
+ private System.Windows.Forms.Button buttonOpenSourceCSVMeasurementsFile;
+ private System.Windows.Forms.TextBox textBoxDestinationFiles;
+ private System.Windows.Forms.Label labelDestinationFilesLocation;
+ private System.Windows.Forms.Button buttonOpenDestinationFilesLocation;
+ private System.Windows.Forms.DateTimePicker dateTimePickerFrom;
+ private System.Windows.Forms.Label labelToDate;
+ private System.Windows.Forms.DateTimePicker dateTimePickerTo;
+ private System.Windows.Forms.Label labelFromDate;
+ private System.Windows.Forms.Button buttonCancel;
+ private System.Windows.Forms.Label labelToUTC;
+ private System.Windows.Forms.Label labelFromUTC;
+ private System.Windows.Forms.TextBox textBoxSourceFiles;
+ private System.Windows.Forms.Label labelSourceFilesLocation;
+ private System.Windows.Forms.Button buttonOpenSourceFilesLocation;
+ }
+}
+
diff --git a/Source/Tools/OHTransfer/OHTransfer.cs b/Source/Tools/OHTransfer/OHTransfer.cs
new file mode 100644
index 0000000000..2b98f3bb9e
--- /dev/null
+++ b/Source/Tools/OHTransfer/OHTransfer.cs
@@ -0,0 +1,690 @@
+//******************************************************************************************************
+// OHTransfer.cs - Gbtc
+//
+// Copyright © 2025, Grid Protection Alliance. All Rights Reserved.
+//
+// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
+// the NOTICE file distributed with this work for additional information regarding copyright ownership.
+// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this
+// file except in compliance with the License. You may obtain a copy of the License at:
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless agreed to in writing, the subject software distributed under the License is distributed on an
+// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
+// License for the specific language governing permissions and limitations.
+//
+// Code Modification History:
+// ----------------------------------------------------------------------------------------------------
+// 08/12/2025 - J. Ritchie Carroll
+// Generated original version of source code.
+//
+//******************************************************************************************************
+// ReSharper disable AccessToModifiedClosure
+// ReSharper disable AccessToDisposedClosure
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+using GSF;
+using GSF.Configuration;
+using GSF.IO;
+using GSF.Snap;
+using GSF.Snap.Filters;
+using GSF.Snap.Services;
+using GSF.Snap.Services.Reader;
+using GSF.Snap.Storage;
+using GSF.Threading;
+using GSF.Units;
+using GSF.Units.EE;
+using GSF.Windows.Forms;
+using openHistorian.Net;
+using openHistorian.Snap;
+using openHistorian.Snap.Definitions;
+using CancellationToken = System.Threading.CancellationToken;
+
+namespace OHTransfer
+{
+ public partial class OHTransfer : Form
+ {
+ private CancellationTokenSource m_cancellationTokenSource;
+ private bool m_formClosing;
+
+ private const int MonitoringInterval = 2000; // 2 seconds
+ private const int FeedbackInterval = 4000; // 4 seconds
+
+ public OHTransfer()
+ {
+ InitializeComponent();
+
+ DateTime nowFromTopOfHour = DateTime.UtcNow.BaselinedTimestamp(BaselineTimeInterval.Hour);
+ dateTimePickerFrom.Value = nowFromTopOfHour.AddDays(-30);
+ dateTimePickerTo.Value = nowFromTopOfHour;
+ }
+
+ private void OHTransfer_Load(object sender, EventArgs e)
+ {
+ CategorizedSettingsElementCollection settings = ConfigurationFile.Current.Settings["systemSettings"];
+
+ settings.Add("sourceFiles", textBoxSourceFiles.Text, "openHistorian 2.0 source files location", false, SettingScope.User);
+ settings.Add("destinationFiles", textBoxDestinationFiles.Text, "openHistorian 2.0 destination files location", false, SettingScope.User);
+ settings.Add("sourceCSVMeasurements", textBoxSourceCSVMeasurements.Text, "openHistorian 2.0 source CSV measurements export file", false, SettingScope.User);
+ settings.Add("destinationCSVMeasurements", textBoxDestinationCSVMeasurements.Text, "openHistorian 2.0 destination CSV measurements export file", false, SettingScope.User);
+ settings.Add("fromDate", dateTimePickerFrom.Value.ToString(dateTimePickerFrom.CustomFormat), "Start date for transfer", false, SettingScope.User);
+ settings.Add("toDate", dateTimePickerTo.Value.ToString(dateTimePickerTo.CustomFormat), "End date for transfer", false, SettingScope.User);
+
+ textBoxSourceFiles.Text = settings["sourceFiles"].Value;
+ textBoxDestinationFiles.Text = settings["destinationFiles"].Value;
+ textBoxSourceCSVMeasurements.Text = settings["sourceCSVMeasurements"].Value;
+ textBoxDestinationCSVMeasurements.Text = settings["destinationCSVMeasurements"].Value;
+ dateTimePickerFrom.Value = DateTime.ParseExact(settings["fromDate"].Value, dateTimePickerFrom.CustomFormat, null, DateTimeStyles.AssumeUniversal);
+ dateTimePickerTo.Value = DateTime.ParseExact(settings["toDate"].Value, dateTimePickerTo.CustomFormat, null, DateTimeStyles.AssumeUniversal);
+
+ this.RestoreLocation();
+ }
+
+ private void OHTransfer_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ CategorizedSettingsElementCollection settings = ConfigurationFile.Current.Settings["systemSettings"];
+
+ m_formClosing = true;
+
+ this.SaveLocation();
+
+ settings["sourceFiles"].Value = textBoxSourceFiles.Text;
+ settings["destinationFiles"].Value = textBoxDestinationFiles.Text;
+ settings["sourceCSVMeasurements"].Value = textBoxSourceCSVMeasurements.Text;
+ settings["destinationCSVMeasurements"].Value = textBoxDestinationCSVMeasurements.Text;
+ settings["fromDate"].Value = dateTimePickerFrom.Value.ToString(dateTimePickerFrom.CustomFormat);
+ settings["toDate"].Value = dateTimePickerTo.Value.ToString(dateTimePickerTo.CustomFormat);
+
+ ConfigurationFile.Current.Save();
+
+ if (m_cancellationTokenSource is null)
+ return;
+
+ Hide();
+ m_cancellationTokenSource?.Cancel();
+ Thread.Sleep((int)(MonitoringInterval * 1.5D));
+ }
+
+ private void buttonOpenSourceFilesLocation_Click(object sender, EventArgs e)
+ {
+ folderBrowserDialog.Description = "Find source location for existing openHistorian 2.0 archive files";
+
+ if (Directory.Exists(textBoxSourceFiles.Text))
+ folderBrowserDialog.SelectedPath = textBoxSourceFiles.Text;
+
+ if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK)
+ textBoxSourceFiles.Text = folderBrowserDialog.SelectedPath;
+
+ if (!textBoxSourceFiles.Text.EndsWith(Path.DirectorySeparatorChar.ToString()))
+ textBoxSourceFiles.Text += Path.DirectorySeparatorChar;
+ }
+
+ private void buttonOpenDestinationFilesLocation_Click(object sender, EventArgs e)
+ {
+ folderBrowserDialog.Description = "Find destination location for new openHistorian 2.0 archive files";
+
+ if (Directory.Exists(textBoxDestinationFiles.Text))
+ folderBrowserDialog.SelectedPath = textBoxDestinationFiles.Text;
+
+ if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK)
+ textBoxDestinationFiles.Text = folderBrowserDialog.SelectedPath;
+
+ if (!textBoxDestinationFiles.Text.EndsWith(Path.DirectorySeparatorChar.ToString()))
+ textBoxDestinationFiles.Text += Path.DirectorySeparatorChar;
+
+ if (!Directory.Exists(textBoxDestinationFiles.Text))
+ Directory.CreateDirectory(textBoxDestinationFiles.Text);
+ }
+
+ private void buttonOpenSourceCSVMeasurementsFile_Click(object sender, EventArgs e)
+ {
+ openFileDialog.Title = "Find source openHistorian 2.0 CSV measurements export file";
+ openFileDialog.FileName = File.Exists(textBoxSourceCSVMeasurements.Text) ? textBoxSourceCSVMeasurements.Text : string.Empty;
+
+ if (openFileDialog.ShowDialog(this) == DialogResult.OK)
+ textBoxSourceCSVMeasurements.Text = openFileDialog.FileName;
+ }
+
+ private void buttonOpenDestinationCSVMeasurementsFile_Click(object sender, EventArgs e)
+ {
+ openFileDialog.Title = "Find destination openHistorian 2.0 CSV measurements export file";
+ openFileDialog.FileName = File.Exists(textBoxDestinationCSVMeasurements.Text) ? textBoxDestinationCSVMeasurements.Text : string.Empty;
+
+ if (openFileDialog.ShowDialog(this) == DialogResult.OK)
+ textBoxDestinationCSVMeasurements.Text = openFileDialog.FileName;
+ }
+
+ private void buttonGo_Click(object sender, EventArgs e)
+ {
+ ClearUpdateMessages();
+ UpdateProgressBar(0);
+
+ if (string.IsNullOrWhiteSpace(textBoxSourceFiles.Text))
+ {
+ MessageBox.Show("Please select a source location for existing openHistorian 2.0 archive files.", "Missing Source Location", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(textBoxDestinationFiles.Text))
+ {
+ MessageBox.Show("Please select a destination location for new openHistorian 2.0 archive files.", "Missing Destination Location", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(textBoxSourceCSVMeasurements.Text))
+ {
+ MessageBox.Show("Please select a source openHistorian 2.0 CSV measurements export file.", "Missing Source File", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ if (string.IsNullOrWhiteSpace(textBoxDestinationCSVMeasurements.Text))
+ {
+ MessageBox.Show("Please select a destination openHistorian 2.0 CSV measurements export file.", "Missing Destination File", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ if (!Directory.Exists(textBoxDestinationFiles.Text))
+ {
+ MessageBox.Show("The specified destination location does not exist.", "Invalid Destination Location", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ if (!File.Exists(textBoxSourceCSVMeasurements.Text))
+ {
+ MessageBox.Show("The specified source openHistorian 2.0 CSV measurements export file does not exist.", "Invalid Source File", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ if (!File.Exists(textBoxDestinationCSVMeasurements.Text))
+ {
+ MessageBox.Show("The specified destination openHistorian 2.0 CSV measurements export file does not exist.", "Invalid Destination File", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ DateTime startTime = dateTimePickerFrom.Value;
+ DateTime endTime = dateTimePickerTo.Value;
+
+ if (endTime <= startTime)
+ {
+ MessageBox.Show("The end time must be greater than the start time.", "Invalid Time Range", MessageBoxButtons.OK, MessageBoxIcon.Warning);
+ return;
+ }
+
+ long processStartTime = DateTime.UtcNow.Ticks;
+ string[] csvLines;
+
+ // Read CSV measurements from source file
+ ShowUpdateMessage("Reading source CSV measurements file: {0}...", textBoxSourceCSVMeasurements.Text);
+
+ try
+ {
+ csvLines = File.ReadAllLines(textBoxSourceCSVMeasurements.Text);
+ }
+ catch (Exception ex)
+ {
+ ShowUpdateMessage("Error reading source CSV measurements file: {0}", ex.Message);
+ return;
+ }
+
+ // Parse ID and SignalReference columns from CSV lines into a dictionary using header row
+ (Dictionary sourceCSVData, string deviceName) = ParseCSVMeasurements(csvLines);
+
+ if (sourceCSVData.Count == 0)
+ {
+ ShowUpdateMessage("No valid measurements found in source CSV file -- operation cancelled.");
+ return;
+ }
+
+ // Read CSV measurements from destination file
+ ShowUpdateMessage("Reading destination CSV measurements file: {0}...", textBoxDestinationCSVMeasurements.Text);
+
+ try
+ {
+ csvLines = File.ReadAllLines(textBoxDestinationCSVMeasurements.Text);
+ }
+ catch (Exception ex)
+ {
+ ShowUpdateMessage("Error reading destination CSV measurements file: {0}", ex.Message);
+ return;
+ }
+
+ // Parse ID and SignalReference columns from CSV lines ulong a dictionary using header row
+ (Dictionary destinationCSVData, _) = ParseCSVMeasurements(csvLines);
+
+ if (destinationCSVData.Count == 0)
+ {
+ ShowUpdateMessage("No valid measurements found in destination CSV file -- operation cancelled.");
+ return;
+ }
+
+ // Find measurements by SignalReference.Kind + SignalReference.Index in source CSV that also exist in destination CSV
+ // where the result is source CSV historian ID to destination CSV historian ID mapping
+ Dictionary historianIDMapping = new();
+
+ // Pre-index destination signals for O(1) lookup by match key
+ Dictionary<(SignalKind Kind, int Index), ulong> signalReferenceIDMap = [];
+ Dictionary<(SignalKind Kind, int Index, string Acronym), ulong> calculatedSignalReferenceIDMap = [];
+
+ foreach (KeyValuePair destinationEntry in destinationCSVData)
+ {
+ SignalReference destinationSignal = destinationEntry.Value;
+
+ if (destinationSignal.Kind == SignalKind.Calculation)
+ calculatedSignalReferenceIDMap[(destinationSignal.Kind, destinationSignal.Index, destinationSignal.Acronym ?? string.Empty)] = destinationEntry.Key;
+ else
+ signalReferenceIDMap[(destinationSignal.Kind, destinationSignal.Index)] = destinationEntry.Key;
+ }
+
+ foreach (KeyValuePair sourceEntry in sourceCSVData)
+ {
+ SignalReference sourceSignal = sourceEntry.Value;
+
+ if (sourceSignal.Kind == SignalKind.Calculation)
+ {
+ if (calculatedSignalReferenceIDMap.TryGetValue((sourceSignal.Kind, sourceSignal.Index, sourceSignal.Acronym ?? string.Empty), out ulong destID))
+ historianIDMapping[sourceEntry.Key] = destID;
+ }
+ else
+ {
+ if (signalReferenceIDMap.TryGetValue((sourceSignal.Kind, sourceSignal.Index), out ulong destID))
+ historianIDMapping[sourceEntry.Key] = destID;
+ }
+ }
+
+ if (historianIDMapping.Count == 0)
+ {
+ ShowUpdateMessage("No matching measurements found between source and destination CSV files -- operation cancelled.");
+ return;
+ }
+
+ ShowUpdateMessage("Found {0:N0} matching measurements between source and destination CSV files.", historianIDMapping.Count);
+
+ string sourcePath = textBoxSourceFiles.Text.Trim();
+ string destinationPath = textBoxDestinationFiles.Text.Trim();
+ bool processCompleted = false;
+
+ m_cancellationTokenSource = new CancellationTokenSource();
+ ICancellationToken monitorCancellationToken = null;
+
+ new Thread(() =>
+ {
+ try
+ {
+ EnableGoButton(false);
+
+ CancellationToken cancellationToken = m_cancellationTokenSource.Token;
+
+ int totalDays = (int)(endTime - startTime).TotalDays;
+ SetProgressMaximum(totalDays);
+ Stats.Clear();
+
+ const string InstanceName = "PPA";
+
+ // Establish archive information for this historian instance
+ HistorianServerDatabaseConfig archiveInfo = new(InstanceName, sourcePath, false)
+ {
+ TargetFileSize = (long)(1.5D * SI.Giga),
+ DirectoryMethod = ArchiveDirectoryMethod.YearThenMonth
+ };
+
+ HistorianServer server = new(archiveInfo);
+ SnapClient client = SnapClient.Connect(server.Host);
+ ClientDatabaseBase database = client.GetDatabase(InstanceName);
+ Dictionary attachedFiles = database.GetAllAttachedFiles()
+ .Where(file => file.EndTime > startTime && file.EndTime <= endTime)
+ .ToDictionary(file => file.Id);
+
+ using ArchiveList archiveList = new();
+
+ archiveList.LoadFiles(attachedFiles.Values
+ .OrderBy(file => file.EndTime)
+ .Select(file => file.FileName));
+
+ ShowUpdateMessage("Found {0:N0} archives in source location covering specified time range.", attachedFiles.Count);
+
+ SeekFilterBase timeFilter = TimestampSeekFilter.CreateFromRange(startTime, endTime);
+ MatchFilterBase pointFilter = PointIdMatchFilter.CreateFromList(historianIDMapping.Keys);
+
+ using WorkerThreadSynchronization workerThreadSynchronization = new();
+ using TranslatingStreamReader reader = new(archiveList, historianIDMapping, SortedTreeEngineReaderOptions.Default, timeFilter, pointFilter, workerThreadSynchronization);
+
+ long lastStatusMessage = DateTime.UtcNow.Ticks;
+
+ void readingMonitor()
+ {
+ if (cancellationToken.IsCancellationRequested || processCompleted)
+ {
+ reader.CancelReader();
+ return;
+ }
+
+ if (DateTime.UtcNow.Ticks - lastStatusMessage < FeedbackInterval * Ticks.PerMillisecond)
+ {
+ workerThreadSynchronization.RequestCallback(() =>
+ {
+ lastStatusMessage = DateTime.UtcNow.Ticks;
+
+ if (Stats.PointsReturned == 0L)
+ {
+ ShowUpdateMessage("\r\nScanning archives for points in specified time range, processing {0:N0} cache miss retries per second...", Stats.PointsScanned / ((DateTime.UtcNow.Ticks - processStartTime) / Ticks.PerSecond));
+ }
+ else
+ {
+ ShowUpdateMessage("\r\nProcessed {0:N0} points so far, scanning at {1:N0} points per second:", Stats.PointsReturned, Stats.PointsReturned / ((DateTime.UtcNow.Ticks - processStartTime) / Ticks.PerSecond));
+
+ double processedDays = (reader.LastKey.TimestampAsDate - startTime).TotalDays;
+
+ UpdateProgressBar((int)processedDays);
+ ShowUpdateMessage(" {0:0.00%} complete...", processedDays / totalDays);
+ }
+ });
+ }
+
+ monitorCancellationToken = new Action(readingMonitor).DelayAndExecute(MonitoringInterval);
+ }
+
+ monitorCancellationToken = new Action(readingMonitor).DelayAndExecute(MonitoringInterval);
+
+ string completeFileName = Path.Combine(destinationPath, $"{deviceName}-Exported.d2");
+ string pendingFileName = Path.Combine(destinationPath, $"{FilePath.GetFileNameWithoutExtension(completeFileName)}.~d2i");
+
+ if (File.Exists(pendingFileName))
+ File.Delete(pendingFileName);
+
+ if (File.Exists(completeFileName))
+ File.Delete(completeFileName);
+
+ SortedTreeFileSimpleWriter.Create(pendingFileName, completeFileName, 4096, null, HistorianFileEncodingDefinition.TypeGuid, reader, FileFlags.GetStage(3));
+
+ Ticks processDuration = DateTime.UtcNow.Ticks - processStartTime;
+ processCompleted = true;
+
+ ShowUpdateMessage("\r\nData transfer completed in {0}", processDuration.ToElapsedTimeString(2));
+ UpdateProgressBar(totalDays);
+ }
+ catch (Exception ex)
+ {
+ ShowUpdateMessage("\r\nError during transfer: {0}", ex.Message);
+ }
+ finally
+ {
+ monitorCancellationToken?.Cancel();
+ EnableGoButton(true);
+ }
+ })
+ {
+ IsBackground = true
+ }
+ .Start();
+ }
+
+ private void buttonCancel_Click(object sender, EventArgs e)
+ {
+ m_cancellationTokenSource.Cancel();
+ ShowUpdateMessage("Transfer operation cancelled by user.");
+ }
+
+ private (Dictionary csvData, string deviceName) ParseCSVMeasurements(string[] csvLines)
+ {
+ Dictionary csvData = new();
+
+ if (csvLines is null || csvLines.Length <= 1)
+ return (csvData, "");
+
+ // Parse header to find column indices using robust CSV parser
+ string[] headers = ParseCSVLine(csvLines[0]);
+
+ int deviceIndex = Array.FindIndex(headers, header => header.Trim().Equals("Device", StringComparison.OrdinalIgnoreCase));
+
+ if (deviceIndex < 0)
+ {
+ ShowUpdateMessage("CSV header must contain 'Device' column.");
+ return (csvData, "");
+ }
+
+ // Validate that device names in all rows are the same
+ string firstDeviceName = null;
+
+ for (int i = 1; i < csvLines.Length; i++)
+ {
+ if (string.IsNullOrWhiteSpace(csvLines[i]))
+ continue;
+
+ string[] columns = ParseCSVLine(csvLines[i]);
+
+ if (columns.Length <= deviceIndex)
+ continue;
+
+ string deviceName = columns[deviceIndex].Trim();
+
+ if (string.IsNullOrEmpty(firstDeviceName))
+ {
+ firstDeviceName = deviceName;
+ }
+ else if (!string.Equals(firstDeviceName, deviceName, StringComparison.OrdinalIgnoreCase))
+ {
+ ShowUpdateMessage("All rows in CSV file must have the same 'Device' name. Export is designed to transfer one device at a time.");
+ return (csvData, "");
+ }
+ }
+
+ int idIndex = Array.FindIndex(headers, header => header.Trim().Equals("ID", StringComparison.OrdinalIgnoreCase));
+ int signalRefIndex = Array.FindIndex(headers, header => header.Trim().Equals("SignalReference", StringComparison.OrdinalIgnoreCase));
+
+ if (idIndex < 0 || signalRefIndex < 0)
+ {
+ ShowUpdateMessage("CSV header must contain 'ID' and 'SignalReference' columns.");
+ return (csvData, "");
+ }
+
+ int maxColumnIndex = Math.Max(Math.Max(deviceIndex, idIndex), signalRefIndex);
+ int calcIndex = 1;
+
+ // Parse data rows using robust CSV parser
+ for (int i = 1; i < csvLines.Length; i++)
+ {
+ if (string.IsNullOrWhiteSpace(csvLines[i]))
+ continue;
+
+ string[] columns = ParseCSVLine(csvLines[i]);
+
+ if (columns.Length <= maxColumnIndex)
+ continue;
+
+ string idValue = columns[idIndex].Trim();
+
+ if (string.IsNullOrEmpty(idValue))
+ continue;
+
+ string[] parts = idValue.Split(':');
+
+ if (parts.Length != 2 || !ulong.TryParse(parts[1], out ulong id))
+ {
+ ShowUpdateMessage("Invalid ID format in row {0}: {1}. Expected format is 'Source:ID'.", i + 1, idValue);
+ continue;
+ }
+
+ string signalReferenceValue = columns[signalRefIndex].Trim();
+
+ if (string.IsNullOrEmpty(signalReferenceValue))
+ continue;
+
+ SignalReference signalReference = new(signalReferenceValue);
+
+ if (signalReference.Kind == SignalKind.Unknown)
+ {
+ parts = signalReferenceValue.Split('-');
+
+ if (parts.Length > 1)
+ {
+ // Track matching acronyms for Calculation signals
+ signalReference.Acronym = parts[parts.Length - 1].Trim();
+ signalReference.Kind = SignalKind.Calculation;
+ signalReference.Index = calcIndex++;
+ }
+ else
+ {
+ continue; // Skip invalid SignalReference
+ }
+ }
+
+ csvData[id] = signalReference;
+ }
+
+ return (csvData, firstDeviceName ?? "");
+ }
+
+ private static string[] ParseCSVLine(string line)
+ {
+ if (string.IsNullOrEmpty(line))
+ return [];
+
+ List fields = [];
+ StringBuilder current = new();
+ bool inQuotes = false;
+
+ for (int i = 0; i < line.Length; i++)
+ {
+ char c = line[i];
+
+ if (inQuotes)
+ {
+ if (c == '"')
+ {
+ // Check for escaped quote ("")
+ if (i + 1 < line.Length && line[i + 1] == '"')
+ {
+ current.Append('"');
+ i++; // Skip the next quote
+ }
+ else
+ {
+ inQuotes = false;
+ }
+ }
+ else
+ {
+ current.Append(c);
+ }
+ }
+ else
+ {
+ switch (c)
+ {
+ case ',':
+ fields.Add(current.ToString());
+ current.Clear();
+ break;
+ case '"':
+ inQuotes = true;
+ break;
+ default:
+ current.Append(c);
+ break;
+ }
+ }
+ }
+
+ fields.Add(current.ToString());
+
+ return fields.ToArray();
+ }
+
+ private void EnableGoButton(bool enabled)
+ {
+ if (m_formClosing)
+ return;
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(EnableGoButton), enabled);
+ }
+ else
+ {
+ buttonGo.Enabled = enabled;
+ buttonGo.Visible = enabled;
+ }
+ }
+
+ private void UpdateProgressBar(int value)
+ {
+ if (m_formClosing)
+ return;
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(UpdateProgressBar), value);
+ }
+ else
+ {
+ if (value < progressBar.Minimum)
+ value = progressBar.Minimum;
+
+ if (value > progressBar.Maximum)
+ progressBar.Maximum = value;
+
+ progressBar.Value = value;
+ }
+ }
+
+ private void SetProgressMaximum(int maximum)
+ {
+ if (m_formClosing)
+ return;
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(SetProgressMaximum), maximum);
+ }
+ else
+ {
+ progressBar.Maximum = maximum;
+ }
+ }
+
+ private void ClearUpdateMessages()
+ {
+ if (m_formClosing)
+ return;
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(ClearUpdateMessages));
+ }
+ else
+ {
+ lock (textBoxMessageOutput)
+ textBoxMessageOutput.Text = "";
+ }
+ }
+
+ private void ShowUpdateMessage(string message, params object[] args)
+ {
+ if (m_formClosing)
+ return;
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new Action(ShowUpdateMessage), message, args);
+ }
+ else
+ {
+ StringBuilder outputText = new();
+
+ outputText.AppendFormat(message, args);
+ outputText.AppendLine();
+
+ lock (textBoxMessageOutput)
+ textBoxMessageOutput.AppendText(outputText.ToString());
+ }
+ }
+ }
+}
diff --git a/Source/Tools/OHTransfer/OHTransfer.csproj b/Source/Tools/OHTransfer/OHTransfer.csproj
new file mode 100644
index 0000000000..0549002286
--- /dev/null
+++ b/Source/Tools/OHTransfer/OHTransfer.csproj
@@ -0,0 +1,115 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}
+ WinExe
+ OHTransfer
+ OHTransfer
+ v4.8
+ 512
+ true
+ true
+ latest
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ false
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ false
+
+
+ OHTransfer.ico
+
+
+
+ ..\..\Dependencies\GSF\GSF.Core.dll
+
+
+ ..\..\Dependencies\GSF\GSF.Windows.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ OHTransfer.cs
+
+
+
+
+
+ OHTransfer.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
+
+
+
+ {040e2ae7-021b-435a-adbf-06d07ee0a67d}
+ GSF.SortedTreeStore
+
+
+ {7b53c942-e891-461c-b09c-49faba82f19d}
+ openHistorian.Core
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Tools/OHTransfer/OHTransfer.ico b/Source/Tools/OHTransfer/OHTransfer.ico
new file mode 100644
index 0000000000..e074a5092a
Binary files /dev/null and b/Source/Tools/OHTransfer/OHTransfer.ico differ
diff --git a/Source/Tools/OHTransfer/OHTransfer.resx b/Source/Tools/OHTransfer/OHTransfer.resx
new file mode 100644
index 0000000000..d278b50a58
--- /dev/null
+++ b/Source/Tools/OHTransfer/OHTransfer.resx
@@ -0,0 +1,1165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 24, 17
+
+
+ 185, 17
+
+
+ 277, 17
+
+
+
+
+ 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
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgADAABAAsJERwNgTCMEfdO9RX/UP0V/1D8Ff9Q/RX/TvQV/ylx
+ EO4MCwxMEBsNAAwMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAQsAAQALCBAbDYEvhxH2TvMV/1D9
+ Ff9R/hX/OKcS/xAcDYcAAAoDCwcMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAALAAEA
+ CwgPGAyCLX8Q9E3xFP9J4xT/HUYOzAUACx4LCAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAcACwABAAsHDhUMbCp1EOssfhD7DREMYhIiDQAMCwwAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAsAAAAKBA0QDFQPFgx/CgYMEwsJDAAAAAAAAAAAAAAA
+ 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
+
+
+
\ No newline at end of file
diff --git a/Source/Tools/OHTransfer/OHTransfer.sln b/Source/Tools/OHTransfer/OHTransfer.sln
new file mode 100644
index 0000000000..ff8aa0a553
--- /dev/null
+++ b/Source/Tools/OHTransfer/OHTransfer.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.14.36401.2 d17.14
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OHTransfer", "OHTransfer.csproj", "{FE351919-B4A6-4D81-91CC-64BC1D588ECC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {365C2FB8-B1C5-4D4E-A5EA-2F8F759AC740}
+ EndGlobalSection
+EndGlobal
diff --git a/Source/Tools/OHTransfer/OHTransfer.sln.DotSettings b/Source/Tools/OHTransfer/OHTransfer.sln.DotSettings
new file mode 100644
index 0000000000..7dbc342733
--- /dev/null
+++ b/Source/Tools/OHTransfer/OHTransfer.sln.DotSettings
@@ -0,0 +1,2 @@
+
+ CSV
\ No newline at end of file
diff --git a/Source/Tools/OHTransfer/Program.cs b/Source/Tools/OHTransfer/Program.cs
new file mode 100644
index 0000000000..c290b1316b
--- /dev/null
+++ b/Source/Tools/OHTransfer/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace OHTransfer
+{
+ internal static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new OHTransfer());
+ }
+ }
+}
diff --git a/Source/Tools/OHTransfer/Properties/AssemblyInfo.cs b/Source/Tools/OHTransfer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..5cfa672c5a
--- /dev/null
+++ b/Source/Tools/OHTransfer/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("OHTransfer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("OHTransfer")]
+[assembly: AssemblyCopyright("Copyright © 2025")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("fe351919-b4a6-4d81-91cc-64bc1d588ecc")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Source/Tools/OHTransfer/Properties/Resources.Designer.cs b/Source/Tools/OHTransfer/Properties/Resources.Designer.cs
new file mode 100644
index 0000000000..db3b947816
--- /dev/null
+++ b/Source/Tools/OHTransfer/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace OHTransfer.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OHTransfer.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Source/Tools/OHTransfer/Properties/Resources.resx b/Source/Tools/OHTransfer/Properties/Resources.resx
new file mode 100644
index 0000000000..af7dbebbac
--- /dev/null
+++ b/Source/Tools/OHTransfer/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Source/Tools/OHTransfer/Properties/Settings.Designer.cs b/Source/Tools/OHTransfer/Properties/Settings.Designer.cs
new file mode 100644
index 0000000000..e8cafbbd4b
--- /dev/null
+++ b/Source/Tools/OHTransfer/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace OHTransfer.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Source/Tools/OHTransfer/Properties/Settings.settings b/Source/Tools/OHTransfer/Properties/Settings.settings
new file mode 100644
index 0000000000..39645652af
--- /dev/null
+++ b/Source/Tools/OHTransfer/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Source/Tools/OHTransfer/TranslatingStreamReader.cs b/Source/Tools/OHTransfer/TranslatingStreamReader.cs
new file mode 100644
index 0000000000..c1993f6910
--- /dev/null
+++ b/Source/Tools/OHTransfer/TranslatingStreamReader.cs
@@ -0,0 +1,69 @@
+//******************************************************************************************************
+// TranslatingStreamReader.cs - Gbtc
+//
+// Copyright © 2025, Grid Protection Alliance. All Rights Reserved.
+//
+// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
+// the NOTICE file distributed with this work for additional information regarding copyright ownership.
+// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may not use this
+// file except in compliance with the License. You may obtain a copy of the License at:
+//
+// http://opensource.org/licenses/MIT
+//
+// Unless agreed to in writing, the subject software distributed under the License is distributed on an
+// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
+// License for the specific language governing permissions and limitations.
+//
+// Code Modification History:
+// ----------------------------------------------------------------------------------------------------
+// 08/13/2025 - J. Ritchie Carroll
+// Generated original version of source code.
+//
+//******************************************************************************************************
+
+using System.Collections.Generic;
+using GSF.Snap.Filters;
+using GSF.Snap.Services;
+using GSF.Snap.Services.Reader;
+using GSF.Threading;
+using openHistorian.Snap;
+
+namespace OHTransfer;
+
+///
+/// Represents a sequential reader stream for reading historian data from an archive list that
+/// translates source IDs to destination IDs using the .
+///
+///
+/// We derive a specific implementation of this class so we can translate source IDs to
+/// destination IDs and also track last processed key in the stream for progress reporting.
+///
+internal class TranslatingStreamReader(
+ ArchiveList archiveList,
+ Dictionary historianIDMapping,
+ SortedTreeEngineReaderOptions readerOptions = null,
+ SeekFilterBase keySeekFilter = null,
+ MatchFilterBase keyMatchFilter = null,
+ WorkerThreadSynchronization workerThreadSynchronization = null) :
+ SequentialReaderStream(
+ archiveList,
+ readerOptions,
+ keySeekFilter,
+ keyMatchFilter,
+ workerThreadSynchronization)
+{
+ public HistorianKey LastKey = new();
+
+ ///
+ protected override bool ReadNext(HistorianKey key, HistorianValue value)
+ {
+ bool result = base.ReadNext(key, value);
+
+ if (historianIDMapping.TryGetValue(key.PointID, out ulong destinationPointID))
+ key.PointID = destinationPointID;
+
+ LastKey = key;
+
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/Source/Tools/OHTransfer/openHistorian.ico b/Source/Tools/OHTransfer/openHistorian.ico
new file mode 100644
index 0000000000..9efe34e937
Binary files /dev/null and b/Source/Tools/OHTransfer/openHistorian.ico differ
diff --git a/Source/openHistorian.sln b/Source/openHistorian.sln
index 80a7c3120c..03cb2fd8ea 100755
--- a/Source/openHistorian.sln
+++ b/Source/openHistorian.sln
@@ -537,6 +537,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docker", "Docker", "{7F01BE
DockerReadMe.md = DockerReadMe.md
EndProjectSection
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OHTransfer", "Tools\OHTransfer\OHTransfer.csproj", "{FE351919-B4A6-4D81-91CC-64BC1D588ECC}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1200,6 +1202,24 @@ Global
{7F5BBF4C-A27D-4367-9D1E-95AEA45EC58B}.Release|x64.Build.0 = Release|Any CPU
{7F5BBF4C-A27D-4367-9D1E-95AEA45EC58B}.Release|x86.ActiveCfg = Release|Any CPU
{7F5BBF4C-A27D-4367-9D1E-95AEA45EC58B}.Release|x86.Build.0 = Release|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Debug|x64.Build.0 = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Debug|x86.Build.0 = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Mono|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Mono|Any CPU.Build.0 = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Mono|x64.ActiveCfg = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Mono|x64.Build.0 = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Mono|x86.ActiveCfg = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Mono|x86.Build.0 = Debug|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Release|x64.ActiveCfg = Release|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Release|x64.Build.0 = Release|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Release|x86.ActiveCfg = Release|Any CPU
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1260,6 +1280,7 @@ Global
{D61BBB31-74A7-498D-8C36-FB18C72609F8} = {880E5A69-EE1E-46EC-838F-783F188D8B49}
{9DE89239-FEDC-4218-8770-1167A22EC999} = {550621C3-C903-4405-971A-DC4BAA286BA0}
{7F5BBF4C-A27D-4367-9D1E-95AEA45EC58B} = {3A952272-B64C-48E0-9CB2-0130AC28D72E}
+ {FE351919-B4A6-4D81-91CC-64BC1D588ECC} = {3A952272-B64C-48E0-9CB2-0130AC28D72E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {CA73B94E-45F7-4272-BCA2-4B4386CC92B2}