private unsafe string MarshalAndFreeRocksDbString(IntPtr resultPtr, long resultLength, Encoding encoding)
        {
            var result = CurrentFramework.CreateString((sbyte *)resultPtr.ToPointer(), 0, (int)resultLength, encoding);

            rocksdb_free(resultPtr);
            return(result);
        }
        private unsafe int Comparator_Compare(IntPtr state, IntPtr a, UIntPtr alen, IntPtr b, UIntPtr blen)
        {
            var getComparatorPtr = (*((ComparatorState *)state)).GetComparatorPtr;
            var getComparator    = CurrentFramework.GetDelegateForFunctionPointer <GetComparator>(getComparatorPtr);
            var comparator       = getComparator();

            return(comparator.Compare(a, alen, b, blen));
        }
            public static T LoadFunc <T>(INativeLibImporter importer, IntPtr libraryHandle, string entryPoint)
            {
                IntPtr procAddress = importer.GetProcAddress(libraryHandle, entryPoint);

                if (procAddress == IntPtr.Zero)
                {
                    throw new NativeLoadException(string.Format("Unable to get address of {0} ({1})", entryPoint, typeof(T)), null);
                }
                return(CurrentFramework.GetDelegateForFunctionPointer <T>(procAddress));
            }
Beispiel #4
0
 public unsafe ComparatorBase(string name = null, IntPtr state = default(IntPtr))
 {
     Name     = name ?? GetType().FullName;
     _destroy = s => this.Destroy(s);
     Handle   = Native.Instance.rocksdb_comparator_create(
         state: IntPtr.Zero,
         destructor: CurrentFramework.GetFunctionPointerForDelegate(_destroy),
         compare: CurrentFramework.GetFunctionPointerForDelegate <CompareFunc>(Compare),
         getName: CurrentFramework.GetFunctionPointerForDelegate <GetNameFunc>(GetName)
         );
 }
        /// <summary>
        /// Returns true if a particular target runtime is available.
        /// </summary>
        /// <param name="framework">The framework being sought</param>
        /// <returns>True if it's available, false if not</returns>
        public static bool IsAvailable(RuntimeFramework framework)
        {
            switch (framework.Runtime)
            {
            case RuntimeType.Mono:
                return(IsMonoInstalled());

            case RuntimeType.Net:
                return(CurrentFramework.Matches(framework) || IsDotNetInstalled(framework.Version));

            default:
                return(false);
            }
        }
