Skip to content

Commit

Permalink
Refactor of paths, this new methodology will solve bugs related to th…
Browse files Browse the repository at this point in the history
…e load_from_file of multiple loaders. This new mode will standardize how it works and reduce friction between loaders.
  • Loading branch information
viferga committed May 10, 2021
1 parent 83bd101 commit 8a3e90a
Show file tree
Hide file tree
Showing 53 changed files with 1,166 additions and 432 deletions.
2 changes: 1 addition & 1 deletion source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#

# Export output script directory
set(LOADER_SCRIPT_PATH "${PROJECT_BINARY_DIR}/scripts/" CACHE PATH "MetaCall scripts path")
set(LOADER_SCRIPT_PATH "${PROJECT_BINARY_DIR}/scripts" CACHE PATH "MetaCall scripts path")

# Export output loader plugin directory
set(LOADER_LIBRARY_PATH "@OUTPUT_DIRECTORY_DIR@" CACHE PATH "MetaCall loaders path")
Expand Down
40 changes: 1 addition & 39 deletions source/loader/source/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,45 +403,7 @@ int loader_load_from_file(const loader_naming_tag tag, const loader_naming_path

if (impl != NULL)
{
const char *script_path = loader_env_script_path();

if (script_path != NULL)
{
loader_naming_path *absolute_paths = malloc(sizeof(loader_naming_path) * size);

size_t iterator;

int result;

if (absolute_paths == NULL)
{
log_write("metacall", LOG_LEVEL_ERROR, "Loader load from file invalid absolute paths allocation");

return 1;
}

for (iterator = 0; iterator < size; ++iterator)
{
if (loader_path_is_absolute(paths[iterator]) != 0)
{
(void)loader_path_join(script_path, strlen(script_path) + 1, paths[iterator], strnlen(paths[iterator], LOADER_NAMING_PATH_SIZE - 1) + 1, absolute_paths[iterator]);
}
else
{
strncpy(absolute_paths[iterator], paths[iterator], strnlen(paths[iterator], LOADER_NAMING_PATH_SIZE - 1) + 1);
}
}

result = loader_impl_load_from_file(impl, (const loader_naming_path *)absolute_paths, size, handle);

free(absolute_paths);

return result;
}
else
{
return loader_impl_load_from_file(impl, paths, size, handle);
}
return loader_impl_load_from_file(impl, paths, size, handle);
}
}
}
Expand Down
13 changes: 12 additions & 1 deletion source/loader/source/loader_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ int loader_impl_initialize(loader_impl impl)
configuration config;

const char *script_path = NULL;
const char *library_path = NULL;

vector paths;

Expand Down Expand Up @@ -303,6 +304,16 @@ int loader_impl_initialize(loader_impl impl)
loader_impl_configuration(impl, config);
}

library_path = loader_env_library_path();

if (library_path != NULL)
{
if (loader_impl_execution_path(impl, library_path) != 0)
{
log_write("metacall", LOG_LEVEL_ERROR, "Error when loading path %s", library_path);
}
}

script_path = loader_env_script_path();

