예제 #1
0
        public static IterateResult RunUnorderedWorkload(IList src, int smalllist, int dop, Func <object, int, int, object[], object> body)
#pragma warning restore IDE0060 // Remove unused parameter
        {
            int idx = 0;
            List <Exception> errors = new();
            List <object>    data   = new();

            if (src.Count <= smalllist)
            {
                foreach (var a in src)
                {
                    try
                    {
                        var lidx = Interlocked.Add(ref idx, 1);
                        var d    = body.Invoke(a, lidx - 1, src.Count - lidx, Array.Empty <object>());

                        lock (data)
                        {
                            data.Add(d);
                        }
                    }
                    catch (Exception ex)
                    {
                        errors.Add(ex);
                    }
                }
            }
            else
            {
                var ss = CEF.CurrentServiceScope;

                _ = Parallel.ForEach(src.Cast <object>(), (a) =>
                {
                    try
                    {
                        using (CEF.UseServiceScope(ss))
                        {
                            var lidx = Interlocked.Add(ref idx, 1);
                            var d    = body.Invoke(a, lidx - 1, src.Count - lidx, Array.Empty <object>());

                            lock (data)
                            {
                                data.Add(d);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        lock (errors)
                        {
                            errors.Add(ex);
                        }
                    }
                });
            }

            return(new IterateResult(data.ToArray(), errors.ToArray()));
        }
예제 #2
0
 string IDataErrorInfo.this[string columnName]
 {
     get
     {
         using (CEF.UseServiceScope(_initScope))
         {
             return(_errorSource?[columnName]);
         }
     }
 }
예제 #3
0
        public static void RunWorkloadFunctions(params Action[] args)
        {
            var ss = CEF.CurrentServiceScope;

            Parallel.ForEach(args, (a) =>
            {
                using (CEF.UseServiceScope(ss))
                {
                    a.Invoke();
                }
            });
        }
예제 #4
0
        protected override object AddNewCore()
        {
            using (CEF.UseServiceScope(OwningScope))
            {
                // We rely on construction of a new DynamicBindable that has the same shape as the first item in the collection, if any exist
                if (this.Any())
                {
                    var f   = this.First();
                    var wot = f.Wrapped?.GetWrappedObject()?.GetType();

                    if (wot != null)
                    {
                        var no  = Activator.CreateInstance(wot);
                        var wno = CEF.IncludeObject(no, ObjectState.Added);
                        var nod = wno.AsDynamicBindable();
                        base.Add(nod);
                        return(nod);
                    }
                }

                // If none exist, need to rely on the "default schema" provided
                if (BaseItemType != null)
                {
                    var no  = Activator.CreateInstance(BaseItemType);
                    var wno = CEF.IncludeObject(no, ObjectState.Added);
                    var iw  = wno.AsInfraWrapped();
                    var nod = wno.AsDynamicBindable();

                    if (ExternalSchema != null)
                    {
                        foreach (var e in ExternalSchema)
                        {
                            if (!iw.HasProperty(e.Key))
                            {
                                iw.SetValue(e.Key, null, e.Value);
                            }
                        }
                    }

                    base.Add(nod);
                    return(nod);
                }

                // No default schema? It's an error situation.
                throw new InvalidOperationException("Cannot add a new item to the GenericBindableSet collection since there's no object definition available.");
            }
        }
예제 #5
0
        protected override void RemoveItem(int index)
        {
            var i = this[index];

            RemoveTracking(new DynamicBindable[] { this[index] });
            base.RemoveItem(index);

            using (CEF.UseServiceScope(OwningScope))
            {
                var uw = i.Wrapped;

                if (uw != null)
                {
                    CEF.DeleteObject(uw);
                }
            }

            SetDirty();
        }
예제 #6
0
            public override void SetValue(object component, object value)
            {
                using (CEF.UseServiceScope(_ss))
                {
                    DynamicWithBag iw = null;

                    if (component is DynamicBindable db)
                    {
                        iw = db.Wrapped;
                    }

                    if (iw == null)
                    {
                        iw = _iw;
                    }

                    iw.SetValue(_name, value, _dt);
                }
            }
예제 #7
0
            public override void ResetValue(object component)
            {
                using (CEF.UseServiceScope(_ss))
                {
                    DynamicWithBag iw = null;

                    if (component is DynamicBindable db)
                    {
                        iw = db.Wrapped;
                    }

                    if (iw == null)
                    {
                        iw = _iw;
                    }

                    iw.SetValue(_name, iw.GetOriginalValue(_name, false), _dt);
                }
            }
예제 #8
0
        public static void RunWorkloadFunctions(bool ordered, params Action[] args)
        {
            if (ordered)
            {
                foreach (var a in args)
                {
                    a.Invoke();
                }
            }
            else
            {
                var ss = CEF.CurrentServiceScope;

                Parallel.ForEach(args, (a) =>
                {
                    using (CEF.UseServiceScope(ss))
                    {
                        a.Invoke();
                    }
                });
            }
        }
예제 #9
0
            public override object GetValue(object component)
            {
                using (CEF.UseServiceScope(_ss))
                {
                    DynamicWithBag iw = null;

                    if (component is DynamicBindable db)
                    {
                        iw = db.Wrapped;
                    }

                    if (iw == null)
                    {
                        iw = _iw;
                    }

                    if (iw.HasProperty(_name))
                    {
                        return(iw.GetValue(_name));
                    }
                    return(null);
                }
            }
예제 #10
0
        public static void Benchmark1(int total_parents, List <long> testTimes, List <long> testTimes2, ref int rowcount, ref int rowcount2)
        {
            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();

            using (CEF.NewServiceScope())
            {
                var people = new EntitySet <PersonWrapped>();

                for (int parentcnt = 1; parentcnt <= total_parents; ++parentcnt)
                {
                    var parent = new PersonWrapped()
                    {
                        Name = $"NP{parentcnt}", Age = (parentcnt % 60) + 20, Gender = (parentcnt % 2) == 0 ? "F" : "M"
                    };

                    parent.Phones.Add(new Phone()
                    {
                        Number = "888-7777", PhoneTypeID = PhoneType.Mobile
                    });
                    parent.Phones.Add(new Phone()
                    {
                        Number = "777-6666", PhoneTypeID = PhoneType.Work
                    });

                    if ((parentcnt % 12) == 0)
                    {
                        CEF.NewObject(new Phone()
                        {
                            Number = "666-5555", PhoneTypeID = PhoneType.Home
                        });
                    }
                    else
                    {
                        parent.Phones.Add(new Phone()
                        {
                            Number = "777-6666", PhoneTypeID = PhoneType.Home
                        });
                    }

                    rowcount += 4;

                    for (int childcnt = 1; childcnt <= (parentcnt % 4); ++childcnt)
                    {
                        var child = CEF.NewObject(new PersonWrapped()
                        {
                            Name   = $"NC{parentcnt}{childcnt}",
                            Age    = parent.Age - 20,
                            Gender = (parentcnt % 2) == 0 ? "F" : "M"
                            ,
                            Phones = new Phone[] { new Phone()
                                                   {
                                                       Number = "999-8888", PhoneTypeID = PhoneType.Mobile
                                                   } }
                        });

                        parent.Kids.Add(child);
                        rowcount += 2;
                    }

                    people.Add(parent);
                }

                CEF.DBSave();
            }

            testTimes.Add(watch.ElapsedMilliseconds);
            watch.Restart();

            // For purposes of benchmarking, treat this as a completely separate operation
            using (var ss = CEF.NewServiceScope())
            {
                // For everyone who's a parent of at least 30 yo, if at least 2 children of same sex, remove work phone, increment age
                var people = new EntitySet <Person>().DBRetrieveSummaryForParents(30);

                Parallel.ForEach((from a in people let d = a.AsDynamic() where d.MaleChildren > 1 || d.FemaleChildren > 1 select a).ToList(), (p) =>
                {
                    using (CEF.UseServiceScope(ss))
                    {
                        p.Age += 1;

                        var phones = new EntitySet <Phone>().DBRetrieveByOwner(p.PersonID, PhoneType.Work);

                        if (phones.Any())
                        {
                            CEF.DeleteObject(phones.First());
                        }
                    }
                });

                rowcount2 += CEF.DBSave().Count();
            }

            watch.Stop();
            testTimes2.Add(watch.ElapsedMilliseconds);
        }
예제 #11
0
        public static void Benchmark3SavePer(int total_parents, List <long> testTimes, List <long> testTimes2, ref int rowcount, ref int rowcount2)
        {
            var watch = new System.Diagnostics.Stopwatch();

            watch.Start();
            long cnt1 = 0;

            var people = new EntitySet <PersonWrapped>();

            Parallel.For(1, total_parents + 1, (parentcnt) =>
            {
                using (CEF.NewServiceScope())
                {
                    var parent = CEF.NewObject(new PersonWrapped()
                    {
                        Name = $"NP{parentcnt}", Age = (parentcnt % 60) + 20, Gender = (parentcnt % 2) == 0 ? "F" : "M"
                    });

                    parent.Phones.Add(new Phone()
                    {
                        Number = "888-7777", PhoneTypeID = PhoneType.Mobile
                    });
                    parent.Phones.Add(new Phone()
                    {
                        Number = "777-6666", PhoneTypeID = PhoneType.Work
                    });

                    if ((parentcnt % 12) == 0)
                    {
                        CEF.NewObject(new Phone()
                        {
                            Number = "666-5555", PhoneTypeID = PhoneType.Home
                        });
                    }
                    else
                    {
                        parent.Phones.Add(new Phone()
                        {
                            Number = "777-6666", PhoneTypeID = PhoneType.Home
                        });
                    }

                    Interlocked.Add(ref cnt1, 4);

                    for (int childcnt = 1; childcnt <= (parentcnt % 4); ++childcnt)
                    {
                        var child = CEF.NewObject(new PersonWrapped()
                        {
                            Name   = $"NC{parentcnt}{childcnt}",
                            Age    = parent.Age - 20,
                            Gender = (parentcnt % 2) == 0 ? "F" : "M"
                            ,
                            Phones = new Phone[] { new Phone()
                                                   {
                                                       Number = "999-8888", PhoneTypeID = PhoneType.Mobile
                                                   } }
                        });

                        parent.Kids.Add(child);
                        Interlocked.Add(ref cnt1, 2);
                    }

                    CEF.DBSave();
                }
            });

            rowcount += (int)cnt1;
            testTimes.Add(watch.ElapsedMilliseconds);
            watch.Restart();
            long cnt2 = 0;

            // For purposes of benchmarking, treat this as a completely separate operation
            // For everyone who's a parent of at least 30 yo, if at least 2 children of same sex, remove work phone, increment age

            int?id = null;

            using (var ss = CEF.NewServiceScope())
            {
                var people2 = new EntitySet <Person>().DBRetrieveSummaryForParents(30);

                Parallel.ForEach((from a in people2 let d = a.AsDynamic() where d.MaleChildren > 1 || d.FemaleChildren > 1 select a).ToList(), (p) =>
                {
                    using (CEF.UseServiceScope(ss))
                    {
                        if (!id.HasValue)
                        {
                            id = p.PersonID;
                        }

                        p.AsInfraWrapped().SetValue(nameof(Person.Age), p.Age + 1);

                        var ph2 = new EntitySet <Phone>().DBRetrieveByOwner(p.PersonID, PhoneType.Work).FirstOrDefault();

                        if (ph2 != null)
                        {
                            CEF.DeleteObject(ph2);
                        }

                        p.DBSave();
                        Interlocked.Add(ref cnt2, 2);
                    }
                });

                // Simulate "later heavy read access"...
                for (int c = 0; c < 50000; ++c)
                {
                    var work = new EntitySet <Phone>().DBRetrieveByOwner(c + id.GetValueOrDefault(), PhoneType.Work).FirstOrDefault();

                    if (work != null && work.Number == "123")
                    {
                        MessageBox.Show("Found (should never!)");
                    }
                }
            }

            rowcount2 += (int)cnt2 + 50000;
            watch.Stop();

            testTimes2.Add(watch.ElapsedMilliseconds);
        }
예제 #12
0
        internal static void CopyParsePropertyValues(IDictionary <string, object?>?sourceProps, object target, bool isNew, ServiceScope?ss, IDictionary <object, object> visits, bool justTraverse)
        {
            // Can disable this to improve performance - default is enabled
            if (!Globals.DoCopyParseProperties)
            {
                return;
            }

            _propCache.TryGetValue(target.GetType(), out var dic);

            if (dic == null)
            {
                dic = (from a in target.FastGetAllProperties(true, true) select new { Name = a.name, PropertyType = a.type }).ToDictionary((p) => p.Name, (p) => p.PropertyType);
                _propCache[target.GetType()] = dic;
            }

            var iter = sourceProps == null ?
                       (from t in dic select(t.Key, target.FastGetValue(t.Key), t.Value))
                : (from s in sourceProps from t in dic where s.Key == t.Key select(s.Key, s.Value, t.Value));

            var maxdop = Globals.EnableParallelPropertyParsing && Environment.ProcessorCount > 4 && iter.Count() >= Environment.ProcessorCount ? Environment.ProcessorCount >> 2 : 1;

            Interlocked.Add(ref _copyNesting, maxdop);

            try
            {
                void a((string PropName, object SourceVal, Type TargPropType) info)
                {
                    object?wrapped = null;

                    if (ss != null && IsWrappableListType(info.TargPropType, info.SourceVal))
                    {
                        ICEFList?wrappedCol = null;

                        if (ss.Settings.InitializeNullCollections || info.SourceVal != null)
                        {
                            // This by definition represents CHILDREN
                            // Use an observable collection we control - namely EntitySet
                            wrappedCol = CreateWrappingList(ss, info.TargPropType, target, info.PropName);
                            target.FastSetValue(info.PropName, wrappedCol);
                        }
                        else
                        {
                            wrappedCol = info.SourceVal as ICEFList;
                        }

                        // Merge any existing data into the collection - as we do this, recursively construct wrappers!
                        if (info.SourceVal != null && wrappedCol != null)
                        {
                            // Based on the above type checks, we know this thing supports IEnumerable
                            var sValEnum = ((System.Collections.IEnumerable)info.SourceVal).GetEnumerator();

                            while (sValEnum.MoveNext())
                            {
                                if (visits.ContainsKey(sValEnum.Current))
                                {
                                    wrapped = visits[sValEnum.Current] ?? sValEnum.Current;
                                }
                                else
                                {
                                    wrapped = ss.InternalCreateAddBase(sValEnum.Current, isNew, null, null, null, visits, true, true);
                                }

                                if (wrapped != null)
                                {
                                    wrappedCol.AddWrappedItem(wrapped);
                                }
                            }
                        }

                        if (wrappedCol != null && (ss.Settings.InitializeNullCollections || info.SourceVal != null))
                        {
                            ((ISupportInitializeNotification)wrappedCol).EndInit();
                        }
                    }
                    else
                    {
                        // If the type is a ref type that we manage, then this property represents a PARENT and we should replace/track it (only if we have a PK for it: without one, can't be tracked)
                        if (ss != null && info.SourceVal != null)
                        {
                            var svt = info.SourceVal.GetType();

                            if (!_sourceValTypeOk.TryGetValue(svt, out bool svtok))
                            {
                                svtok = !svt.IsValueType && svt != typeof(string) && KeyService.ResolveKeyDefinitionForType(svt).Any();
                                _sourceValTypeOk[svt] = svtok;
                            }

                            if (svtok)
                            {
                                if (visits.ContainsKey(info.SourceVal))
                                {
                                    wrapped = visits[info.SourceVal] ?? info.SourceVal;
                                }
                                else
                                {
                                    var to = ss.GetTrackedByWrapperOrTarget(info.SourceVal);

                                    if (to == null)
                                    {
                                        wrapped = ss.InternalCreateAddBase(info.SourceVal, isNew, null, null, null, visits, true, true);
                                    }
                                    else
                                    {
                                        wrapped = to.GetWrapperTarget();
                                    }
                                }

                                if (wrapped != null)
                                {
                                    target.FastSetValue(info.PropName, wrapped);
                                }
                            }
                            else
                            {
                                if (!justTraverse)
                                {
                                    target.FastSetValue(info.PropName, info.SourceVal);
                                }
                            }
                        }
                        else
                        {
                            if (!justTraverse)
                            {
                                target.FastSetValue(info.PropName, info.SourceVal);
                            }
                        }
                    }
                }

                int resdop = Interlocked.Read(ref _copyNesting) > 12 ? 1 : maxdop;

                if (resdop == 1)
                {
                    foreach (var info in iter)
                    {
                        a(info);
                    }
                }
                else
                {
                    ss ??= CEF.CurrentServiceScope;

                    Parallel.ForEach(iter, new ParallelOptions()
                    {
                        MaxDegreeOfParallelism = resdop
                    }, (info) =>
                    {
                        using (CEF.UseServiceScope(ss))
                        {
                            a(info);
                        }
                    });
                }
            }
            finally
            {
                Interlocked.Add(ref _copyNesting, -maxdop);
            }
        }
        public void AddByQuery <T>(IEnumerable <T> list, string text, object[] parms = null, int?expirySeconds = null, CacheBehavior?mode = null) where T : class, new()
        {
            var ss = CEF.CurrentServiceScope;

            if (mode == null)
            {
                mode = ss.ResolvedCacheBehaviorForType(typeof(T));
            }

            if ((mode & CacheBehavior.QueryBased) == 0 && (mode & CacheBehavior.ConvertQueryToIdentity) != 0 && ((mode & CacheBehavior.ForAllDoesntConvertToIdentity) == 0 || string.Compare(text, "All", true) != 0))
            {
                // All we can do is for all list items, add to identity cache
                void act2()
                {
                    try
                    {
                        Interlocked.Increment(ref _working);

                        Parallel.ForEach(list, (i) =>
                        {
                            using (CEF.UseServiceScope(ss))
                            {
                                AddByIdentity <T>(i, expirySeconds: expirySeconds);
                            }
                        });
                    }
                    catch (Exception ex)
                    {
                        CEFDebug.WriteInfo($"Exception in cache serializer: {ex.Message}");
                    }
                    finally
                    {
                        Interlocked.Decrement(ref _working);
                    }
                }

                if (Globals.AsyncCacheUpdates)
                {
                    Task.Factory.StartNew(act2);
                }
                else
                {
                    act2();
                }

                return;
            }

            if ((mode & CacheBehavior.OnlyForAllQuery) != 0 && string.Compare(text, "All", true) != 0)
            {
                return;
            }

            StringBuilder sb = new StringBuilder(128);

            sb.Append(typeof(T).Name);
            sb.Append(text.ToUpperInvariant());

            if (parms != null)
            {
                foreach (var k in parms)
                {
                    sb.Append(k);
                }
            }

            string hash;

            using (SHA256Managed hasher = new SHA256Managed())
            {
                hash = Convert.ToBase64String(hasher.ComputeHash(Encoding.ASCII.GetBytes(sb.ToString())));
            }

            var c = _index.GetFirstByName(nameof(MFSEntry.ByQuerySHA), hash);

            if (!expirySeconds.HasValue)
            {
                expirySeconds = CEF.CurrentServiceScope.ResolvedCacheDurationForType(typeof(T));
            }

            var newExpDate = DateTime.Now.AddSeconds(expirySeconds.GetValueOrDefault(DefaultCacheIntervalSeconds));

            if (c == null)
            {
                c = new MFSEntry();

                if (list.Any())
                {
                    c.ObjectTypeName = list.First().GetBaseType().Name;
                }
                else
                {
                    c.ObjectTypeName = typeof(T).Name;
                }

                c.ByQuerySHA  = hash;
                c.FileName    = BuildNewFileName(typeof(T));
                c.QueryForAll = string.Compare(text, "All", true) == 0;
                _index.Add(c);
            }

            long current;

            lock (c.ObjSync)
            {
                current      = ++c.Sequence;
                c.ExpiryDate = newExpDate;
                c.SourceList = list;
                c.Active     = true;
            }

            void act()
            {
                try
                {
                    Interlocked.Increment(ref _working);

                    using (CEF.UseServiceScope(ss))
                    {
                        // Process all items in parallel, building a list we'll turn into json but also potentially caching "by identity" per row
                        ConcurrentBag <IDictionary <string, object> > rows = new ConcurrentBag <IDictionary <string, object> >();

                        var aiw = list.AllAsInfraWrapped().ToArray();

                        Parallel.ForEach(aiw, (iw) =>
                        {
                            using (CEF.UseServiceScope(ss))
                            {
                                rows.Add(iw.GetAllValues(true, true));

                                if ((mode & CacheBehavior.ConvertQueryToIdentity) != 0 && ((mode & CacheBehavior.ForAllDoesntConvertToIdentity) == 0 || string.Compare(text, "All", true) != 0))
                                {
                                    var uw = iw.AsUnwrapped() as T;

                                    if (uw != null)
                                    {
                                        AddByIdentity <T>(uw, expirySeconds: expirySeconds);
                                    }
                                }
                            }
                        });

                        lock (c.ObjSync)
                        {
                            if (c.Sequence == current)
                            {
                                c.Rows       = rows;
                                c.SourceList = null;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    CEFDebug.WriteInfo($"Exception in cache serializer: {ex.Message}");

                    // Invalidate the entry is probably the safest
                    c.Active     = false;
                    c.Properties = null;
                    c.Rows       = null;
                }
                finally
                {
                    Interlocked.Decrement(ref _working);
                }
            }

            if (Globals.AsyncCacheUpdates)
            {
                Task.Factory.StartNew(act);
            }
            else
            {
                act();
            }
        }