Beispiel #6
0
        /// <summary>
        /// REQUIRES: The client must provide a merge operator if Merge operation
        /// needs to be accessed. Calling Merge on a DB without a merge operator
        /// would result in Status::NotSupported. The client must ensure that the
        /// merge operator supplied here has the same name and *exactly* the same
        /// semantics as the merge operator provided to previous open calls on
        /// the same DB. The only exception is reserved for upgrade, where a DB
        /// previously without a merge operator is introduced to Merge operation
        /// for the first time. It's necessary to specify a merge operator when
        /// openning the DB in this case.
        /// Default: nullptr
        /// </summary>
        public ColumnFamilyOptions SetMergeOperator(MergeOperator mergeOperator)
        {
            // Allocate some memory for the name bytes
            var name      = mergeOperator.Name ?? mergeOperator.GetType().FullName;
            var nameBytes = Encoding.UTF8.GetBytes(name + "\0");
            var namePtr   = Marshal.AllocHGlobal(nameBytes.Length);

            Marshal.Copy(nameBytes, 0, namePtr, nameBytes.Length);

            // Hold onto a reference to everything that needs to stay alive
            MergeOperatorRef = new MergeOperatorReferences
            {
                GetMergeOperator     = () => mergeOperator,
                DestructorDelegate   = MergeOperator_Destroy,
                NameDelegate         = MergeOperator_GetNamePtr,
                DeleteValueDelegate  = MergeOperator_DeleteValue,
                FullMergeDelegate    = MergeOperator_FullMerge,
                PartialMergeDelegate = MergeOperator_PartialMerge,
            };

            // Allocate the state
            var state = new MergeOperatorState
            {
                NamePtr             = namePtr,
                GetMergeOperatorPtr = CurrentFramework.GetFunctionPointerForDelegate <GetMergeOperator>(MergeOperatorRef.GetMergeOperator)
            };
            var statePtr = Marshal.AllocHGlobal(Marshal.SizeOf(state));

            Marshal.StructureToPtr(state, statePtr, false);

            // Create the merge operator
            IntPtr handle = Native.Instance.rocksdb_mergeoperator_create(
                state: statePtr,
                destructor: MergeOperatorRef.DestructorDelegate,
                delete_value: MergeOperatorRef.DeleteValueDelegate,
                full_merge: MergeOperatorRef.FullMergeDelegate,
                partial_merge: MergeOperatorRef.PartialMergeDelegate,
                name: MergeOperatorRef.NameDelegate
                );

            return(SetMergeOperator(handle));
        }
        /// <summary>
        /// Comparator used to define the order of keys in the table.
        /// Default: a comparator that uses lexicographic byte-wise ordering
        ///
        /// REQUIRES: The client must ensure that the comparator supplied
        /// here has the same name and orders keys *exactly* the same as the
        /// comparator provided to previous open calls on the same DB.
        /// </summary>
        public ColumnFamilyOptions SetComparator(Comparator comparator)
        {
            // Allocate some memory for the name bytes
            var name      = comparator.Name ?? comparator.GetType().FullName;
            var nameBytes = Encoding.UTF8.GetBytes(name + "\0");
            var namePtr   = Marshal.AllocHGlobal(nameBytes.Length);

            Marshal.Copy(nameBytes, 0, namePtr, nameBytes.Length);

            // Hold onto a reference to everything that needs to stay alive
            ComparatorRef = new ComparatorReferences
            {
                GetComparator      = () => comparator,
                CompareDelegate    = Comparator_Compare,
                DestructorDelegate = Comparator_Destroy,
                NameDelegate       = Comparator_GetNamePtr,
            };

            // Allocate the state
            var state = new ComparatorState
            {
                NamePtr          = namePtr,
                GetComparatorPtr = CurrentFramework.GetFunctionPointerForDelegate <GetComparator>(ComparatorRef.GetComparator)
            };
            var statePtr = Marshal.AllocHGlobal(Marshal.SizeOf(state));

            Marshal.StructureToPtr(state, statePtr, false);

            // Create the comparator
            IntPtr handle = Native.Instance.rocksdb_comparator_create(
                state: statePtr,
                destructor: ComparatorRef.DestructorDelegate,
                compare: ComparatorRef.CompareDelegate,
                name: ComparatorRef.NameDelegate
                );

            return(SetComparator(handle));
        }
        /// <summary>
        /// Executes a multi_get with automatic marshalling
        /// </summary>
        /// <param name="db"></param>
        /// <param name="read_options"></param>
        /// <param name="keys"></param>
        /// <param name="numKeys">when non-zero, specifies the number of keys in the array to fetch</param>
        /// <param name="keyLengths">when non-null specifies the lengths of each key to fetch</param>
        /// <param name="errptrs">when non-null, must be an array that will be populated with error codes</param>
        /// <param name="values">when non-null is a pre-allocated array to put the resulting values in</param>
        /// <param name="cf"></param>
        /// <returns></returns>
        public unsafe KeyValuePair <string, string>[] rocksdb_multi_get(
            IntPtr db,
            IntPtr read_options,
            string[] keys,
            IntPtr[] errptrs,
            ulong numKeys = 0,
            KeyValuePair <string, string>[] values = null,
            ColumnFamilyHandle[] cf = null,
            Encoding encoding       = null)
        {
            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }
            int count = numKeys == 0 ? keys.Length : (int)numKeys;

            IntPtr[] keyPtrs    = new IntPtr[count];
            var      keyLengths = new ulong[count];

            IntPtr[] valuePtrs    = new IntPtr[count];
            ulong[]  valueLengths = new ulong[count];

            if (values == null)
            {
                values = new KeyValuePair <string, string> [count];
            }
            if (errptrs == null)
            {
                errptrs = new IntPtr[count];
            }

            // first we have to encode each key
            for (int i = 0; i < count; i++)
            {
                var key = keys[i];
                fixed(char *k = key)
                {
                    var klength  = key.Length;
                    int bklength = encoding.GetByteCount(k, klength);
                    var bk       = Marshal.AllocHGlobal(bklength);

                    encoding.GetBytes(k, klength, (byte *)bk.ToPointer(), bklength);
                    keyPtrs[i]    = bk;
                    keyLengths[i] = (ulong)bklength;
                }
            }
            if (cf == null)
            {
                rocksdb_multi_get(db, read_options, (ulong)count, keyPtrs, keyLengths, valuePtrs, valueLengths, errptrs);
            }
            else
            {
                IntPtr[] cfhs = new IntPtr[cf.Length];
                for (int i = 0; i < count; i++)
                {
                    cfhs[i] = cf[i].Handle;
                }
                rocksdb_multi_get_cf(db, read_options, cfhs, (ulong)count, keyPtrs, keyLengths, valuePtrs, valueLengths, errptrs);
            }
            // free the buffers allocated for each encoded key
            foreach (var keyPtr in keyPtrs)
            {
                Marshal.FreeHGlobal(keyPtr);
            }

            // now marshal all of the values
            for (int i = 0; i < count; i++)
            {
                var resultPtr = valuePtrs[i];
                if (resultPtr != IntPtr.Zero)
                {
                    var bv       = (sbyte *)resultPtr.ToPointer();
                    var bvLength = valueLengths[i];
                    values[i] = new KeyValuePair <string, string>(keys[i], CurrentFramework.CreateString(bv, 0, (int)bvLength, encoding));
                    rocksdb_free(resultPtr);
                }
                else
                {
                    values[i] = new KeyValuePair <string, string>(keys[i], null);
                }
            }
            return(values);
        }
 private unsafe string MarshalString(IntPtr resultPtr, long resultLength, Encoding encoding)
 {
     return(CurrentFramework.CreateString((sbyte *)resultPtr.ToPointer(), 0, (int)resultLength, encoding));
 }
