Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Versioning_Engine: Add methodology for directly calling upgrades from main process rather than via pipes #3332

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 136 additions & 21 deletions Versioning_Engine/Convert/ToNewVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
/**** Public Methods ****/
/***************************************************/

public static string ToNewVersion(string json)

Check warning on line 47 in Versioning_Engine/Convert/ToNewVersion.cs

View check run for this annotation

BHoMBot-CI / documentation-compliance

Versioning_Engine/Convert/ToNewVersion.cs#L47

Input parameter requires a matching Input attribute - For more information see https://bhom.xyz/documentation/DevOps/Code%20Compliance%20and%20CI/Compliance%20Checks/IsInputAttributePresent Method must contain an Output or MultiOutput attribute - For more information see https://bhom.xyz/documentation/DevOps/Code%20Compliance%20and%20CI/Compliance%20Checks/HasOutputAttribute
{
BsonDocument document;
if (BsonDocument.TryParse(json, out document))
Expand All @@ -64,7 +64,7 @@

/***************************************************/

public static BsonDocument ToNewVersion(this BsonDocument document, string version = "")

Check warning on line 67 in Versioning_Engine/Convert/ToNewVersion.cs

View check run for this annotation

BHoMBot-CI / documentation-compliance

Versioning_Engine/Convert/ToNewVersion.cs#L67

Input parameter requires a matching Input attribute - For more information see https://bhom.xyz/documentation/DevOps/Code%20Compliance%20and%20CI/Compliance%20Checks/IsInputAttributePresent Input parameter requires a matching Input attribute - For more information see https://bhom.xyz/documentation/DevOps/Code%20Compliance%20and%20CI/Compliance%20Checks/IsInputAttributePresent Method must contain an Output or MultiOutput attribute - For more information see https://bhom.xyz/documentation/DevOps/Code%20Compliance%20and%20CI/Compliance%20Checks/HasOutputAttribute
{
if (document == null)
return null;
Expand All @@ -83,32 +83,71 @@
// Get the list of upgraders to call
List<string> versions = Query.UpgradersToCall(version);

bool versionWithPipes = false;

lock (m_versioningLock)
{
// Call all the upgraders in sequence
for (int i = 0; i < versions.Count; i++)
if (versionWithPipes)
{
// Create a connection with the upgrader
NamedPipeServerStream pipe = GetPipe(versions[i]);
if (pipe == null)
return document;
// Call all the upgraders in sequence
for (int i = 0; i < versions.Count; i++)
{
// Create a connection with the upgrader
NamedPipeServerStream pipe = GetPipe(versions[i]);
if (pipe == null)
return document;

// Send the document
SendDocument(document, pipe);
// Send the document
SendDocument(document, pipe);

// Get the new version back
BsonDocument result = ReadDocument(pipe);
if (result != null)
// Get the new version back
BsonDocument result = ReadDocument(pipe);
if (result != null)
{
if (result.Contains("_t") && result["_t"] == "NoUpdate")
{
if (result.Contains("Message"))
{
noUpdateMessage = result["Message"].ToString();
Engine.Base.Compute.RecordError(noUpdateMessage);
}
}
else if (document != result)
{
wasUpdated = true;
document = result;
}
}
}
}
else
{
// Call all the upgraders in sequence
for (int i = 0; i < versions.Count; i++)
{
if (result.Contains("_t") && result["_t"] == "NoUpdate")
BsonDocument result = null;
try
{
if (result.Contains("Message"))
//Get pre-compiled upgrader method for the version
Func<BsonDocument, BsonDocument> upgrader = GetUpgraderMethod(versions[i]);
if (upgrader != null)
result = upgrader(document); //Upgrade
}
catch (Exception e)
{
if (e.GetType().Name == "NoUpdateException")
{
Engine.Base.Compute.RecordError(e.Message);
noUpdateMessage = e.Message;
result = null;
}
else
{
noUpdateMessage = result["Message"].ToString();
Engine.Base.Compute.RecordError(noUpdateMessage);
Engine.Base.Compute.RecordError(e, "BHoMUpgrader exception:");
}
}
else if (document != result)

if (result != null && document != result)
{
wasUpdated = true;
document = result;
Expand All @@ -117,7 +156,6 @@
}
}

// Record the fact that a document needed to be upgraded
if (wasUpdated || noUpdateMessage != null)
{
string newDocument = noUpdateMessage != null ? null : Compute.VersioningKey(document);
Expand All @@ -134,7 +172,6 @@
Message = message
});
}

return document;
}

Expand Down Expand Up @@ -167,7 +204,7 @@

// Find the upgrader file
string upgraderName = "BHoMUpgrader" + version.Replace(".", "");
string processFile = upgraderName + "\\" + upgraderName + ".exe";
string processFile = upgraderName + "\\" + upgraderName + ".exe";
if (!File.Exists(processFile))
{
processFile = Path.Combine(BH.Engine.Base.Query.BHoMFolderUpgrades(), processFile);
Expand All @@ -184,11 +221,11 @@
process.StartInfo = new ProcessStartInfo(processFile, pipeName);
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
bool ok = process.Start();
bool ok = process.Start();

// Waiting for pipe to connect
pipe.WaitForConnection();

// Store the pipe
m_Pipes[version] = pipe;

Expand Down Expand Up @@ -229,6 +266,74 @@
return BsonSerializer.Deserialize(content, typeof(BsonDocument)) as BsonDocument;
}

/***************************************************/

private static string FindFile(string path)
{
if (!File.Exists(path))
{
path = Path.Combine(BH.Engine.Base.Query.BHoMFolderUpgrades(), path);

if (!File.Exists(path))
{
Base.Compute.RecordWarning(path.Split(new char[] { '\\' }).Last() + " is missing. The object will not be upgraded");
return null;
}
}
return path;
}

/***************************************************/

private static Func<BsonDocument, BsonDocument> GetUpgraderMethod(string version)
{
// Return the pipe if already exists
if (m_CompiledUpgraders.ContainsKey(version))
return m_CompiledUpgraders[version];


// Find the upgrader file
string upgraderName = "BHoMUpgrader" + version.Replace(".", "");
string processFile = FindFile(upgraderName + "\\" + upgraderName + ".exe");
if (processFile == null)
return null;

Assembly converterAssembly = Assembly.LoadFrom(processFile);

if (m_BaseConverter == null)
{
Assembly upgraderAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(x => x.GetName().Name == "BHoMUpgrader");
if (upgraderAssembly == null)
{
string baseUpgraderName = "BHoMUpgrader" + version.Replace(".", "");
string baseProcessFile = FindFile(upgraderName + "\\" + "BHoMUpgrader" + ".dll");
if (baseUpgraderName == null)
return null;
upgraderAssembly = Assembly.LoadFrom(baseProcessFile);
}
Type upgraderType = upgraderAssembly.GetTypes().First(x => x.Name == "Upgrader");
m_Upgrader = Activator.CreateInstance(upgraderType);
m_UpgraderMethod = upgraderType.GetMethod("Upgrade", BindingFlags.NonPublic | BindingFlags.Instance);

Type baseConverterType = upgraderAssembly.GetTypes().First(x => x.Name == "Converter");
m_BaseConverter = Activator.CreateInstance(baseConverterType);
}

Type converterType = converterAssembly.GetTypes().First(x => m_BaseConverter.GetType().IsAssignableFrom(x));
dynamic converter = Activator.CreateInstance(converterType);

Func<BsonDocument, BsonDocument> func = CreateUpgradeFunction(converter as dynamic, m_BaseConverter as dynamic);
m_CompiledUpgraders[version] = func;
return func;
}

/***************************************************/

private static Func<BsonDocument, BsonDocument> CreateUpgradeFunction<T, TBase>(T converter, TBase baseConverter) where T : class where TBase : class
{
Func<BsonDocument, TBase, BsonDocument> initFunc = (Func<BsonDocument, TBase, BsonDocument>)Delegate.CreateDelegate(typeof(Func<BsonDocument, TBase, BsonDocument>), m_Upgrader, m_UpgraderMethod);
return x => initFunc(x, converter as TBase);
}

/***************************************************/
/**** Private Fields ****/
Expand All @@ -239,6 +344,16 @@
private static object m_versioningLock = new object();

/***************************************************/

private static Dictionary<string, Func<BsonDocument, BsonDocument>> m_CompiledUpgraders = new Dictionary<string, Func<BsonDocument, BsonDocument>>();

private static object m_Upgrader = null;

private static dynamic m_BaseConverter = null;

private static MethodInfo m_UpgraderMethod = null;

/***************************************************/
}
}

Expand Down
Loading