Ejemplo n.º 1
0
        public void CacheObjectWhenCPPChanges()
        {
            TestUtils.ResetLINQLibrary();
            // Make sure that when the C++ code changes, the cache key for lookup of results will also change.
            var q     = new QueriableDummy <ntup>();
            var i     = q.Select(e => DoItClass.DoIt(e.run)).Where(x => x > 2).Count();
            var query = DummyQueryExectuor.LastQueryModel;

            // Look for a hash value.
            var str1 = FormattingQueryVisitor.Format(query);

            Console.WriteLine(str1);
            var m = Regex.Match(str1, @"DoIt([^\(]+)");

            Assert.IsTrue(m.Success);
        }
Ejemplo n.º 2
0
            /// <summary>
            /// The main entry point that we watch - we generate a method info stub when we need it
            /// from this.
            /// </summary>
            /// <param name="queryModel"></param>
            public override void VisitQueryModel(QueryModel queryModel)
            {
                // If the type is something that is friendly to be returned from a
                // method, then we should cache this guy.

                _qmContextStack.Push(new QMContext());

                // Now, run through the query model.

                base.VisitQueryModel(queryModel);

                // And if the QM result type is something we can reasonably cache, then we should do it.
                //  - Do not cache the outter most QM. This guy has the best place to start combining things.
                //  - Do not cache anything that is enumerable. We'll have to deal with that later.
                //  - Do not cache any anonymous types
                //  - Deal with later somethign that is an iterator (used in a later loop).

                var isEnumerable   = typeof(IEnumerable).IsAssignableFrom(queryModel.GetResultType());
                var selectSequence = !queryModel.ResultOperators.Any();

                if (_qmContextStack.Count > 1 &&
                    ((selectSequence && isGoodSelectSequenceType(queryModel.GetResultType())) || !isEnumerable) &&
                    !queryModel.GetResultType().IsClass
                    )
                {
                    var qmText = FormattingQueryVisitor.Format(queryModel);
                    if (!FoundFunctions.Where(ff => ff.QMText == qmText).Any())
                    {
                        var sref = _qmContextStack.Peek();
                        var f    = new QMFuncHeader()
                        {
                            QM         = queryModel,
                            QMText     = qmText,
                            Arguments  = sref._arguments.Cast <object>(),
                            IsSequence = selectSequence
                        };
                        FoundFunctions.Add(f);
                    }
                }

                // Go back to working on the previous qm.
                _qmContextStack.Pop();
            }
