Esempio n. 1
0
        public RelationEnumerator(IInternalObjectDBTransaction tr, RelationInfo relationInfo, byte[] keyBytes,
                                  IRelationModificationCounter modificationCounter, int loaderIndex)
        {
            _transaction = tr;

            ItemLoader             = relationInfo.ItemLoaderInfos[loaderIndex];
            _keyValueTr            = _transaction.KeyValueDBTransaction;
            _prevProtectionCounter = _keyValueTr.CursorMovedCounter;

            KeyBytes             = keyBytes;
            _modificationCounter = modificationCounter;
            _pos        = 0;
            _seekNeeded = true;
            _prevModificationCounter = _modificationCounter.ModificationCounter;
        }
Esempio n. 2
0
        public RelationEnumerator(IInternalObjectDBTransaction tr, RelationInfo relationInfo, ByteBuffer keyBytes)
        {
            RelationInfo = relationInfo;
            _tr          = tr;

            _keyValueTr            = _tr.KeyValueDBTransaction;
            _keyValueTrProtector   = _tr.TransactionProtector;
            _prevProtectionCounter = _keyValueTrProtector.ProtectionCounter;

            KeyBytes = keyBytes;
            _keyValueTr.SetKeyPrefix(KeyBytes);
            _pos        = 0;
            _seekNeeded = true;
            _prevModificationCounter = relationInfo.ModificationCounter;
        }
Esempio n. 3
0
        public RelationEnumerator(IInternalObjectDBTransaction tr, RelationInfo relationInfo, ByteBuffer keyBytes,
                                  IRelationModificationCounter modificationCounter, int loaderIndex)
        {
            RelationInfo = relationInfo;
            Transaction  = tr;

            ItemLoader             = relationInfo.ItemLoaderInfos[loaderIndex];
            _keyValueTr            = Transaction.KeyValueDBTransaction;
            _keyValueTrProtector   = Transaction.TransactionProtector;
            _prevProtectionCounter = _keyValueTrProtector.ProtectionCounter;

            KeyBytes             = keyBytes;
            _modificationCounter = modificationCounter;
            _keyValueTrProtector.Start();
            _keyValueTr.SetKeyPrefix(KeyBytes);
            _pos        = 0;
            _seekNeeded = true;
            _prevModificationCounter = _modificationCounter.ModificationCounter;
        }
Esempio n. 4
0
        IDictionary <string, FieldBuilder> DefineProperties(RelationInfo relationInfo, IILDynamicType classImpl,
                                                            Type createdType)
        {
            var apartFields = new Dictionary <string, FieldBuilder>();
            var methods     = createdType.GetMethods();

            foreach (var method in methods)
            {
                var name = method.Name;
                if (!name.StartsWith("get_") && !name.StartsWith("set_"))
                {
                    continue;
                }
                FieldBuilder field;
                var          propName = method.Name.Substring(4);

                if (!relationInfo.ApartFields.ContainsKey(propName))
                {
                    throw new BTDBException($"Invalid property name {propName}.");
                }

                if (!apartFields.TryGetValue(propName, out field))
                {
                    apartFields[propName] = field = classImpl.DefineField("_" + propName, method.ReturnType,
                                                                          FieldAttributes.Private);
                }
                var reqMethod = classImpl.DefineMethod(method.Name, method.ReturnType,
                                                       method.GetParameters().Select(pi => pi.ParameterType).ToArray(),
                                                       MethodAttributes.Virtual | MethodAttributes.Public);

                if (method.Name.StartsWith("get_"))
                {
                    reqMethod.Generator.Ldarg(0).Ldfld(field).Ret();
                }
                else if (method.Name.StartsWith("set_"))
                {
                    reqMethod.Generator.Ldarg(0).Ldarg(1).Stfld(field).Ret();
                }
                classImpl.DefineMethodOverride(reqMethod, method);
            }
            return(apartFields);
        }
