Skip to content

Commit

Permalink
apply changes from dnnsoftware#2032
Browse files Browse the repository at this point in the history
  • Loading branch information
zyhfish committed Dec 17, 2019
1 parent d368201 commit 1836c35
Showing 1 changed file with 89 additions and 85 deletions.
174 changes: 89 additions & 85 deletions DNN Platform/Library/Entities/Urls/TabIndexController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1392,8 +1392,28 @@ internal static string CreateRewritePath(int tabId, string cultureCode, ActionTy
return rewritePath;
}

/// <summary>
/// Returns whether the portal specified exists in the Tab index or not.
/// </summary>
/// <param name="portalDepths">The current portalDepths dictionary.</param>
/// <param name="portalId">The id of the portal to search for.</param>
/// <returns></returns>
private static bool PortalExistsInIndex(SharedDictionary<int, PathSizes> portalDepths, int portalId)
{
bool result = false;

if (portalDepths != null)
{
using (portalDepths.GetReadLock())
{
result = portalDepths.ContainsKey(portalId);
}
}
return result;
}

/// <summary>
/// Gets the Tab Dictionary from the DataCache memory location, if it's empty or missing, builds a new one
/// Gets the Tab Dictionary from the DataCache memory location, if it's empty or missing, builds a new one.
/// </summary>
/// <param name="portalId"></param>
/// <param name="minTabPathDepth">ByRef parameter to return the minimum tab path depth (the number of '/' in the tab path)</param>
Expand Down Expand Up @@ -1421,48 +1441,50 @@ internal static SharedDictionary<string, string> FetchTabDictionary(int portalId
bool bypassCache,
Guid parentTraceId)
{
SharedDictionary<int, PathSizes> portalDepths;
SharedDictionary<string, string> dict;
PathSizes depthInfo;
SharedDictionary<int, PathSizes> portalDepths = null;
SharedDictionary<string, string> dict = null;
SharedDictionary<string, string> portalTabPathDictionary = null;
string reason = "";

//place threadlock to prevent two threads getting a null object
//check for the tab dictionary in the DataCache
var cc = new CacheController();
cc.GetPageIndexFromCache(out dict, out portalDepths, settings);

string reason = "";
if (dict == null)
if (bypassCache == false)
{
reason += "No Page index in cache;";
}
if (forceRebuild)
{
reason += "Force Rebuild;";
}
if (bypassCache)
{
reason += "Bypass Cache;";
}
if (dict != null)
{
using (dict.GetReadLock())
{
reason += "Existing Page Index=" + dict.Count.ToString() + " items;";
}
cc.GetPageIndexFromCache(out dict, out portalDepths, settings);
portalTabPathDictionary = FetchTabPathDictionary(portalId);
}

Hashtable homePageSkins; //keeps a list of skins set per home page and culture
SharedDictionary<string, string> portalTabPathDictionary;
if (dict != null && portalDepths != null && forceRebuild == false && bypassCache == false)
if (dict == null || portalDepths == null || portalTabPathDictionary == null || !PortalExistsInIndex(portalDepths, portalId) || forceRebuild)
{
PathSizes depthInfo;
bool changed = false;
using (portalDepths.GetWriteLock())
//place threadlock to prevent two threads getting a null object. Use the same lock object that is used to
lock (tabPathDictBuildLock)
{
if (!portalDepths.ContainsKey(portalId))
//check for the tab dictionary in the DataCache again as it could have been cached by another thread
//while waiting for the lock to become available.
if (bypassCache == false)
{
cc.GetPageIndexFromCache(out dict, out portalDepths, settings);
portalTabPathDictionary = FetchTabPathDictionary(portalId);
}

if (dict == null || portalDepths == null || portalTabPathDictionary == null || !PortalExistsInIndex(portalDepths, portalId) || forceRebuild)
{
reason += "Portal " + portalId.ToString() + " added to index;";
Hashtable homePageSkins; //keeps a list of skins set per home page and culture

//tab dictionary built, but portal not in it
if (!bypassCache && dict == null)
{
reason += "No Page index in cache;";
}
if (forceRebuild)
{
reason += "Force Rebuild;";
}
if (bypassCache)
{
reason += "Bypass Cache;";
}
//PathSizes depthInfo;
//the cached dictionary was null or forceRebuild = true or bypassCache = true, so go get a new dictionary
dict = BuildTabDictionary(out depthInfo,
settings,
portalId,
Expand All @@ -1471,76 +1493,58 @@ internal static SharedDictionary<string, string> FetchTabDictionary(int portalId
out portalTabPathDictionary,
parentTraceId);

//recheck portal add, when running with locks can get duplicate key exceptions
if (portalDepths.ContainsKey(portalId) == false)
if (portalDepths == null || forceRebuild)
{
portalDepths.Add(portalId, depthInfo);
changed = true;
portalDepths = new SharedDictionary<int, PathSizes>();
}

cc.StoreTabPathsInCache(portalId, portalTabPathDictionary, settings);
CacheController.StoreHomePageSkinsInCache(portalId, homePageSkins);
}
else
{
depthInfo = portalDepths[portalId];
//store the fact that this portal has been built
using (portalDepths.GetWriteLock())
{
//depthInfo may already exist in index so use indexer to Add/Update rather than using Add method which
//would throw an exception if the portal already existed in the dictionary.
portalDepths[portalId] = depthInfo;
}

if (bypassCache == false) //only cache if bypass not switched on
{
reason += "Portal " + portalId + " added to index;";
using (dict.GetReadLock())
{
reason += "Existing Page Index=" + dict.Count + " items;";
}

cc.StorePageIndexInCache(dict, portalDepths, settings, reason);
cc.StoreTabPathsInCache(portalId, portalTabPathDictionary, settings);
CacheController.StoreHomePageSkinsInCache(portalId, homePageSkins);
}
}
}
if (changed)
{
//restash dictionary
cc.StorePageIndexInCache(dict, portalDepths, settings, reason);
}
}

if (depthInfo != null)
if (PortalExistsInIndex(portalDepths, portalId))
{
using (portalDepths.GetReadLock())
{
depthInfo = portalDepths[portalId];
minTabPathDepth = depthInfo.MinTabPathDepth;
maxTabPathDepth = depthInfo.MaxTabPathDepth;
minAliasPathDepth = depthInfo.MinAliasDepth;
maxAliasPathDepth = depthInfo.MaxAliasDepth;
}
else
{
//fallback values, should never get here: mainly for compiler wranings
minTabPathDepth = 1;
maxTabPathDepth = 10;
minAliasPathDepth = 1;
maxAliasPathDepth = 4;
}
}
else
{
//the cached dictionary was null or forceRebuild = true or bypassCache = true, so go get a new dictionary
PathSizes depthInfo;
dict = BuildTabDictionary(out depthInfo,
settings,
portalId,
null,
out homePageSkins,
out portalTabPathDictionary,
parentTraceId);

//store the fact that this portal has been built
portalDepths = new SharedDictionary<int, PathSizes>();
using (portalDepths.GetWriteLock())
{
portalDepths.Add(portalId, depthInfo);
}
if (bypassCache == false) //only cache if bypass not switched on
{
cc.StorePageIndexInCache(dict, portalDepths, settings, reason);
}
cc.StoreTabPathsInCache(portalId, portalTabPathDictionary, settings);
CacheController.StoreHomePageSkinsInCache(portalId, homePageSkins);
minTabPathDepth = depthInfo.MinTabPathDepth;
maxTabPathDepth = depthInfo.MaxTabPathDepth;
minAliasPathDepth = depthInfo.MinAliasDepth;
maxAliasPathDepth = depthInfo.MaxAliasDepth;
//fallback values, should never get here: mainly for compiler wranings
minTabPathDepth = 1;
maxTabPathDepth = 10;
minAliasPathDepth = 1;
maxAliasPathDepth = 4;
}

return dict;
}


/// <summary>
/// Returns a list of aliases that are used in custom tab/alias association.
/// </summary>
Expand Down

0 comments on commit 1836c35

Please sign in to comment.