Beispiel #10
0
        public static T Import <T>(INativeLibImporter importer, string libName, string version, bool suppressUnload) where T : class
        {
            var subdir = GetArchName(RuntimeInformation.ProcessArchitecture);

            var    assemblyName    = new AssemblyName("DynamicLink");
            var    assemblyBuilder = CurrentFramework.DefineDynamicAssembly(assemblyName, System.Reflection.Emit.AssemblyBuilderAccess.Run);
            var    moduleBuilder   = assemblyBuilder.DefineDynamicModule("DynLinkModule");
            string typeName        = typeof(T).Name + "_impl";
            var    typeBuilder     = moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout, typeof(T));

            FieldBuilder field_importer      = typeBuilder.DefineField("importer", typeof(INativeLibImporter), FieldAttributes.Private | FieldAttributes.InitOnly);
            FieldBuilder field_libraryHandle = typeBuilder.DefineField("libraryHandle", typeof(IntPtr), FieldAttributes.Private | FieldAttributes.InitOnly);

            var methods = typeof(T).GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.IsAbstract && !m.IsGenericMethod).ToArray();

            // Define delegate types for each of the method signatures
            var delegateMap = new Dictionary <string, Type>();

            foreach (var method in methods)
            {
                var sig = GetMethodSig(method);
                if (delegateMap.ContainsKey(sig))
                {
                    continue;
                }
                var delegateTypeInfo = CreateDelegateType(moduleBuilder, method);
                delegateMap.Add(sig, delegateTypeInfo.AsType());
            }

            // Define one field for each method to hold a delegate
            var delegates = methods.Select(m => new {
                MethodInfo   = m,
                DelegateType = delegateMap[GetMethodSig(m)],
            }).ToArray();
            var fields = delegates.Select((d, i) => typeBuilder.DefineField($"{d.MethodInfo.Name}_func_{i}", d.DelegateType, FieldAttributes.Private)).ToArray();

            // Create the constructor which will initialize the importer and library handle
            // and also use the importer to populate each of the delegate fields
            ConstructorBuilder constructor = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { typeof(INativeLibImporter), typeof(IntPtr) });

            {
                var         baseConstructor = typeof(T).GetTypeInfo().GetConstructors().Where(con => con.GetParameters().Length == 0).First();
                ILGenerator il = constructor.GetILGenerator();

                // Call base constructor
                il.Emit(OpCodes.Ldarg_0); // this
                il.Emit(OpCodes.Call, baseConstructor);

                // Store importer field
                il.Emit(OpCodes.Ldarg_0); // this
                il.Emit(OpCodes.Ldarg_1); // importer
                il.Emit(OpCodes.Stfld, field_importer);

                // Load and store library handle
                il.Emit(OpCodes.Ldarg_0); // this
                il.Emit(OpCodes.Ldarg_2); // library handle
                il.Emit(OpCodes.Stfld, field_libraryHandle);

                var getDelegateMethod = typeof(INativeLibImporter).GetTypeInfo().GetMethod("GetDelegate");
                // Initialize each delegate field
                for (int i = 0; i < fields.Length; i++)
                {
                    var delegateType = delegates[i].DelegateType;

                    il.Emit(OpCodes.Ldarg_0);                                                                // this

                    il.Emit(OpCodes.Ldarg_1);                                                                // importer
                    il.Emit(OpCodes.Ldarg_0);                                                                // this
                    il.Emit(OpCodes.Ldfld, field_libraryHandle);
                    il.Emit(OpCodes.Ldstr, delegates[i].MethodInfo.Name);                                    // use method name from original class as entry point
                    il.Emit(OpCodes.Ldtoken, delegateType);                                                  // the delegate type
                    il.Emit(OpCodes.Call, typeof(System.Type).GetTypeInfo().GetMethod("GetTypeFromHandle")); // typeof()
                    il.Emit(OpCodes.Callvirt, getDelegateMethod);                                            // importer.GetDelegate()
                    il.Emit(OpCodes.Isinst, delegateType);                                                   // as <delegate type>
                    il.Emit(OpCodes.Stfld, fields[i]);
                }

                // End of constructor
                il.Emit(OpCodes.Ret);
            }

            // Create destructor
            var destructor = typeBuilder.DefineMethod("Finalize", MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig);

            {
                var baseDestructor = typeof(T).GetTypeInfo().GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance);
                var il             = destructor.GetILGenerator();
                var end            = il.DefineLabel();

                il.BeginExceptionBlock();
                if (!suppressUnload)
                {
                    il.Emit(OpCodes.Ldarg_0);                                                                     // this
                    il.Emit(OpCodes.Ldfld, field_importer);                                                       // .importer
                    il.Emit(OpCodes.Ldarg_0);                                                                     // this
                    il.Emit(OpCodes.Ldfld, field_libraryHandle);                                                  // .libraryHandle
                    il.Emit(OpCodes.Callvirt, typeof(INativeLibImporter).GetTypeInfo().GetMethod("FreeLibrary")); // INativeLibImporter::FreeLibrary()
                }
                //il.Emit(OpCodes.Leave, end);
                il.BeginFinallyBlock();
                il.Emit(OpCodes.Ldarg_0);              // this
                il.Emit(OpCodes.Call, baseDestructor); // object::Finalize()
                //il.Emit(OpCodes.Endfinally);
                il.EndExceptionBlock();
                il.MarkLabel(end);
                il.Emit(OpCodes.Ret);
            }

            // Now override each method from the base class
            for (int i = 0; i < fields.Length; i++)
            {
                var baseMethod = delegates[i].MethodInfo;
                var args       = baseMethod.GetParameters();
                var omethod    = typeBuilder.DefineMethod(
                    baseMethod.Name,
                    (baseMethod.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.NewSlot)) | MethodAttributes.Virtual,
                    baseMethod.CallingConvention,
                    baseMethod.ReturnType,
                    args.Select(arg => arg.ParameterType).ToArray()
                    );
                var il = omethod.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);          // this
                il.Emit(OpCodes.Ldfld, fields[i]); // {field}
                if (args.Length >= 1)
                {
                    il.Emit(OpCodes.Ldarg_1);
                }
                if (args.Length >= 2)
                {
                    il.Emit(OpCodes.Ldarg_2);
                }
                if (args.Length >= 3)
                {
                    il.Emit(OpCodes.Ldarg_3);
                }
                for (short argNum = 4; argNum <= args.Length; argNum++)
                {
                    il.Emit(OpCodes.Ldarg_S, argNum);
                }
                il.Emit(OpCodes.Tailcall);
                il.Emit(OpCodes.Callvirt, delegates[i].DelegateType.GetTypeInfo().GetMethod("Invoke"));
                il.Emit(OpCodes.Ret);
            }

            var type = typeBuilder.CreateTypeInfo();

            var versionParts = version.Split('.');
            var names        = versionParts.Select((p, i) => libName + "-" + string.Join(".", versionParts.Take(i + 1)))
                               .Reverse()
                               .Concat(Enumerable.Repeat(libName, 1));

            // try to load locally
            var paths = new[]
            {
                Path.Combine("native", subdir),
                "native",
                subdir,
                "",
            };

            // If the RocksDbNative package is referenced, then dynamically load it here so that it can tell us where the native libraries are
            string nativeCodeBase = null;

            try
            {
                var nativeLibName     = new AssemblyName("RocksDbNative");
                var native            = Assembly.Load(nativeLibName);
                var nativePkgClass    = native.GetTypes().First(t => t.FullName == "RocksDbSharp.NativePackage");
                var getCodeBaseMethod = nativePkgClass.GetTypeInfo().GetMethod("GetCodeBase");
                var getCodeBase       = getCodeBaseMethod.CreateDelegate <Func <string> >();
                nativeCodeBase = getCodeBase();
            }
            catch (Exception)
            {
            }

            var basePaths = new string[] {
                nativeCodeBase,
                Path.GetDirectoryName(UriToPath(Transitional.CurrentFramework.GetBaseDirectory())),
                Path.GetDirectoryName(UriToPath(Assembly.GetEntryAssembly()?.CodeBase)),
                Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location),
                Path.GetDirectoryName(UriToPath(typeof(PosixImporter).GetTypeInfo().Assembly.CodeBase)),
                Path.GetDirectoryName(typeof(PosixImporter).GetTypeInfo().Assembly.Location),
            };
            var search = basePaths
                         .Where(p => p != null)
                         .Distinct()
                         .SelectMany(basePath =>
                                     paths.SelectMany(path => names.Select(n => Path.Combine(basePath, path, importer.Translate(n))))
                                     .Concat(names.Select(n => importer.Translate(n)))
                                     )
                         .Select(path => new SearchPath {
                Path = path
            })
                         .ToArray();

            foreach (var spec in search)
            {
                var    construct = type.GetConstructor(new Type[] { typeof(INativeLibImporter), typeof(IntPtr) });
                IntPtr lib       = IntPtr.Zero;
                try
                {
                    lib = importer.LoadLibrary(spec.Path);
                    if (lib == IntPtr.Zero)
                    {
                        throw new NativeLoadException("LoadLibrary returned 0", null);
                    }
                }
                catch (TargetInvocationException tie)
                {
                    spec.Error = tie.InnerException;
                    continue;
                }
                catch (Exception e)
                {
                    spec.Error = e;
                    continue;
                }
                var obj = construct.Invoke(new object[] { importer, lib });
                var t   = obj as T;
                return(t);
            }

            throw new NativeLoadException("Unable to locate rocksdb native library, either install it, or use RocksDbNative nuget package\nSearched:\n" + string.Join("\n", search.Select(s => $"{s.Path}: ({s.Error.GetType().Name}) {s.Error.Message}")), null);
        }
Beispiel #11
0
        private static MergeOperator GetMergeOperatorFromPtr(IntPtr getMergeOperatorPtr)
        {
            var getMergeOperator = CurrentFramework.GetDelegateForFunctionPointer <GetMergeOperator>(getMergeOperatorPtr);

            return(getMergeOperator());
        }