Esempio n. 5
0
        internal RelationInfo CreateByName(IInternalObjectDBTransaction tr, string name, Type interfaceType,
                                           RelationBuilder builder)
        {
            name = string.Intern(name);
            if (!_name2Id.TryGetValue(name, out var id))
            {
                id             = _freeId++;
                _name2Id[name] = id;
                var nameWriter = new SpanWriter();
                nameWriter.WriteBlock(ObjectDB.RelationNamesPrefix);
                nameWriter.WriteString(name);
                var idWriter = new SpanWriter();
                idWriter.WriteVUInt32(id);
                tr.KeyValueDBTransaction.CreateOrUpdateKeyValue(nameWriter.GetSpan(), idWriter.GetSpan());
            }

            if (_id2Relation.TryGetValue(id, out var relation))
            {
                throw new BTDBException($"Relation with name '{name}' was already initialized");
            }
            relation         = new RelationInfo(id, name, builder, tr);
            _id2Relation[id] = relation;
            return(relation);
        }
Esempio n. 6
0
 public RelationPrimaryKeyEnumerator(IInternalObjectDBTransaction tr, RelationInfo relationInfo,
                                     ByteBuffer keyBytes, IRelationModificationCounter modificationCounter, int loaderIndex)
     : base(tr, relationInfo, keyBytes, modificationCounter, loaderIndex)
 {
     _skipBytes = relationInfo.Prefix.Length;
 }
Esempio n. 7
0
        static Func <IObjectDBTransaction, T1> BuildRelationCreatorInstance <T1>(Type classImplType, string relationName, RelationInfo relationInfo)
        {
            var methodBuilder = ILBuilder.Instance.NewMethod("RelationFactory" + relationName, typeof(Func <IObjectDBTransaction, T1>), typeof(RelationInfo));
            var ilGenerator   = methodBuilder.Generator;

            ilGenerator
            .Ldarg(1)
            .Ldarg(0)
            .Newobj(classImplType.GetConstructor(new[] { typeof(IObjectDBTransaction), typeof(RelationInfo) }))
            .Castclass(typeof(T1))
            .Ret();
            return((Func <IObjectDBTransaction, T1>)methodBuilder.Create(relationInfo));
        }
Esempio n. 8
0
 public RelationBuilder(RelationInfo relationInfo)
 {
     _relationInfo = relationInfo;
 }
Esempio n. 9
0
 public RelationDBManipulator(IObjectDBTransaction transation, RelationInfo relationInfo)
 {
     _transaction  = (IInternalObjectDBTransaction)transation;
     _relationInfo = relationInfo;
 }
Esempio n. 10
0
 public RelationPrimaryKeyEnumerator(IInternalObjectDBTransaction tr, RelationInfo relationInfo, ByteBuffer keyBytes,
                                     RelationDBManipulator <T> manipulator)
     : base(tr, relationInfo, keyBytes, manipulator)
 {
     _skipBytes = relationInfo.Prefix.Length;
 }
