using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using SQLitePCL;
namespace Mrleo1nid.SwarmAssistent;
///
/// SwarmUI loads extensions in an isolated AssemblyLoadContext — Microsoft.Data.Sqlite
/// does not auto-init native SQLite there. Native libs ship under the extension dir
/// (runtimes/linux-x64/native/libe_sqlite3.so), but the loader searches the host
/// base dir unless we preload from the extension assembly location.
///
internal static class AssistentSqliteBootstrap
{
static int _ready;
internal static void EnsureInitialized()
{
if (Interlocked.CompareExchange(ref _ready, 1, 0) != 0)
{
return;
}
PreloadNativeLibrary();
Batteries_V2.Init();
}
static void PreloadNativeLibrary()
{
string extDir = Path.GetDirectoryName(typeof(AssistentSqliteBootstrap).Assembly.Location)
?? AppContext.BaseDirectory
?? "";
if (string.IsNullOrWhiteSpace(extDir))
{
return;
}
foreach (string rel in CandidatePaths())
{
string path = Path.Combine(extDir, rel);
if (!File.Exists(path))
{
continue;
}
try
{
IntPtr handle = NativeLibrary.Load(path);
RegisterResolver(handle);
return;
}
catch (Exception ex)
{
SwarmUI.Utils.Logs.Debug($"AssistentSqliteBootstrap: NativeLibrary.Load({path}): {ex.Message}");
}
}
}
/// Native e_sqlite3 locations for the current OS / arch, most specific first.
static string[] CandidatePaths()
{
string arch = RuntimeInformation.ProcessArchitecture switch
{
Architecture.Arm64 => "arm64",
Architecture.X86 => "x86",
Architecture.Arm => "arm",
_ => "x64",
};
if (OperatingSystem.IsWindows())
{
return [Path.Combine("runtimes", $"win-{arch}", "native", "e_sqlite3.dll"), "e_sqlite3.dll"];
}
if (OperatingSystem.IsMacOS())
{
return [Path.Combine("runtimes", $"osx-{arch}", "native", "libe_sqlite3.dylib"), "libe_sqlite3.dylib"];
}
return
[
Path.Combine("runtimes", $"linux-{arch}", "native", "libe_sqlite3.so"),
Path.Combine("runtimes", $"linux-{arch}", "native", "e_sqlite3.so"),
"libe_sqlite3.so",
"e_sqlite3.so",
];
}
/// The provider's [DllImport("e_sqlite3")] would otherwise probe the host dir, not the extension dir.
static void RegisterResolver(IntPtr handle)
{
try
{
NativeLibrary.SetDllImportResolver(typeof(SQLite3Provider_e_sqlite3).Assembly,
(name, _, _) => name.Contains("e_sqlite3", StringComparison.OrdinalIgnoreCase) ? handle : IntPtr.Zero);
}
catch (InvalidOperationException)
{
// A resolver is already set for this assembly — the preloaded handle still helps on Windows.
}
}
}