예제 #1
0
        /// <summary>
        /// Fetches an existing item from cache or null. IsAbsent is true when data was read from cache as an AbsentValue
        /// </summary>
        /// <typeparam name="TKey">Type of key</typeparam>
        /// <typeparam name="TResult">Type of the returned result value</typeparam>
        /// <param name="cache">Cache instance to operate on</param>
        /// <param name="key">Key to read</param>
        /// <param name="tblCache">Name of a cache table within a cache</param>
        /// <param name="caching">Caching options, or null for defaults</param>
        /// <param name="isAbsent">Returns true when value was found, but it is an AbsentValue instance</param>
        /// <returns>Cached reference type value, or null if not found or absent</returns>
        public static TResult FetchFrom <TKey, TResult>(this ICache cache,
                                                        TKey key,
                                                        string tblCache,
                                                        ICacheParams caching,
                                                        out bool isAbsent) where TResult : class
        {
            cache.NonNull(nameof(cache));

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            TResult result = null;

            isAbsent = false;

            if (caching.ReadCacheMaxAgeSec >= 0)
            {
                ICacheTable <TKey> tbl = cache.GetOrCreateTable <TKey>(tblCache);
                var cached             = tbl.Get(key, caching.ReadCacheMaxAgeSec);
                isAbsent = cached is AbsentValue;
                if (!isAbsent)
                {
                    result = cached as TResult;
                }
            }

            return(result);
        }