Ejemplo n.º 3
0
        public void CacheWhenCPPChanges()
        {
            // Make sure that when the C++ code changes, the cache key for lookup of results will also change.
            var q   = new QueriableDummy <ntup>();
            var mym = new MyModifiableCode();

            mym.LOC = new string[] { "int i = 0;", "MultBy2 = 10;" };
            var i     = q.Select(e => mym.MultBy2(e.run)).Where(x => x > 2).Count();
            var query = DummyQueryExectuor.LastQueryModel;

            // Set the LOC to something.
            var str1 = FormattingQueryVisitor.Format(query);

            mym.LOC = new string[] { "int j = 10;", "MultBy2 = 10;" };
            var str2 = FormattingQueryVisitor.Format(query);

            Console.WriteLine(str1);
            Console.WriteLine(str2);
            Assert.AreNotEqual(str1, str2);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Return the key object
        /// </summary>
        /// <param name="rootfiles"></param>
        /// <param name="treename"></param>
        /// <param name="inputObjects"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        public IQueryResultCacheKey GetKey(Uri[] unsortedRootfiles, string treename, object[] inputObjects,
                                           string[] unsortedCrumbs,
                                           QueryModel query,
                                           bool recheckDates = false,
                                           Func <Uri, DateTime> dateChecker = null)
        {
            ///
            /// Quick check to make sure everything is good
            ///

            TraceHelpers.TraceInfo(23, "GetKey: Initial query calculation");
            if (unsortedRootfiles.Any(f => f == null))
            {
                throw new ArgumentException("one of the root files is null");
            }
            if (string.IsNullOrWhiteSpace(treename))
            {
                throw new ArgumentException("tree name must be valid");
            }
            if (inputObjects != null && inputObjects.Any(o => o == null))
            {
                throw new ArgumentException("one of the input objects is null - not allowed");
            }

            ///
            /// Build the hash, which is a bit of a pain in the butt.
            /// For the root files we don't care about the order given to us in or the order they
            /// are processed in. What we care about is what is there!
            ///

            var rootfiles = (from r in unsortedRootfiles
                             orderby r.OriginalString ascending
                             select r).ToArray();

            TraceHelpers.TraceInfo(24, "GetKey: Creating big string file name and calculating hash");
            int           fnameLength    = rootfiles.Select(f => f.OriginalString).Sum(w => w.Length) + 100;
            StringBuilder fullSourceName = new StringBuilder(fnameLength);

            foreach (var f in rootfiles)
            {
                fullSourceName.Append(f.OriginalString);
            }

            var fileHash = fullSourceName.ToString().GetHashCode();

            //
            // Next, the crumbs. They should also be sorted in order, and we will need
            // a hash code for them too.
            //

            string[] crumbs    = null;
            int      crumbHash = 0;

            if (unsortedCrumbs == null)
            {
                crumbs = new string[0];
            }
            else
            {
                crumbs = (from c in unsortedCrumbs orderby c select c).Distinct().ToArray();
                StringBuilder crumbString = new StringBuilder();
                foreach (var c in crumbs)
                {
                    crumbString.Append(c);
                }
                crumbHash = crumbString.ToString().GetHashCode();
            }

            ///
            /// Save the names of the files for a descriptor we will write out.
            ///

            KeyInfo result = new KeyInfo();

            TraceHelpers.TraceInfo(25, "GetKey: Saving description lines");
            result.DescriptionLines = (from f in rootfiles
                                       select f.OriginalString).ToArray();
            result.ExtraQueryInfoLines = crumbs;

            ///
            /// Text for the query. There are strings like "generated_x" where x is a number. These get incremented each time they are used,
            /// so to protect the caching we need to swap those out with a dummy.
            ///

            TraceHelpers.TraceInfo(26, "GetKey: Pretty printing the query");
            result.QueryText = FormattingQueryVisitor.Format(query);
            result.QueryText = result.QueryText.SwapOutWithUninqueString("\\<generated\\>_[0-9]+");

            ///
            /// And the directory name - we use the first name of the file.
            ///

            TraceHelpers.TraceInfo(27, "GetKey: Getting the cache directory");
            var fpathName = Path.GetFileNameWithoutExtension(rootfiles[0].PathAndQuery.SanitizedPathName(100));

            result.CacheDirectory = new DirectoryInfo(CacheDirectory.FullName + "\\" + fileHash + " - " + treename + "-" + fpathName);

            ///
            /// Scan the files that we are input and find the oldest one there
            ///

            TraceHelpers.TraceInfo(28, "GetKey: calculating the most recent file dates");
            result.OldestSourceFileDate = GetRecentFileDates(rootfiles, recheckDates, dateChecker).Max();

            ///
            /// And now the file that the query should be cached in
            ///

            TraceHelpers.TraceInfo(29, "GetKey: Calculating query hash");
            var queryHash = result.QueryText.GetHashCode();

            TraceHelpers.TraceInfo(30, "GetKey: Calculating the input object hash");
            var    inputObjectHash = CalcObjectHash(inputObjects);
            string queryNameBase   = string.Format(@"\\query {0}-inp{1}-crm{2}", queryHash.ToString(), inputObjectHash, crumbHash);

            result.RootFile = new FileInfo(result.CacheDirectory.FullName + queryNameBase + "_%%CYCLE%%.root");

            // And a complete unique hash string.
            result.UniqueHashString = $"files{fileHash.ToString()}-query{queryHash.ToString()}-objs{inputObjectHash}-crm{crumbHash}";

            TraceHelpers.TraceInfo(31, "GetKey: Done");
            return(result);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Return a QM function if we can find a list.
        /// </summary>
        /// <param name="queryModel"></param>
        /// <returns></returns>
        public IQMFunctionSource FindQMFunction(QueryModel queryModel)
        {
            var qmText = FormattingQueryVisitor.Format(queryModel);

            return(QMFunctions.Where(ff => ff.Matches(qmText)).FirstOrDefault());
        }