Esempio n. 11
0
        public Func <IObjectDBTransaction, T> Build(string relationName, Type relationDBManipulatorType)
        {
            var interfaceType     = typeof(T);
            var classImpl         = ILBuilder.Instance.NewType("Relation" + relationName, relationDBManipulatorType, new[] { interfaceType });
            var constructorMethod = classImpl.DefineConstructor(new[] { typeof(IObjectDBTransaction), typeof(RelationInfo) });
            var il = constructorMethod.Generator;

            // super.ctor(transaction, relationInfo);
            il.Ldarg(0).Ldarg(1).Ldarg(2).Call(relationDBManipulatorType.GetConstructor(new[] { typeof(IObjectDBTransaction), typeof(RelationInfo) }))
            .Ret();
            GenerateApartFieldsProperties(classImpl, interfaceType);
            var methods = RelationInfo.GetMethods(interfaceType);

            foreach (var method in methods)
            {
                if (method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))
                {
                    continue;
                }
                var reqMethod = classImpl.DefineMethod("_R_" + method.Name, method.ReturnType,
                                                       method.GetParameters().Select(pi => pi.ParameterType).ToArray(), MethodAttributes.Virtual | MethodAttributes.Public);
                if (method.Name.StartsWith("RemoveBy"))
                {
                    if (method.Name == "RemoveByIdPartial")
                    {
                        BuildRemoveByIdPartialMethod(method, reqMethod, relationDBManipulatorType);
                    }
                    else
                    {
                        BuildRemoveByMethod(method, reqMethod, relationDBManipulatorType);
                    }
                }
                else if (method.Name.StartsWith("FindBy"))
                {
                    BuildFindByMethod(method, reqMethod, relationDBManipulatorType);
                }
                else if (method.Name == "Contains")
                {
                    BuildContainsMethod(method, reqMethod, relationDBManipulatorType);
                }
                else if (method.Name == "ListById") //list by primary key
                {
                    BuildListByIdMethod(method, reqMethod);
                }
                else if (method.Name.StartsWith("ListBy", StringComparison.Ordinal)) //ListBy{Name}(tenantId, .., AdvancedEnumeratorParam)
                {
                    BuildListByMethod(method, reqMethod);
                }
                else if (method.Name == "Insert")
                {
                    BuildInsertMethod(method, reqMethod, relationDBManipulatorType);
                }
                else
                {
                    BuildManipulatorCallWithSameParameters(method, reqMethod, relationDBManipulatorType);
                }
                reqMethod.Generator.Ret();
                classImpl.DefineMethodOverride(reqMethod, method);
            }
            var classImplType = classImpl.CreateType();

            return(BuildRelationCreatorInstance <T>(classImplType, relationName, _relationInfo));
        }
Esempio n. 12
0
 public RelationDBManipulator(IObjectDBTransaction transation, RelationInfo relationInfo)
 {
     _transaction         = (IInternalObjectDBTransaction)transation;
     _relationInfo        = relationInfo;
     _modificationCounter = _transaction.GetRelationModificationCounter(relationInfo.Id);
 }
