void CopyFromBuffer(IILGen ilGenerator, int bufferIdx, int skFieldIdx, ref BufferInfo bi, Dictionary <int, MemorizedPositionWithLength> outOfOrderPKParts, List <TableFieldInfo> pks, IList <FieldId> skFields, IILLocal positionLoc, IILLocal memoPositionLoc, Action <IILGen> pushWriter) { for (var idx = bi.ActualFieldIdx; idx < skFieldIdx; idx++) { var field = skFields[idx]; if (field.IsFromPrimaryKey) { outOfOrderPKParts[(int)field.Index] = SkipWithMemorizing(bufferIdx, ilGenerator, bi.PushReader, pks[(int)field.Index].Handler, positionLoc); } else { var f = ClientRelationVersionInfo.GetSecondaryKeyField((int)field.Index); f.Handler.Skip(ilGenerator, bi.PushReader); } } var skField = skFields[skFieldIdx]; GenerateCopyFieldFromByteBufferToWriterIl(ilGenerator, pks[(int)skField.Index].Handler, bi.PushReader, pushWriter, positionLoc, memoPositionLoc); bi.ActualFieldIdx = skFieldIdx + 1; }
internal Action <IInternalObjectDBTransaction, AbstractBufferedWriter, object, object> GetSecondaryKeysKeySaver (uint secondaryKeyIndex, string name) { return(_secondaryKeysSavers.GetOrAdd(secondaryKeyIndex, idx => CreateSaverWithApartFields(ClientRelationVersionInfo.GetSecondaryKeyFields(secondaryKeyIndex), $"Relation_{Name}_SK_{name}_KeySaver"))); }
Action <byte[], byte[], AbstractBufferedWriter> CreatePrimaryKeyFromSKDataMerger(uint secondaryKeyIndex, int paramFieldCountInFirstBuffer, string mergerName) { var method = ILBuilder.Instance.NewMethod <Action <byte[], byte[], AbstractBufferedWriter> >(mergerName); var ilGenerator = method.Generator; Action <IILGen> pushWriter = il => il.Ldarg(2); var skFields = ClientRelationVersionInfo.SecondaryKeys[secondaryKeyIndex].Fields; var positionLoc = ilGenerator.DeclareLocal(typeof(ulong)); //stored position var memoPositionLoc = ilGenerator.DeclareLocal(typeof(IMemorizedPosition)); var firstBuffer = new BufferInfo(); var secondBuffer = new BufferInfo { ActualFieldIdx = paramFieldCountInFirstBuffer }; var outOfOrderPKParts = new Dictionary <int, MemorizedPositionWithLength>(); //index -> bufferIdx, IMemorizedPosition, length var pks = ClientRelationVersionInfo.GetPrimaryKeyFields().ToList(); for (var pkIdx = 0; pkIdx < pks.Count; pkIdx++) { if (outOfOrderPKParts.ContainsKey(pkIdx)) { var memo = outOfOrderPKParts[pkIdx]; var pushReader = GetBufferPushAction(memo.BufferIndex, firstBuffer.PushReader, secondBuffer.PushReader); CopyFromMemorizedPosition(ilGenerator, pushReader, pushWriter, memo, memoPositionLoc); continue; } int bufferIdx, skFieldIdx; FindPosition(pkIdx, skFields, paramFieldCountInFirstBuffer, out bufferIdx, out skFieldIdx); if (bufferIdx == 0) { MergerInitializeFirstBufferReader(ilGenerator, ref firstBuffer); CopyFromBuffer(ilGenerator, bufferIdx, skFieldIdx, ref firstBuffer, outOfOrderPKParts, pks, skFields, positionLoc, memoPositionLoc, pushWriter); } else { MergerInitializeBufferReader(ilGenerator, ref secondBuffer, 1); CopyFromBuffer(ilGenerator, bufferIdx, skFieldIdx, ref secondBuffer, outOfOrderPKParts, pks, skFields, positionLoc, memoPositionLoc, pushWriter); } } ilGenerator.Ret(); return(method.Create()); }
void CalculateSecondaryKey(IInternalObjectDBTransaction tr, IList <KeyValuePair <uint, SecondaryKeyInfo> > indexes) { var keyWriter = new ByteBufferWriter(); var enumeratorType = typeof(RelationEnumerator <>).MakeGenericType(_clientType); keyWriter.WriteByteArrayRaw(ObjectDB.AllRelationsPKPrefix); keyWriter.WriteVUInt32(Id); var enumerator = (IEnumerator)Activator.CreateInstance(enumeratorType, tr, this, keyWriter.GetDataAndRewind().ToAsyncSafe(), new SimpleModificationCounter()); var keySavers = new Action <IInternalObjectDBTransaction, AbstractBufferedWriter, object> [indexes.Count]; for (int i = 0; i < indexes.Count; i++) { keySavers[i] = CreateSaver(ClientRelationVersionInfo.GetSecondaryKeyFields(indexes[i].Key), $"Relation_{Name}_Upgrade_SK_{indexes[i].Value.Name}_KeySaver"); } while (enumerator.MoveNext()) { var obj = enumerator.Current; tr.TransactionProtector.Start(); tr.KeyValueDBTransaction.SetKeyPrefix(ObjectDB.AllRelationsSKPrefix); for (int i = 0; i < indexes.Count; i++) { keyWriter.WriteVUInt32(Id); keyWriter.WriteVUInt32(indexes[i].Key); keySavers[i](tr, keyWriter, obj); var keyBytes = keyWriter.GetDataAndRewind(); if (!tr.KeyValueDBTransaction.CreateOrUpdateKeyValue(keyBytes, ByteBuffer.NewEmpty())) { throw new BTDBException("Internal error, secondary key bytes must be always unique."); } } } }
public RelationInfo(uint id, string name, IRelationInfoResolver relationInfoResolver, Type interfaceType, Type clientType, IInternalObjectDBTransaction tr) { _id = id; _name = name; _relationInfoResolver = relationInfoResolver; _interfaceType = interfaceType; _clientType = clientType; ClientRelationVersionInfo = CreateVersionInfoByReflection(); LoadVersionInfos(tr.KeyValueDBTransaction); ApartFields = FindApartFields(interfaceType, ClientRelationVersionInfo); if (LastPersistedVersion > 0 && RelationVersionInfo.Equal(_relationVersions[LastPersistedVersion], ClientRelationVersionInfo)) { _relationVersions[LastPersistedVersion] = ClientRelationVersionInfo; ClientTypeVersion = LastPersistedVersion; } else { ClientTypeVersion = LastPersistedVersion + 1; _relationVersions.Add(ClientTypeVersion, ClientRelationVersionInfo); var writerk = new ByteBufferWriter(); writerk.WriteByteArrayRaw(ObjectDB.RelationVersionsPrefix); writerk.WriteVUInt32(_id); writerk.WriteVUInt32(ClientTypeVersion); var writerv = new ByteBufferWriter(); ClientRelationVersionInfo.Save(writerv); tr.KeyValueDBTransaction.SetKeyPrefix(ByteBuffer.NewEmpty()); tr.KeyValueDBTransaction.CreateOrUpdateKeyValue(writerk.Data, writerv.Data); if (LastPersistedVersion > 0) { CheckThatPrimaryKeyHasNotChanged(name, ClientRelationVersionInfo, _relationVersions[LastPersistedVersion]); UpdateSecondaryKeys(tr, ClientRelationVersionInfo, _relationVersions[LastPersistedVersion]); } } _typeConvertorGenerator = tr.Owner.TypeConvertorGenerator; }