예제 #2
0
        /// <summary>
        /// Saves an item through cache: call the `fSave` functor synchronously then saves the result into cache table
        /// </summary>
        /// <typeparam name="TKey">Type of key</typeparam>
        /// <typeparam name="TData">Type of reference type value to save</typeparam>
        /// <typeparam name="TSaveResult">Type of save result</typeparam>
        /// <param name="cache">Cache to operate on</param>
        /// <param name="key">Key value</param>
        /// <param name="data">Reference type value to save. May not be null or AbsentValue</param>
        /// <param name="tblCache">The name of a cache table</param>
        /// <param name="caching">Caching options, or null for default</param>
        /// <param name="fSave">Synchronous functor that performs backend save</param>
        /// <returns>A result of the call to `fSave` functor</returns>
        public static TSaveResult SaveThrough <TKey, TData, TSaveResult>(this ICache cache,
                                                                         TKey key,
                                                                         TData data,
                                                                         string tblCache,
                                                                         ICacheParams caching,
                                                                         Func <TKey, TData, TSaveResult> fSave) where TData : class
        {
            cache.NonNull(nameof(cache));

            if (data == null || data is AbsentValue)
            {
                throw new DataAccessException(StringConsts.ARGUMENT_ERROR + "{0}(data ==null || is AbsentValue)".Args(nameof(SaveThrough)));
            }

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            var result = fSave.NonNull(nameof(fSave))(key, data);

            var wAge = caching.WriteCacheMaxAgeSec;

            if (wAge >= 0)
            {
                var tbl = cache.GetOrCreateTable <TKey>(tblCache);
                tbl.Put(key, data, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
            }

            return(result);
        }
예제 #3
0
 /// <summary>
 /// Assigns caching parameters to this query from  anotherICacheParams
 /// </summary>
 public void AssignCaching(ICacheParams cache)
 {
     if (cache == null)
     {
         return;
     }
     ReadCacheMaxAgeSec  = cache.ReadCacheMaxAgeSec;
     WriteCacheMaxAgeSec = cache.WriteCacheMaxAgeSec;
     WriteCachePriority  = cache.WriteCachePriority;
     CacheAbsentData     = cache.CacheAbsentData;
 }
예제 #4
0
        protected virtual GraphNode DoGetNode(GDID gNode, ICacheParams cacheParams = null)
        {
            var row = Cache.FetchThrough(gNode,
                                         SocialConsts.GS_NODE_TBL,
                                         cacheParams,
                                         gdid => loadNodeRow(gNode));

            if (row == null)
            {
                return(new GraphNode());
            }

            return(new GraphNode(row.Node_Type,
                                 row.GDID,
                                 row.G_OriginShard,
                                 row.G_Origin,
                                 row.Origin_Name,
                                 row.Origin_Data,
                                 row.Create_Date.Value,
                                 GSFriendVisibility.ToFriendVisibility(row.Friend_Visibility)));
        }
예제 #5
0
        /// <inheritdoc/>
        public async Task <IEnumerable <TreeNodeHeader> > GetChildNodeListAsync(EntityId idParent, DateTime?asOfUtc = null, ICacheParams cache = null)
        {
            //permission checks are performed in the child traverse loop down below
            var gop  = GdidOrPath.OfGNodeOrPath(idParent);
            var asof = DefaultAndAlignOnPolicyBoundary(asOfUtc, idParent);

            if (cache == null)
            {
                cache = CacheParams.DefaultCache;
            }

            IEnumerable <TreeNodeHeader> result;

            if (gop.PathAddress != null)
            {
                result = await getChildNodeListByTreePath(gop.Tree, gop.PathAddress, asof, cache).ConfigureAwait(false);
            }
            else
            {
                result = await getChildNodeListByGdid(gop.Tree, gop.GdidAddress, asof, cache).ConfigureAwait(false);
            }

            return(result);
        }
예제 #6
0
 IEnumerable <string> GetFileNames(ICacheParams caching = null)
 {
     return(null);
 }
예제 #7
0
        public static bool DeleteThrough <TKey>(this ICache cache, TKey key, string tblCache, ICacheParams caching, Func <TKey, bool> fDelete)
        {
            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            var wAge = caching.WriteCacheMaxAgeSec;
            var tbl  = cache.GetOrCreateTable <TKey>(tblCache);

            if (caching.CacheAbsentData && wAge >= 0)
            {
                tbl.Put(key, AbsentValue.Instance, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
            }
            else
            {
                tbl.Remove(key);
            }

            return(fDelete(key));
        }
예제 #8
0
        public static int SaveThrough <TKey, TData>(this ICache cache, TKey key, TData data, string tblCache, ICacheParams caching, Func <TKey, TData, int> fSave) where TData : class
        {
            if (data == null)
            {
                return(0);
            }

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            var result = fSave(key, data);

            var wAge = caching.WriteCacheMaxAgeSec;

            if (wAge >= 0)
            {
                var tbl = cache.GetOrCreateTable <TKey>(tblCache);
                tbl.Put(key, data, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
            }

            return(result);
        }
예제 #9
0
        /// <summary>
        /// Asynchronously fetches an item through cache - if the item exists and satisfies the `ICacheParams` (and optional `fFilter` functor) then it is
        /// immediately (synchronously) returned to the caller. Otherwise, calls the `fFetch` async functor to perform the actual fetch of a value by key,
        /// and then puts the result in cache according to `ICacheParams`
        /// </summary>
        /// <typeparam name="TKey">Type of key</typeparam>
        /// <typeparam name="TResult">Type of the result value</typeparam>
        /// <param name="cache">Non-null ICache instance to operate on</param>
        /// <param name="key">Key value</param>
        /// <param name="tblCache">Name of cache table</param>
        /// <param name="caching">Caching options, or null for defaults</param>
        /// <param name="fFetch">Required async functor that performs actual fetch when the value is NOT found in cache</param>
        /// <param name="fFilter">Optional functor - additional filter applied to existing values</param>
        /// <returns>Cached reference type value, or null if not found or absent</returns>
        public static async Task <TResult> FetchThroughAsync <TKey, TResult>(this ICache cache,
                                                                             TKey key,
                                                                             string tblCache,
                                                                             ICacheParams caching,
                                                                             Func <TKey, Task <TResult> > fFetch,
                                                                             Func <TKey, TResult, TResult> fFilter = null) where TResult : class
        {
            cache.NonNull(nameof(cache));

            ICacheTable <TKey> tbl = null;

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            if (caching.ReadCacheMaxAgeSec >= 0 || caching.WriteCacheMaxAgeSec >= 0)
            {
                tbl = cache.GetOrCreateTable <TKey>(tblCache);
            }

            TResult result = null;

            if (caching.ReadCacheMaxAgeSec >= 0)
            {
                var cached = tbl.Get(key, caching.ReadCacheMaxAgeSec);
                if (cached is AbsentValue)
                {
                    return(null);
                }
                else
                {
                    result = cached as TResult;
                }

                if (fFilter != null)
                {
                    result = fFilter(key, result);
                }
            }

            if (result != null)
            {
                return(result);
            }

            result = await fFetch.NonNull(nameof(fFetch))(key);//<-- only fFetch is IO-bound hence asynchronous

            if (result == null && !caching.CacheAbsentData)
            {
                return(null);
            }

            var wAge = caching.WriteCacheMaxAgeSec;

            if (wAge >= 0)
            {
                tbl.Put(key, (object)result ?? AbsentValue.Instance, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
            }

            return(result);
        }
예제 #10
0
        /// <summary>
        /// Implements <see cref="ICmsSource.FetchContentAsync(ContentId, string, DateTime, ICacheParams)"/>
        /// </summary>
        public async Task <Content> FetchContentAsync(ContentId id, string isoLang, DateTime utcNow, ICacheParams caching)
        {
            ensureOperationalState();
            var appliedIsoLang = ComponentDirector.DefaultGlobalLanguage.ISO; //in future this can be moved to property per portal

            if (isoLang.IsNullOrWhiteSpace())
            {
                isoLang = appliedIsoLang;
            }

            var dirPath = m_FS.CombinePaths(m_FSRootPath, id.Portal, id.Namespace);

            using (var session = m_FS.StartSession(m_FSConnectParams))
            {
                var dir = await session.GetItemAsync(dirPath) as FileSystemDirectory;

                if (dir == null)
                {
                    return(null);    //directory not found
                }
                //1st try to get language-specific file
                var(fname, fext) = getFileNameWithLangIso(id.Block, isoLang);
                var actualIsoLang = isoLang;

                var file = await dir.GetFileAsync(fname);

                //2nd try to get language-agnostic file
                if (file == null)
                {
                    fname = id.Block;//without the language
                    file  = await dir.GetFileAsync(fname);
                }
                else
                {
                    appliedIsoLang = isoLang;
                }

                if (file == null)
                {
                    return(null);     //file not found
                }
                var ctp = App.GetContentTypeMappings().MapFileExtension(fext);

                byte[] binContent = null;
                string txtContent = null;

                if (ctp.IsBinary)
                {
                    using (var ms = new MemoryStream())
                        using (var stream = file.FileStream)
                        {
                            await stream.CopyToAsync(ms);

                            binContent = ms.ToArray();
                        }
                }
                else
                {
                    txtContent = await file.ReadAllTextAsync();
                }

                var createUser = m_FS.InstanceCapabilities.SupportsCreationUserNames      ? file.CreationUser.Name     : null;
                var modifyUser = m_FS.InstanceCapabilities.SupportsModificationUserNames  ? file.ModificationUser.Name : null;
                var createDate = m_FS.InstanceCapabilities.SupportsCreationTimestamps     ? file.CreationTimestamp     : null;
                var modifyDate = m_FS.InstanceCapabilities.SupportsModificationTimestamps ? file.ModificationTimestamp : null;

                var result = new Content(id,
                                         ctp.Name,
                                         txtContent,
                                         binContent,
                                         ctp.ContentType,
                                         new LangInfo(appliedIsoLang, appliedIsoLang),
                                         attachmentFileName: id.Block,
                                         createUser: createUser,
                                         modifyUser: modifyUser,
                                         createDate: createDate,
                                         modifyDate: modifyDate);
                return(result);
            }
        }
예제 #11
0
        /// <summary>
        /// Implements <see cref="ICmsFacade.GetContentAsync(ContentId, Atom?, ICacheParams)"/>
        /// </summary>
        public async Task <Content> GetContentAsync(ContentId id, Atom?isoLang = null, ICacheParams caching = null)
        {
            if (!id.IsAssigned)
            {
                throw new CmsException($"{StringConsts.ARGUMENT_ERROR} {nameof(CmsFacade)}.{nameof(GetContentAsync)}(!id.IsAssigned)");
            }

            if (!isoLang.HasValue || isoLang.Value.IsZero)
            {
                isoLang = this.DefaultGlobalLanguage.ISO;
            }

            if (caching == null)
            {
                caching = getEffectiveCaching();
            }

            if (InstrumentationEnabled)
            {
                m_stat_RequestCount.IncrementLong(Datum.UNSPECIFIED_SOURCE);
                m_stat_RequestCount.IncrementLong($"{id.Portal}:${isoLang}");
            }

            var now      = App.TimeSource.UTCNow;
            var existing = tryLookupExisting(id, isoLang.Value, now, caching);

            if (existing != null)
            {
                if (InstrumentationEnabled)
                {
                    Interlocked.Increment(ref m_stat_CacheHitCount);
                    m_stat_ResponseCount.IncrementLong(Datum.UNSPECIFIED_SOURCE);
                    m_stat_ResponseCount.IncrementLong($"{id.Portal}:${isoLang}");
                }
                return(existing);
            }

            if (InstrumentationEnabled)
            {
                Interlocked.Increment(ref m_stat_CacheMissCount);
            }

            var fetched = await fetchAndCacheContent(id, isoLang.Value, now, caching).ConfigureAwait(false);

            if (InstrumentationEnabled && fetched != null)
            {
                m_stat_ResponseCount.IncrementLong(Datum.UNSPECIFIED_SOURCE);
                m_stat_ResponseCount.IncrementLong($"{id.Portal}:${isoLang}");
            }

            return(fetched);
        }
예제 #12
0
 /// <summary>
 /// If NoCache is true then returns `CacheParams.NoCache` otherwise returns default (null by dflt)
 /// </summary>
 public static ICacheParams NoOrDefaultCache(this bool noCache, ICacheParams dflt = null) => noCache ? CacheParams.NoCache : dflt;
예제 #13
0
        /// <summary>
        /// Deletes an item from cache and underlying store by calling the supplied asynchronous functor
        /// </summary>
        /// <typeparam name="TKey">Type of key</typeparam>
        /// <param name="cache">Non-null cache instance to delete from</param>
        /// <param name="key">Key value</param>
        /// <param name="tblCache">The name of a cache table</param>
        /// <param name="caching">Caching options, or null for defaults</param>
        /// <param name="fDelete">Asynchronous functor that performs backend deletion</param>
        /// <returns>True when value was deleted from the backing store</returns>
        public static async Task <bool> DeleteThroughAsync <TKey>(this ICache cache, TKey key, string tblCache, ICacheParams caching, Func <TKey, Task <bool> > fDelete)
        {
            cache.NonNull(nameof(cache));

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            var wAge = caching.WriteCacheMaxAgeSec;
            var tbl  = cache.GetOrCreateTable <TKey>(tblCache);

            if (caching.CacheAbsentData && wAge >= 0)
            {
                tbl.Put(key, AbsentValue.Instance, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
            }
            else
            {
                tbl.Remove(key);
            }

            return(await fDelete.NonNull(nameof(fDelete))(key).ConfigureAwait(false));
        }
예제 #14
0
 /// <summary>
 /// Returns Config by name or null
 /// </summary>
 public FileResource GetFile(string name, ICacheParams caching = null)
 {
     return(null);
 }
예제 #15
0
 /// <summary>
 /// Returns Config by name or null
 /// </summary>
 public ConfigResource GetConfig(string name, ICacheParams caching = null)
 {
     return(null);
 }
예제 #16
0
        /// <summary>
        /// Saves an item through cache: call the `fSave` functor asynchronously then synchronously saves the result into cache table
        /// </summary>
        /// <typeparam name="TKey">Type of key</typeparam>
        /// <typeparam name="TData">Type of reference type value to save</typeparam>
        /// <typeparam name="TSaveResult">Type of save result</typeparam>
        /// <param name="cache">Cache to operate on</param>
        /// <param name="key">Key value</param>
        /// <param name="data">Reference type value to save. May not be null or AbsentValue</param>
        /// <param name="tblCache">The name of a cache table</param>
        /// <param name="caching">Caching options, or null for default</param>
        /// <param name="fSave">Synchronous functor that performs backend save</param>
        /// <param name="extraPut">Optional functor (cache, TKey, TData, ICacheParams) which can be used to add the piled value to other cache tables (indexes) </param>
        /// <returns>A result of the call to `fSave` functor</returns>
        public static async Task <TSaveResult> SaveThroughAsync <TKey, TData, TSaveResult>(this ICache cache,
                                                                                           TKey key,
                                                                                           TData data,
                                                                                           string tblCache,
                                                                                           ICacheParams caching,
                                                                                           Func <TKey, TData, Task <TSaveResult> > fSave,
                                                                                           Action <ICache, TKey, TData, ICacheParams> extraPut = null
                                                                                           ) where TData : class
        {
            cache.NonNull(nameof(cache));

            if (data == null || data is AbsentValue)
            {
                throw new DataAccessException(StringConsts.ARGUMENT_ERROR + "{0}(data ==null || is AbsentValue)".Args(nameof(SaveThrough)));
            }

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            var result = await fSave.NonNull(nameof(fSave))(key, data);

            var wAge = caching.WriteCacheMaxAgeSec;

            if (wAge >= 0)
            {
                var tbl = cache.GetOrCreateTable <TKey>(tblCache);
                var pr  = tbl.Put(key, data, out var ptr, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
                if (pr != PutResult.Collision && ptr.Valid)
                {
                    extraPut?.Invoke(cache, key, data, caching);
                }
            }

            return(result);
        }
예제 #17
0
        /// <summary>
        /// Fetches an item through cache - if the item exists and satisfies the `ICacheParams` (and optional `fFilter` functor) then it is immediately returned
        /// to the caller. Otherwise, calls the `fFetch` functor to perform the actual fetch of a value by key, and then puts the result in cache
        /// according to `ICacheParams`
        /// </summary>
        /// <typeparam name="TKey">Type of key</typeparam>
        /// <typeparam name="TResult">Type of the result value</typeparam>
        /// <param name="cache">Non-null ICache instance to operate on</param>
        /// <param name="key">Key value</param>
        /// <param name="tblCache">Name of cache table</param>
        /// <param name="caching">Caching options, or null for defaults</param>
        /// <param name="fFetch">Required functor that performs actual fetch when the value is NOT found in cache</param>
        /// <param name="fFilter">Optional functor - additional filter applied to existing values</param>
        /// <param name="extraPut">Optional functor (cache, TKey, TResult, ICacheParams) which can be used to add the piled value to other cache tables (indexes) </param>
        /// <returns>Cached reference type value, or null if not found or absent</returns>
        public static TResult FetchThrough <TKey, TResult>(this ICache cache,
                                                           TKey key,
                                                           string tblCache,
                                                           ICacheParams caching,
                                                           Func <TKey, TResult> fFetch,
                                                           Func <TKey, TResult, TResult> fFilter = null,
                                                           Action <ICache, TKey, TResult, ICacheParams> extraPut = null
                                                           ) where TResult : class
        {
            cache.NonNull(nameof(cache));

            ICacheTable <TKey> tbl = null;

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            if (caching.ReadCacheMaxAgeSec >= 0 || caching.WriteCacheMaxAgeSec >= 0)
            {
                tbl = cache.GetOrCreateTable <TKey>(tblCache);
            }

            TResult result = null;

            if (caching.ReadCacheMaxAgeSec >= 0)
            {
                var cached = tbl.Get(key, caching.ReadCacheMaxAgeSec);
                if (cached is AbsentValue)
                {
                    return(null);
                }
                else
                {
                    result = cached as TResult;
                }

                if (fFilter != null)
                {
                    result = fFilter(key, result);
                }
            }

            if (result != null)
            {
                return(result);
            }

            result = fFetch.NonNull(nameof(fFetch))(key);

            if (result == null && !caching.CacheAbsentData)
            {
                return(null);
            }

            var wAge = caching.WriteCacheMaxAgeSec;

            if (wAge >= 0)
            {
                var pr = tbl.Put(key, (object)result ?? AbsentValue.Instance, out var ptr, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
                if (pr != PutResult.Collision && ptr.Valid)
                {
                    extraPut?.Invoke(cache, key, result, caching);
                }
            }

            return(result);
        }
예제 #18
0
        /// <inheritdoc/>
        public async Task <TreeNodeInfo> GetNodeInfoAsync(EntityId id, DateTime?asOfUtc = null, ICacheParams cache = null)
        {
            //permission checks are performed in the child traverse loop down below
            if (cache == null)
            {
                cache = CacheParams.DefaultCache;
            }
            var asof = DefaultAndAlignOnPolicyBoundary(asOfUtc, id);
            var gop  = GdidOrPath.OfGNodeOrPath(id);

            TreeNodeInfo result;

            if (gop.PathAddress != null)
            {
                result = await getNodeByTreePath(gop.Tree, gop.PathAddress, asof, cache).ConfigureAwait(false);
            }
            else
            {
                var graph = new HashSet <GDID>();
                result = await getNodeByGdid(graph, gop.Tree, gop.GdidAddress, asof, cache).ConfigureAwait(false);
            }

            return(result);
        }
예제 #19
0
 /// <summary>
 /// This is an async version of FetchFrom. This cache operation is only nominally asynchronous as it is performed in-memory and hence CPU-bound.
 /// Fetches an existing item from cache or null. IsAbsent is true when data was read from cache as an AbsentValue.
 /// </summary>
 /// <typeparam name="TKey">Type of key</typeparam>
 /// <typeparam name="TResult">Type of the returned result value</typeparam>
 /// <param name="cache">Cache instance to operate on</param>
 /// <param name="key">Key to read</param>
 /// <param name="tblCache">Name of a cache table within a cache</param>
 /// <param name="caching">Caching options, or null for defaults</param>
 /// <param name="isAbsent">Returns true when value was found, but it is an AbsentValue instance</param>
 /// <returns>Cached reference type value, or null if not found or absent</returns>
 public static Task <TResult> FetchFromAsync <TKey, TResult>(this ICache cache,
                                                             TKey key,
                                                             string tblCache,
                                                             ICacheParams caching,
                                                             out bool isAbsent) where TResult : class
 => Task.FromResult(cache.FetchFrom <TKey, TResult>(key, tblCache, caching, out isAbsent));
예제 #20
0
        private async Task <TreeNodeInfo> getNodeByTreePath(TreePtr tree, TreePath path, DateTime asOfUtc, ICacheParams caching)
        {
            var tblCache = s_CacheTableName[tree];
            var keyCache = nameof(getNodeByTreePath) + path + asOfUtc.Ticks;

            var result = await m_Data.Cache.FetchThroughAsync(
                keyCache, tblCache, caching,
                async key => {
                TreeNodeInfo nodeParent = null;
                TreeNodeInfo node       = null;
                for (var i = -1; i < path.Count; i++) //going from LEFT to RIGHT
                {
                    var segment = i < 0 ? Constraints.VERY_ROOT_PATH_SEGMENT : path[i];
                    node        = await getNodeByPathSegment(tree, nodeParent == null ? GDID.ZERO : nodeParent.Gdid, segment, asOfUtc, caching).ConfigureAwait(false);
                    if (node == null)
                    {
                        return(null);     // deleted
                    }
                    //Config chain inheritance pattern
                    if (nodeParent == null)
                    {
                        node.EffectiveConfig = new ConfigVector(node.LevelConfig.Content);//Copy
                        node.FullPath        = Constraints.VERY_ROOT_PATH_SEGMENT;
                    }
                    else
                    {
                        var confHere   = node.LevelConfig.Node.NonEmpty(nameof(node.LevelConfig));
                        var confParent = nodeParent.EffectiveConfig.Node.NonEmpty(nameof(nodeParent.EffectiveConfig));
                        var confResult = new MemoryConfiguration()
                        {
                            Application = this.App
                        };
                        confResult.CreateFromNode(confParent); //inherit
                        confResult.Root.OverrideBy(confHere);  //override
                        node.EffectiveConfig = new ConfigVector(confResult.Root);
                        node.FullPath        = TreePath.Join(nodeParent.FullPath, node.PathSegment);
                    }
                    nodeParent = node;
                    App.Authorize(new TreePermission(TreeAccessLevel.Read, node.FullPathId));
                }
                return(node);
            }).ConfigureAwait(false);

            return(result);
        }
예제 #21
0
        private async Task <TreeNodeInfo> getNodeByPathSegment(TreePtr tree, GDID gParent, string pathSegment, DateTime asOfUtc, ICacheParams caching)
        {
            if (gParent.IsZero)
            {
                gParent = Constraints.G_VERY_ROOT_NODE;
            }

            var tblCache = s_CacheTableName[tree];
            var keyCache = nameof(getNodeByPathSegment) + gParent.ToHexString() + (pathSegment ?? string.Empty) + asOfUtc.Ticks;

            var node = await m_Data.Cache.FetchThroughAsync(
                keyCache, tblCache, caching,
                async key =>
            {
                var qry = new Query <TreeNodeInfo>("Tree.GetNodeInfo")
                {
                    new Query.Param("tree", tree),
                    new Query.Param("gparent", gParent),
                    new Query.Param("psegment", pathSegment),
                    new Query.Param("asof", asOfUtc)
                };
                return(await m_Data.TreeLoadDocAsync(tree, qry));
            }
                ).ConfigureAwait(false);

            return(node);
        }
예제 #22
0
        private async Task <TreeNodeInfo> getNodeByGdid(HashSet <GDID> graph, TreePtr tree, GDID gNode, DateTime asOfUtc, ICacheParams caching)
        {
            var tblCache = s_CacheTableName[tree];
            var keyCache = nameof(getNodeByGdid) + gNode.ToHexString() + asOfUtc.Ticks;
            var result   = await m_Data.Cache.FetchThroughAsync(
                keyCache, tblCache, caching,
                async key =>
            {
                if (!graph.Add(gNode))
                {
                    //circular reference
                    var err = new ConfigException("Circular reference in config tree = `{0}`, gnode = `{1}`, asof = `{2}`".Args(tree, gNode, asOfUtc));
                    WriteLogFromHere(Log.MessageType.CatastrophicError,
                                     err.Message,
                                     err,
                                     pars: new { tree = tree.ToString(), gnode = gNode, asof = asOfUtc }.ToJson());
                    throw err;
                }

                //1 - fetch THIS level - rightmost part of the tree
                var qry = new Query <TreeNodeInfo>("Tree.GetNodeInfoByGdid")
                {
                    new Query.Param("tree", tree),
                    new Query.Param("gdid", gNode),
                    new Query.Param("asof", asOfUtc)
                };

                var node = await m_Data.TreeLoadDocAsync(tree, qry);
                if (node == null)
                {
                    return(null);
                }

                //2 - if IAM ROOT, there is no parent for root
                node.EffectiveConfig = new ConfigVector(node.LevelConfig.Content);//Copy
                node.FullPath        = Constraints.VERY_ROOT_PATH_SEGMENT;

                if (node.Gdid == Constraints.G_VERY_ROOT_NODE)
                {
                    return(node);
                }

                //3 - Fetch parent of THIS
                TreeNodeInfo nodeParent = await getNodeByGdid(graph, tree, node.G_Parent, asOfUtc, caching).ConfigureAwait(false);
                if (nodeParent == null)
                {
                    return(null);
                }

                //4 - calculate effective config
                var cfgNode   = node.LevelConfig.Node.NonEmpty(nameof(node.LevelConfig));
                var cfgParent = nodeParent.EffectiveConfig.Node.NonEmpty(nameof(nodeParent.EffectiveConfig));

                var confResult = new MemoryConfiguration()
                {
                    Application = this.App
                };
                confResult.CreateFromNode(cfgParent); //inherit
                confResult.Root.OverrideBy(cfgNode);  //override
                node.EffectiveConfig.Node = confResult.Root;

                node.FullPath = TreePath.Join(nodeParent.FullPath, node.PathSegment);

                //the security check is done post factum AFTER tree node full path is known
                return(node);
            }
                ).ConfigureAwait(false);

            if (result == null)
            {
                return(null);
            }
            App.Authorize(new TreePermission(TreeAccessLevel.Read, result.FullPathId));
            return(result);
        }
예제 #23
0
        /// <summary>
        /// Fetches an item through cache
        /// </summary>
        public static TResult FetchThrough <TKey, TResult>(this ICache cache, TKey key, string tblCache, ICacheParams caching, Func <TKey, TResult> fFetch, Func <TKey, TResult, TResult> fFilter = null) where TResult : class
        {
            ICacheTable <TKey> tbl = null;

            if (caching == null)
            {
                caching = CacheParams.DefaultCache;
            }

            if (caching.ReadCacheMaxAgeSec >= 0 || caching.WriteCacheMaxAgeSec >= 0)
            {
                tbl = cache.GetOrCreateTable <TKey>(tblCache);
            }

            TResult result = null;

            if (caching.ReadCacheMaxAgeSec >= 0)
            {
                var cached = tbl.Get(key, caching.ReadCacheMaxAgeSec);
                if (cached is AbsentValue)
                {
                    return(null);
                }
                else
                {
                    result = cached as TResult;
                }

                if (fFilter != null)
                {
                    result = fFilter(key, result);
                }
            }

            if (result != null)
            {
                return(result);
            }

            result = fFetch(key);

            if (result == null && !caching.CacheAbsentData)
            {
                return(null);
            }

            var wAge = caching.WriteCacheMaxAgeSec;

            if (wAge >= 0)
            {
                tbl.Put(key, (object)result ?? AbsentValue.Instance, wAge > 0 ? wAge : (int?)null, caching.WriteCachePriority);
            }

            return(result);
        }
예제 #24
0
        private async Task <IEnumerable <TreeNodeHeader> > getChildNodeListByTreePath(TreePtr tree, TreePath pathAddress, DateTime asOfUtc, ICacheParams caching)
        {
            var nodeParent = await getNodeByTreePath(tree, pathAddress, asOfUtc, caching).ConfigureAwait(false);

            if (nodeParent == null)
            {
                return(null);
            }

            var result = await getChildNodeListByGdid(tree, nodeParent.Gdid, asOfUtc, caching);

            return(result);
        }
예제 #25
0
파일: Intfs.cs 프로젝트: sergey-msu/azos
        public static TResource Navigate <TResource>(this ICMSContext ctx, string path, ICacheParams caching = null) where TResource : Resource
        {
            var result = ctx.TryNavigate(path, caching) as TResource;

            if (result == null)
            {
                throw new CMSException(StringConsts.CMS_NAVIGATE_T_ERROR.Args(ctx.Portal, typeof(TResource), path));
            }
            return(result);
        }
예제 #26
0
        private async Task <IEnumerable <TreeNodeHeader> > getChildNodeListByGdid(TreePtr tree, GDID gdidAddress, DateTime asOfUtc, ICacheParams caching)
        {
            var tblCache = s_CacheTableName[tree];
            var keyCache = nameof(getChildNodeListByGdid) + gdidAddress.ToHexString() + asOfUtc.Ticks;

            var nodes = await m_Data.Cache.FetchThroughAsync(
                keyCache, tblCache, caching,
                async key =>
            {
                var qry = new Query <TreeNodeHeader>("Tree.GetChildNodeList")
                {
                    new Query.Param("tree", tree),
                    new Query.Param("gparent", gdidAddress),
                    new Query.Param("asof", asOfUtc)
                };
                return(await m_Data.TreeLoadEnumerableAsync(tree, qry));
            }
                ).ConfigureAwait(false);

            return(nodes);
        }
예제 #27
0
        public async Task <Content> FetchContentAsync(ContentId id, Atom isoLang, DateTime utcNow, ICacheParams caching)
        {
            id.HasRequiredValue(nameof(id));
            var(svc, adr) = ensureOperationalState();

            var uri = new UriQueryBuilder("feed")
                      .Add("portal", id.Portal)
                      .Add("ns", id.Namespace)
                      .Add("block", id.Block)
                      .Add("isolang", isoLang.ToString())
                      .Add("nocache", caching == null || caching.ReadCacheMaxAgeSec < 0)
                      .Add("buffered", false)
                      .ToString();


            var result = await svc.Call(adr, nameof(ICmsSource), new ShardKey(id.Block), async (http, ct) => {
                Content content = null;
                using (var httpResponse = await http.Client.GetAsync(uri).ConfigureAwait(false))
                {
                    httpResponse.EnsureSuccessStatusCode();
                    var compress = httpResponse.Content.Headers.ContentType.MediaType.EqualsOrdIgnoreCase(Controllers.CmsSourceFeeder.CTP_COMPRESSED);
                    using (var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false))
                    {
                        var rstream = stream;
                        if (compress)
                        {
                            rstream = new GZipStream(stream, CompressionMode.Decompress, true);
                        }

                        content = new Content(stream);

                        if (compress)
                        {
                            rstream.Dispose();
                        }
                    }
                }

                return(content);
            }).ConfigureAwait(false);

            return(result);
        }
예제 #28
0
        protected virtual IEnumerable <FriendConnection> DoGetFriendConnections(FriendQuery query, ICacheParams cacheParams = null)
        {
            var rows = ForNode(query.G_Node).LoadEnumerable(Queries.FindFriends <FriendRow>(query));

            foreach (var row in rows)
            {
                var friendNode = DoGetNode(row.G_Friend, cacheParams);
                foreach (var graphNode in GraphHost.FilterByOriginQuery(new[] { friendNode }, query.OriginQuery))
                {
                    yield return(new FriendConnection(graphNode,
                                                      row.Request_Date,
                                                      FriendStatus.Approved.Equals(GSFriendStatus.ToFriendStatus(row.Status))
              ? (DateTime?)row.Status_Date
              : null,
                                                      GSFriendshipRequestDirection.ToFriendshipRequestDirection(row.Direction),
                                                      GSFriendVisibility.ToFriendVisibility(row.Visibility),
                                                      row.Lists));
                }
            }
        }