Esempio n. 13
0
        public Func <IObjectDBTransaction, T> Build(string relationName, Type relationDBManipulatorType)
        {
            var interfaceType     = typeof(T);
            var classImpl         = ILBuilder.Instance.NewType("Relation" + relationName, relationDBManipulatorType, new[] { interfaceType });
            var constructorMethod = classImpl.DefineConstructor(new[] { typeof(IObjectDBTransaction), typeof(RelationInfo) });
            var il = constructorMethod.Generator;

            // super.ctor(transaction, relationInfo);
            il.Ldarg(0).Ldarg(1).Ldarg(2).Call(relationDBManipulatorType.GetConstructor(new[] { typeof(IObjectDBTransaction), typeof(RelationInfo) }))
            .Ret();
            GenerateApartFieldsProperties(classImpl, interfaceType);
            var methods = RelationInfo.GetMethods(interfaceType);

            foreach (var method in methods)
            {
                if (method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))
                {
                    continue;
                }
                var reqMethod = classImpl.DefineMethod("_R_" + method.Name, method.ReturnType,
                                                       method.GetParameters().Select(pi => pi.ParameterType).ToArray(), MethodAttributes.Virtual | MethodAttributes.Public);
                if (method.Name.StartsWith("RemoveBy") || method.Name.StartsWith("FindBy") || method.Name == "Contains")
                {
                    SaveKeyBytesAndCallMethod(reqMethod.Generator, relationDBManipulatorType, method.Name,
                                              method.GetParameters(), method.ReturnType, _relationInfo.ApartFields);
                }
                else if (method.Name == "ListById") //list by primary key
                {
                    var parameters        = method.GetParameters();
                    var advEnumParamOrder = (ushort)parameters.Length;
                    var advEnumParam      = parameters[advEnumParamOrder - 1].ParameterType;
                    var advEnumParamType  = advEnumParam.GenericTypeArguments[0];

                    var emptyBufferLoc   = reqMethod.Generator.DeclareLocal(typeof(ByteBuffer));
                    var prefixParamCount = method.GetParameters().Length - 1;

                    var field = _relationInfo.ClientRelationVersionInfo.GetPrimaryKeyFields()
                                .Skip(_relationInfo.ApartFields.Count + prefixParamCount).First();

                    reqMethod.Generator
                    .Ldarg(0);
                    SavePKListPrefixBytes(reqMethod.Generator, method.Name,
                                          method.GetParameters(), _relationInfo.ApartFields);
                    reqMethod.Generator
                    .LdcI4(prefixParamCount + _relationInfo.ApartFields.Count)
                    .Ldarg(advEnumParamOrder).Ldfld(advEnumParam.GetField("Order"))
                    .Ldarg(advEnumParamOrder).Ldfld(advEnumParam.GetField("StartProposition"));
                    FillBufferWhenNotIgnoredKeyPropositionIl(advEnumParamOrder, field, emptyBufferLoc,
                                                             advEnumParam.GetField("Start"), reqMethod.Generator);
                    reqMethod.Generator
                    .Ldarg(advEnumParamOrder).Ldfld(advEnumParam.GetField("EndProposition"));
                    FillBufferWhenNotIgnoredKeyPropositionIl(advEnumParamOrder, field, emptyBufferLoc,
                                                             advEnumParam.GetField("End"), reqMethod.Generator);

                    if (typeof(IEnumerator <>).MakeGenericType(_relationInfo.ClientType).IsAssignableFrom(method.ReturnType))
                    {
                        //return new RelationAdvancedEnumerator<T>(relationManipulator,
                        //    prefixBytes, prefixFieldCount,
                        //    order,
                        //    startKeyProposition, startKeyBytes,
                        //    endKeyProposition, endKeyBytes, secondaryKeyIndex);
                        var enumType = typeof(RelationAdvancedEnumerator <>).MakeGenericType(_relationInfo.ClientType);
                        var advancedEnumeratorCtor = enumType.GetConstructors()[0];
                        reqMethod.Generator.Newobj(advancedEnumeratorCtor);
                    }
                    else if (typeof(IOrderedDictionaryEnumerator <,>).MakeGenericType(advEnumParamType, _relationInfo.ClientType)
                             .IsAssignableFrom(method.ReturnType))
                    {
                        reqMethod.Generator
                        .LdcI4(1);     //init key reader

                        //return new RelationAdvancedOrderedEnumerator<T>(relationManipulator,
                        //    prefixBytes, prefixFieldCount,
                        //    order,
                        //    startKeyProposition, startKeyBytes,
                        //    endKeyProposition, endKeyBytes, secondaryKeyIndex, initKeyReader);
                        var enumType = typeof(RelationAdvancedOrderedEnumerator <,>).MakeGenericType(advEnumParamType, _relationInfo.ClientType);
                        var advancedEnumeratorCtor = enumType.GetConstructors()[0];
                        reqMethod.Generator.Newobj(advancedEnumeratorCtor);
                    }
                    else
                    {
                        throw new BTDBException("Invalid method " + method.Name);
                    }
                }
                else if (method.Name.StartsWith("ListBy", StringComparison.Ordinal)) //ListBy{Name}(tenantId, .., AdvancedEnumeratorParam)
                {
                    var parameters        = method.GetParameters();
                    var advEnumParamOrder = (ushort)parameters.Length;
                    var advEnumParam      = parameters[advEnumParamOrder - 1].ParameterType;
                    var advEnumParamType  = advEnumParam.GenericTypeArguments[0];

                    var emptyBufferLoc    = reqMethod.Generator.DeclareLocal(typeof(ByteBuffer));
                    var secondaryKeyIndex = _relationInfo.ClientRelationVersionInfo.GetSecondaryKeyIndex(method.Name.Substring(6));
                    var prefixParamCount  = method.GetParameters().Length - 1;

                    var field = _relationInfo.ClientRelationVersionInfo.GetSecondaryKeyFields(secondaryKeyIndex)
                                .Skip(_relationInfo.ApartFields.Count + prefixParamCount).First();

                    reqMethod.Generator
                    .Ldarg(0);
                    SaveListPrefixBytes(secondaryKeyIndex, reqMethod.Generator, method.Name,
                                        method.GetParameters(), _relationInfo.ApartFields);
                    reqMethod.Generator
                    .LdcI4(prefixParamCount + _relationInfo.ApartFields.Count)
                    .Ldarg(advEnumParamOrder).Ldfld(advEnumParam.GetField("Order"))
                    .Ldarg(advEnumParamOrder).Ldfld(advEnumParam.GetField("StartProposition"));
                    FillBufferWhenNotIgnoredKeyPropositionIl(advEnumParamOrder, field,
                                                             emptyBufferLoc, advEnumParam.GetField("Start"), reqMethod.Generator);
                    reqMethod.Generator
                    .Ldarg(advEnumParamOrder).Ldfld(advEnumParam.GetField("EndProposition"));
                    FillBufferWhenNotIgnoredKeyPropositionIl(advEnumParamOrder, field,
                                                             emptyBufferLoc, advEnumParam.GetField("End"), reqMethod.Generator);
                    reqMethod.Generator
                    .LdcI4((int)secondaryKeyIndex);

                    if (typeof(IEnumerator <>).MakeGenericType(_relationInfo.ClientType).IsAssignableFrom(method.ReturnType))
                    {
                        //return new RelationAdvancedSecondaryKeyEnumerator<T>(relationManipulator,
                        //    prefixBytes, prefixFieldCount,
                        //    order,
                        //    startKeyProposition, startKeyBytes,
                        //    endKeyProposition, endKeyBytes, secondaryKeyIndex);
                        var enumType = typeof(RelationAdvancedSecondaryKeyEnumerator <>).MakeGenericType(_relationInfo.ClientType);
                        var advancedEnumeratorCtor = enumType.GetConstructors()[0];
                        reqMethod.Generator.Newobj(advancedEnumeratorCtor);
                    }
                    else if (typeof(IOrderedDictionaryEnumerator <,>).MakeGenericType(advEnumParamType, _relationInfo.ClientType)
                             .IsAssignableFrom(method.ReturnType))
                    {
                        //return new RelationAdvancedOrderedSecondaryKeyEnumerator<T>(relationManipulator,
                        //    prefixBytes, prefixFieldCount,
                        //    order,
                        //    startKeyProposition, startKeyBytes,
                        //    endKeyProposition, endKeyBytes, secondaryKeyIndex);
                        var enumType = typeof(RelationAdvancedOrderedSecondaryKeyEnumerator <,>).MakeGenericType(advEnumParamType, _relationInfo.ClientType);
                        var advancedEnumeratorCtor = enumType.GetConstructors()[0];
                        reqMethod.Generator.Newobj(advancedEnumeratorCtor);
                    }
                    else
                    {
                        throw new BTDBException("Invalid method " + method.Name);
                    }
                }
                else if (method.Name == "Insert")
                {
                    var  methodInfo = relationDBManipulatorType.GetMethod(method.Name);
                    bool returningBoolVariant;
                    var  returnType = method.ReturnType;
                    if (returnType == typeof(void))
                    {
                        returningBoolVariant = false;
                    }
                    else if (returnType == typeof(bool))
                    {
                        returningBoolVariant = true;
                    }
                    else
                    {
                        throw new BTDBException("Method Insert should be defined with void or bool return type.");
                    }
                    var methodParams = method.GetParameters();
                    CheckParameterCount(method.Name, 1, methodParams.Length);
                    CheckParameterType(method.Name, 0, methodInfo.GetParameters()[0].ParameterType, methodParams[0].ParameterType);
                    reqMethod.Generator
                    .Ldarg(0)     //this
                    .Ldarg(1)
                    .Callvirt(methodInfo);
                    if (!returningBoolVariant)
                    {
                        var returnedTrueLabel = reqMethod.Generator.DefineLabel("returnedTrueLabel");
                        reqMethod.Generator
                        .Brtrue(returnedTrueLabel)
                        .Ldstr("Trying to insert duplicate key.")
                        .Newobj(() => new BTDBException(null))
                        .Throw()
                        .Mark(returnedTrueLabel);
                    }
                }
                else //call the same method name with the same parameters
                {
                    var methodParams = method.GetParameters();
                    int paramCount   = methodParams.Length;
                    var methodInfo   = relationDBManipulatorType.GetMethod(method.Name);
                    if (methodInfo == null)
                    {
                        throw new BTDBException($"Method {method} is not supported.");
                    }
                    CheckReturnType(method.Name, methodInfo.ReturnType, method.ReturnType);
                    var calledMethodParams = methodInfo.GetParameters();
                    CheckParameterCount(method.Name, calledMethodParams.Length, methodParams.Length);
                    for (int i = 0; i < methodParams.Length; i++)
                    {
                        CheckParameterType(method.Name, i, calledMethodParams[i].ParameterType, methodParams[i].ParameterType);
                    }
                    for (ushort i = 0; i <= paramCount; i++)
                    {
                        reqMethod.Generator.Ldarg(i);
                    }
                    reqMethod.Generator.Callvirt(methodInfo);
                }
                reqMethod.Generator.Ret();
                classImpl.DefineMethodOverride(reqMethod, method);
            }
            var classImplType = classImpl.CreateType();

            return(BuildRelationCreatorInstance <T>(classImplType, relationName, _relationInfo));
        }