if (script_path != NULL)
Expand Down Expand Up @@ -665,7 +676,7 @@ int loader_impl_load_from_file(loader_impl impl, const loader_naming_path paths[

handle = interface_impl->load_from_file(impl, paths, size);

log_write("metacall", LOG_LEVEL_DEBUG, "Loader interface: %p\nLoader handle: %p", (void *)interface_impl, (void *)handle);
log_write("metacall", LOG_LEVEL_DEBUG, "Loader interface: %p; Loader handle: %p", (void *)interface_impl, (void *)handle);

if (handle != NULL)
{
Expand Down
16 changes: 15 additions & 1 deletion source/loader/source/loader_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,19 @@ size_t loader_path_join(const loader_naming_path left_path, size_t left_path_siz
size_t loader_path_canonical(const loader_naming_path path, size_t size, loader_naming_path canonical)
{
size_t iterator, canonical_size = 0;
int separator_found = 1;
char separator;

/* Standarize the separators */
for (iterator = 0; iterator < size; ++iterator)
{
if (LOADER_PATH_SEPARATOR(path[iterator]))
{
separator_found = 0;
separator = path[iterator];
break;
}
}

/* Remove first dots */
for (iterator = 0; path[iterator] == '.'; ++iterator)
Expand Down Expand Up @@ -310,7 +323,8 @@ size_t loader_path_canonical(const loader_naming_path path, size_t size, loader_
}
}

canonical[canonical_size++] = path[iterator];
/* Store the correct separator */
canonical[canonical_size++] = LOADER_PATH_SEPARATOR(path[iterator]) && separator_found == 0 ? separator : path[iterator];
}

return canonical_size;
Expand Down
4 changes: 4 additions & 0 deletions source/loaders/cob_loader/source/cob_loader_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ loader_impl_data cob_loader_impl_initialize(loader_impl impl, configuration conf
(void)impl;
(void)config;

// TODO: The enviroment path trick wont be needed if
// we implement cob_loader_impl_execution_path properly.
// Remove this once we implement this properly (if needed)

// Copy environment variables in order to resolve properly the scripts
const char *scripts_path = getenv("LOADER_SCRIPT_PATH");

Expand Down
19 changes: 10 additions & 9 deletions source/loaders/cs_loader/include/cs_loader/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,23 @@ typedef struct
reflect_param pars[10];
} reflect_function;

typedef void(void_func)(void);
typedef char(execution_path_w)(const wchar_t *source);
typedef char(execution_path_c)(const char *source);

typedef char(load_from_source_w)(wchar_t *source);
typedef char(load_from_source_w)(const wchar_t *source);
typedef char(load_from_source_c)(const char *source);

typedef char(load_from_files_w)(wchar_t **source, size_t size);
typedef char(load_from_files_c)(char **source, size_t size);
typedef char(load_from_files_w)(const wchar_t **source, size_t size);
typedef char(load_from_files_c)(const char **source, size_t size);

typedef char(load_from_assembly_w)(wchar_t *source);
typedef char(load_from_assembly_w)(const wchar_t *source);
typedef char(load_from_assembly_c)(const char *source);

typedef void(corefunction_destroy_execution_result)(execution_result *er);
typedef execution_result *(execute_function_c)(char *function);
typedef execution_result *(execute_function_w)(wchar_t *function);
typedef execution_result *(execute_function_with_params_w)(wchar_t *function, parameters *);
typedef execution_result *(execute_function_with_params_c)(char *function, parameters *);
typedef execution_result *(execute_function_c)(const char *function);
typedef execution_result *(execute_function_w)(const wchar_t *function);
typedef execution_result *(execute_function_with_params_w)(const wchar_t *function, parameters *);
typedef execution_result *(execute_function_with_params_c)(const char *function, parameters *);
typedef void(get_loaded_functions)(int *, reflect_function *);

#if defined(__linux) | defined(linux)
Expand Down
29 changes: 19 additions & 10 deletions source/loaders/cs_loader/include/cs_loader/netcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ class netcore
char *dotnet_loader_assembly_path;

public:
execution_path_w *core_execution_path_w;
execution_path_c *core_execution_path_c;

load_from_source_w *core_load_from_source_w;
load_from_source_c *core_load_from_source_c;

Expand All @@ -53,6 +56,9 @@ class netcore
const CHARSTRING *class_name = W("CSLoader.MetacallEntryPoint");
const CHARSTRING *assembly_name = W("CSLoader");

const CHARSTRING *delegate_execution_path_w = W("ExecutionPathW");
const CHARSTRING *delegate_execution_path_c = W("ExecutionPathW");

const CHARSTRING *delegate_load_source_w = W("LoadSourceW");
const CHARSTRING *delegate_load_source_c = W("LoadSourceC");

Expand All @@ -75,20 +81,23 @@ class netcore
virtual bool start() = 0;
virtual void stop() = 0;

bool load_source(wchar_t *source);
bool load_source(char *source);
bool execution_path(const wchar_t *path);
bool execution_path(const char *path);

bool load_source(const wchar_t *source);
bool load_source(const char *source);

bool load_files(wchar_t **source, size_t size);
bool load_files(char **source, size_t size);
bool load_files(const wchar_t **source, size_t size);
bool load_files(const char **source, size_t size);

bool load_assembly(wchar_t *source);
bool load_assembly(char *source);
bool load_assembly(const wchar_t *source);
bool load_assembly(const char *source);

execution_result *execute(char *function);
execution_result *execute(wchar_t *function);
execution_result *execute(const char *function);
execution_result *execute(const wchar_t *function);

execution_result *execute_with_params(char *function, parameters *params);
execution_result *execute_with_params(wchar_t *function, parameters *params);
execution_result *execute_with_params(const char *function, parameters *params);
execution_result *execute_with_params(const wchar_t *function, parameters *params);

bool create_delegates();

Expand Down
12 changes: 7 additions & 5 deletions source/loaders/cs_loader/include/cs_loader/simple_netcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,19 @@ typedef char source_file[512];

netcore_handle simple_netcore_create(char *dotnet_root, char *dotnet_loader_assembly_path);

reflect_function *simple_netcore_get_functions(netcore_handle, int *);
reflect_function *simple_netcore_get_functions(netcore_handle handle, int *count);

int simple_netcore_load_script_from_files(netcore_handle handle, char *files[MAX_FILES], size_t size);
int simple_netcore_load_script_from_files(netcore_handle handle, const char *files[MAX_FILES], size_t size);

int simple_netcore_load_script_from_assembly(netcore_handle handle, char *file);
int simple_netcore_execution_path(netcore_handle handle, const char *path);

int simple_netcore_load_script_from_assembly(netcore_handle handle, const char *file);

int simple_netcore_load_script_from_memory(netcore_handle handle, const char *buffer, size_t size);

execution_result *simple_netcore_invoke(netcore_handle, const char *);
execution_result *simple_netcore_invoke(netcore_handle handle, const char *func);

void simple_netcore_destroy(netcore_handle);
void simple_netcore_destroy(netcore_handle handle);

execution_result *simple_netcore_invoke_with_params(netcore_handle handle, const char *func, parameters *params);

Expand Down
12 changes: 11 additions & 1 deletion source/loaders/cs_loader/netcore/source/MetacallEntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ public unsafe static bool LoadFromPointer(string[] source)
}
}

public static bool ExecutionPathC([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]string path)
{
return loader.ExecutionPath(path);
}

public static bool ExecutionPathW([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]string path)
{
return loader.ExecutionPath(path);
}

public static bool Load(string source)
{
try {
Expand All @@ -61,7 +71,7 @@ public static bool Load(string source)
public static bool Load(string[] files)
{
try {
return loader.LoadFromSourceFunctions(files.Select(x => System.IO.File.ReadAllText(x)).ToArray());
return loader.LoadFromFileFunctions(files);
} catch (Exception ex) {
// TODO: Implement error handling
log.Error(ex.Message, ex);
Expand Down
73 changes: 71 additions & 2 deletions source/loaders/cs_loader/netcore/source/Providers/LoaderBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ protected LoaderBase(ILog log)
this.log = log;
}

public bool ExecutionPath(string path)
{
if (!paths.Contains(path))
{
log.Info("Loading execution path: " + path);
paths.Add(path);
return true;
}

return false;
}

public ReflectFunction[] Functions()
{
return this.functions.Select(x => x.Value.GetReflectFunction()).ToArray();
Expand All @@ -35,6 +47,65 @@ protected virtual IEnumerable<string> AdditionalLibs()

protected abstract Assembly MakeAssembly(MemoryStream stream);

private static bool IsFullPath(string path)
{
// https://stackoverflow.com/a/47569899
if (string.IsNullOrWhiteSpace(path) || path.IndexOfAny(Path.GetInvalidPathChars()) != -1 || !Path.IsPathRooted(path))
return false;

string pathRoot = Path.GetPathRoot(path);
if (pathRoot.Length <= 2 && pathRoot != "/") // Accepts X:\ and \\UNC\PATH, rejects empty string, \ and X:, but accepts / to support Linux
return false;

if (pathRoot[0] != '\\' || pathRoot[1] != '\\')
return true; // Rooted and not a UNC path

return pathRoot.Trim('\\').IndexOf('\\') != -1; // A UNC server name without a share name (e.g "\\NAME" or "\\NAME\") is invalid
}

private string LoadFromFileFunctionsRelative(string file)
{
foreach (var path in paths)
{
try
{
return System.IO.File.ReadAllText(Path.Combine(path, file));
}
catch (Exception ex)
{
continue;
}
}

throw new Exception("File " + file + " not found");
}

public bool LoadFromFileFunctions(string[] files)
{
List<string> sources = new List<string>();

foreach (var file in files)
{
try
{
sources.Add(IsFullPath(file) ? System.IO.File.ReadAllText(file) : LoadFromFileFunctionsRelative(file));
}
catch (Exception ex)
{
this.log.Error("CSLoader loading error: " + ex.Message);
return false;
}
}

if (files.Length != sources.Count)
{
this.log.Error("Not all files could be loaded (" + sources.Count + "/" + files.Length + ")");
return false;
}

return LoadFromSourceFunctions(sources.ToArray());
}

public bool LoadFromSourceFunctions(string[] source)
{
Assembly assembly = null;
Expand Down Expand Up @@ -102,8 +173,6 @@ public bool LoadFromSourceFunctions(string[] source)

public void LoadFunctions(Assembly assembly)
{
this.log.Info("CSLoader load functions");

foreach (var item in assembly.DefinedTypes.SelectMany(x => x.GetMethods()).Where(x => x.IsStatic))
{
var con = new FunctionContainer(item);
Expand Down
7 changes: 7 additions & 0 deletions source/loaders/cs_loader/netcore/source/Providers/LoaderV2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class LoaderV2 : LoaderBase
{
public LoaderV2(ILog log) : base(log)
{
//This handler is called only when the common language runtime tries to bind to the assembly and fails
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(AssemblyResolveEventHandler);
AppDomain.CurrentDomain.TypeResolve += new ResolveEventHandler(AssemblyResolveEventHandler);
}
Expand Down Expand Up @@ -39,12 +40,18 @@ private Assembly AssemblyResolveEventHandler(object sender, ResolveEventArgs arg
log.Error("Invalid Assembly.LoadFile: " + fullPath);
}
}
catch (FileNotFoundException)
{
continue;
}
catch (Exception ex)
{
log.Error(string.Format("Exception when loading the Assembly {0}: {1}", assemName.Name, ex.Message), ex);
}
}

log.Error("Assembly not found: " + assemName.Name);

return asm;
}

Expand Down
Loading

0 comments on commit 8a3e90a

Please sign in to comment.