Esempio n. 14
0
        public RelationAdvancedEnumerator(
            RelationDBManipulator <T> manipulator,
            ByteBuffer prefixBytes, uint prefixFieldCount,
            EnumerationOrder order,
            KeyProposition startKeyProposition, ByteBuffer startKeyBytes,
            KeyProposition endKeyProposition, ByteBuffer endKeyBytes)
        {
            _prefixFieldCount = prefixFieldCount;
            _manipulator      = manipulator;

            _ascending = order == EnumerationOrder.Ascending;

            _tr                    = manipulator.Transaction;
            _keyValueTr            = _tr.KeyValueDBTransaction;
            _keyValueTrProtector   = _tr.TransactionProtector;
            _prevProtectionCounter = _keyValueTrProtector.ProtectionCounter;

            _keyBytes = prefixBytes;
            _keyValueTr.SetKeyPrefix(_keyBytes);

            _relationInfo            = manipulator.RelationInfo;
            _prevModificationCounter = _relationInfo.ModificationCounter;

            long startIndex;
            long endIndex;

            if (endKeyProposition == KeyProposition.Ignored)
            {
                endIndex = _keyValueTr.GetKeyValueCount() - 1;
            }
            else
            {
                switch (_keyValueTr.Find(endKeyBytes))
                {
                case FindResult.Exact:
                    endIndex = _keyValueTr.GetKeyIndex();
                    if (endKeyProposition == KeyProposition.Excluded)
                    {
                        endIndex--;
                    }
                    break;

                case FindResult.Previous:
                    endIndex = _keyValueTr.GetKeyIndex();
                    break;

                case FindResult.Next:
                    endIndex = _keyValueTr.GetKeyIndex() - 1;
                    break;

                case FindResult.NotFound:
                    endIndex = -1;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            if (startKeyProposition == KeyProposition.Ignored)
            {
                startIndex = 0;
            }
            else
            {
                switch (_keyValueTr.Find(startKeyBytes))
                {
                case FindResult.Exact:
                    startIndex = _keyValueTr.GetKeyIndex();
                    if (startKeyProposition == KeyProposition.Excluded)
                    {
                        startIndex++;
                    }
                    break;

                case FindResult.Previous:
                    startIndex = _keyValueTr.GetKeyIndex() + 1;
                    break;

                case FindResult.Next:
                    startIndex = _keyValueTr.GetKeyIndex();
                    break;

                case FindResult.NotFound:
                    startIndex = 0;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
            _count                 = (uint)Math.Max(0, endIndex - startIndex + 1);
            _startPos              = (uint)(_ascending ? startIndex : endIndex);
            _pos                   = 0;
            _seekNeeded            = true;
            _lengthOfNonDataPrefix = ObjectDB.AllRelationsPKPrefix.Length + PackUnpack.LengthVUInt(manipulator.RelationInfo.Id);
        }