Work items: 30204

This commit is contained in:
hartvig
2011-09-14 17:25:30 -02:00
parent eb3cb32965
commit 8a43220657
9 changed files with 201 additions and 152 deletions

View File

@@ -520,10 +520,12 @@ namespace umbraco.cms.businesslogic.web
}
// Add thread safe updating to the hashtable
System.Web.HttpContext.Current.Application.Lock();
if (System.Web.HttpContext.Current != null)
System.Web.HttpContext.Current.Application.Lock();
if (!_checkedPages.ContainsKey(DocumentId))
_checkedPages.Add(DocumentId, isProtected);
System.Web.HttpContext.Current.Application.UnLock();
if (System.Web.HttpContext.Current != null)
System.Web.HttpContext.Current.Application.UnLock();
}
else
isProtected = (bool) _checkedPages[DocumentId];

View File

@@ -39,7 +39,10 @@ namespace umbraco.presentation
{
get
{
return (UmbracoContext)HttpContext.Current.Items["UmbracoContext"];
if (HttpContext.Current != null)
return (UmbracoContext)HttpContext.Current.Items["UmbracoContext"];
return null;
}
set

View File

@@ -7,16 +7,17 @@ using System.Threading;
using System.Web;
using System.Xml;
using System.Xml.XPath;
using umbraco.BusinessLogic;
using umbraco.BusinessLogic.Actions;
using umbraco.BusinessLogic.Utils;
using umbraco.cms.businesslogic;
using umbraco.cms.businesslogic.cache;
using umbraco.cms.businesslogic.web;
using umbraco.DataLayer;
using umbraco.IO;
using umbraco.BusinessLogic.Utils;
using umbraco.presentation.nodeFactory;
using Action = umbraco.BusinessLogic.Actions.Action;
using Node = umbraco.NodeFactory.Node;
namespace umbraco
{
@@ -27,7 +28,17 @@ namespace umbraco
{
#region Declarations
// Sync access to disk file
private static readonly object _readerWriterSyncLock = new object();
// Sync access to internal cache
private static readonly object _xmlContentInternalSyncLock = new object();
// Sync database access
private static readonly object _dbReadSyncLock = new object();
private readonly string XmlContextContentItemKey = "UmbracoXmlContextContent";
private string _umbracoXmlDiskCacheFileName = string.Empty;
private volatile XmlDocument _xmlContent;
/// <summary>
/// Gets the path of the umbraco XML disk cache file.
@@ -43,35 +54,13 @@ namespace umbraco
}
return _umbracoXmlDiskCacheFileName;
}
set
{
_umbracoXmlDiskCacheFileName = value;
}
set { _umbracoXmlDiskCacheFileName = value; }
}
private readonly string XmlContextContentItemKey = "UmbracoXmlContextContent";
// Current content
private volatile XmlDocument _xmlContent = null;
// Sync access to disk file
private static object _readerWriterSyncLock = new object();
// Sync access to internal cache
private static object _xmlContentInternalSyncLock = new object();
// Sync database access
private static object _dbReadSyncLock = new object();
#endregion
#region Constructors
public content()
{
;
}
static content()
{
//Trace.Write("Initializing content");
@@ -86,6 +75,11 @@ namespace umbraco
Instance.CheckXmlContentPopulation();
}
public content()
{
;
}
#endregion
#region Singleton
@@ -111,7 +105,7 @@ namespace umbraco
{
if (HttpContext.Current == null)
return XmlContentInternal;
XmlDocument content = HttpContext.Current.Items[XmlContextContentItemKey] as XmlDocument;
var content = HttpContext.Current.Items[XmlContextContentItemKey] as XmlDocument;
if (content == null)
{
content = XmlContentInternal;
@@ -180,7 +174,8 @@ namespace umbraco
{
if (isInitializing)
{
Trace.WriteLine(string.Format("Initializing content on thread '{0}' (Threadpool? {1})", Thread.CurrentThread.Name, Thread.CurrentThread.IsThreadPoolThread.ToString()));
Trace.WriteLine(string.Format("Initializing content on thread '{0}' (Threadpool? {1})",
Thread.CurrentThread.Name, Thread.CurrentThread.IsThreadPoolThread));
_xmlContent = LoadContent();
Trace.WriteLine("Content initialized (loaded)");
@@ -221,29 +216,48 @@ namespace umbraco
}
XmlDocumentType docType = xmlDoc.CreateDocumentType("root", null, null, dtd);
xmlDoc.InsertAfter(docType, xmlDoc.FirstChild);
}
protected static void ValidateSchema(string docTypeAlias, XmlDocument xmlDoc)
{
// if doctype is not defined i)n schema, then regenerate it
if (!xmlDoc.DocumentType.InternalSubset.Contains(String.Format("<!ATTLIST {0} id ID #REQUIRED>", docTypeAlias)))
if (
!xmlDoc.DocumentType.InternalSubset.Contains(String.Format("<!ATTLIST {0} id ID #REQUIRED>",
docTypeAlias)))
{
// we need to re-load the content, else the dtd changes won't be picked up by the XmlDocument
content.Instance.XmlContentInternal = content.Instance.LoadContentFromDatabase();
Instance.XmlContentInternal = Instance.LoadContentFromDatabase();
}
}
#region Public Methods
#region Delegates
/// <summary>
/// Occurs when [after loading the xml string from the database].
/// </summary>
public delegate void ContentCacheDatabaseLoadXmlStringEventHandler(
ref string xml, ContentCacheLoadNodeEventArgs e);
/// <summary>
/// Occurs when [after loading the xml string from the database and creating the xml node].
/// </summary>
public delegate void ContentCacheLoadNodeEventHandler(XmlNode xmlNode, ContentCacheLoadNodeEventArgs e);
public delegate void DocumentCacheEventHandler(Document sender, DocumentCacheEventArgs e);
public delegate void RefreshContentEventHandler(Document sender, RefreshContentEventArgs e);
#endregion
/// <summary>
/// Load content from database in a background thread
/// Replaces active content when done.
/// </summary>
public virtual void RefreshContentFromDatabaseAsync()
{
cms.businesslogic.RefreshContentEventArgs e = new umbraco.cms.businesslogic.RefreshContentEventArgs();
var e = new RefreshContentEventArgs();
FireBeforeRefreshContent(e);
if (!e.Cancel)
@@ -258,7 +272,8 @@ namespace umbraco
// queues this up, because this delegate is executing on a different thread and may complete
// after the request which invoked it (which would normally persist the file on completion)
// So we are responsible for ensuring the content is persisted in this case.
if (!UmbracoSettings.isXmlContentCacheDisabled && UmbracoSettings.continouslyUpdateXmlDiskCache)
if (!UmbracoSettings.isXmlContentCacheDisabled &&
UmbracoSettings.continouslyUpdateXmlDiskCache)
PersistXmlToFile(xmlDoc);
});
@@ -296,13 +311,27 @@ namespace umbraco
if (d.Published)
{
int parentId = d.Level == 1 ? -1 : d.Parent.Id;
AppendDocumentXml(d.Id, d.Level, parentId, getPreviewOrPublishedNode(d, xmlContentCopy, false), xmlContentCopy);
AppendDocumentXml(d.Id, d.Level, parentId, getPreviewOrPublishedNode(d, xmlContentCopy, false),
xmlContentCopy);
// update sitemapprovider
if (updateSitemapProvider && SiteMap.Provider is presentation.nodeFactory.UmbracoSiteMapProvider)
if (updateSitemapProvider && SiteMap.Provider is UmbracoSiteMapProvider)
{
presentation.nodeFactory.UmbracoSiteMapProvider prov = (presentation.nodeFactory.UmbracoSiteMapProvider)SiteMap.Provider;
prov.UpdateNode(new umbraco.NodeFactory.Node(d.Id, true));
try
{
var prov = (UmbracoSiteMapProvider)SiteMap.Provider;
Node n = new Node(d.Id, true);
if (!String.IsNullOrEmpty(n.Url) && n.Url != "/#")
prov.UpdateNode(n);
else
{
Log.Add(LogTypes.Error, d.Id, "Can't update Sitemap Provider due to empty Url in node");
}
}
catch (Exception ee)
{
Log.Add(LogTypes.Error, d.Id, string.Format("Error adding node to Sitemap Provider in PublishNodeDo(): {0}", ee));
}
}
}
}
@@ -342,7 +371,8 @@ namespace umbraco
// Maybe sort the nodes if the added node has a lower sortorder than the last
if (childNodes.Count > 0)
{
int siblingSortOrder = int.Parse(childNodes[childNodes.Count - 1].Attributes.GetNamedItem("sortOrder").Value);
int siblingSortOrder =
int.Parse(childNodes[childNodes.Count - 1].Attributes.GetNamedItem("sortOrder").Value);
int currentSortOrder = int.Parse(x.Attributes.GetNamedItem("sortOrder").Value);
if (childNodes.Count > 1 && siblingSortOrder > currentSortOrder)
{
@@ -394,7 +424,7 @@ namespace umbraco
/// <param name="pageId">The page id.</param>
public virtual void UpdateDocumentCache(int pageId)
{
Document d = new Document(pageId);
var d = new Document(pageId);
UpdateDocumentCache(d);
}
@@ -405,13 +435,11 @@ namespace umbraco
/// <param name="d">The d.</param>
public virtual void UpdateDocumentCache(Document d)
{
cms.businesslogic.DocumentCacheEventArgs e = new umbraco.cms.businesslogic.DocumentCacheEventArgs();
var e = new DocumentCacheEventArgs();
FireBeforeUpdateDocumentCache(d, e);
if (!e.Cancel)
{
// We need to lock content cache here, because we cannot allow other threads
// making changes at the same time, they need to be queued
// Adding log entry before locking the xmlfile
@@ -440,7 +468,7 @@ namespace umbraco
{
System.Web.Caching.Cache httpCache = HttpContext.Current.Cache;
string cachedFieldKeyStart = String.Format("contentItem{0}_", d.Id);
List<string> foundKeys = new List<string>();
var foundKeys = new List<string>();
foreach (DictionaryEntry cacheItem in httpCache)
{
string key = cacheItem.Key.ToString();
@@ -452,7 +480,7 @@ namespace umbraco
httpCache.Remove(foundKey);
}
}
umbraco.BusinessLogic.Actions.Action.RunActionHandlers(d, ActionPublish.Instance);
Action.RunActionHandlers(d, ActionPublish.Instance);
FireAfterUpdateDocumentCache(d, e);
}
@@ -483,7 +511,7 @@ namespace umbraco
foreach (Document d in Documents)
{
umbraco.BusinessLogic.Actions.Action.RunActionHandlers(d, ActionPublish.Instance);
Action.RunActionHandlers(d, ActionPublish.Instance);
}
}
@@ -498,7 +526,6 @@ namespace umbraco
}
[Obsolete("Method obsolete in version 4.1 and later, please use ClearDocumentCache", true)]
/// <summary>
/// Clears the document cache async.
@@ -517,11 +544,10 @@ namespace umbraco
/// <param name="documentId">The document id.</param>
public virtual void ClearDocumentCache(int documentId)
{
// Get the document
Document d = new Document(documentId);
var d = new Document(documentId);
cms.businesslogic.DocumentCacheEventArgs e = new umbraco.cms.businesslogic.DocumentCacheEventArgs();
var e = new DocumentCacheEventArgs();
FireBeforeClearDocumentCache(d, e);
if (!e.Cancel)
@@ -558,13 +584,13 @@ namespace umbraco
if (x != null)
{
// Run Handler
umbraco.BusinessLogic.Actions.Action.RunActionHandlers(d, ActionUnPublish.Instance);
Action.RunActionHandlers(d, ActionUnPublish.Instance);
}
// update sitemapprovider
if (SiteMap.Provider is presentation.nodeFactory.UmbracoSiteMapProvider)
if (SiteMap.Provider is UmbracoSiteMapProvider)
{
presentation.nodeFactory.UmbracoSiteMapProvider prov = (presentation.nodeFactory.UmbracoSiteMapProvider)SiteMap.Provider;
var prov = (UmbracoSiteMapProvider)SiteMap.Provider;
prov.RemoveNode(d.Id);
}
@@ -601,7 +627,7 @@ namespace umbraco
public virtual void PublishNode(int documentId)
{
// Get the document
Document d = new Document(documentId);
var d = new Document(documentId);
PublishNode(d);
}
@@ -636,9 +662,6 @@ namespace umbraco
UpdateDocumentCache(d);
}
public delegate void DocumentCacheEventHandler(Document sender, cms.businesslogic.DocumentCacheEventArgs e);
public delegate void RefreshContentEventHandler(Document sender, cms.businesslogic.RefreshContentEventArgs e);
/// <summary>
/// Occurs when [before document cache update].
/// </summary>
@@ -649,7 +672,7 @@ namespace umbraco
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.DocumentCacheEventArgs"/> instance containing the event data.</param>
protected virtual void FireBeforeUpdateDocumentCache(Document sender, cms.businesslogic.DocumentCacheEventArgs e)
protected virtual void FireBeforeUpdateDocumentCache(Document sender, DocumentCacheEventArgs e)
{
if (BeforeUpdateDocumentCache != null)
{
@@ -668,7 +691,7 @@ namespace umbraco
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.DocumentCacheEventArgs"/> instance containing the event data.</param>
protected virtual void FireAfterUpdateDocumentCache(Document sender, cms.businesslogic.DocumentCacheEventArgs e)
protected virtual void FireAfterUpdateDocumentCache(Document sender, DocumentCacheEventArgs e)
{
if (AfterUpdateDocumentCache != null)
{
@@ -686,7 +709,7 @@ namespace umbraco
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.DocumentCacheEventArgs"/> instance containing the event data.</param>
protected virtual void FireBeforeClearDocumentCache(Document sender, cms.businesslogic.DocumentCacheEventArgs e)
protected virtual void FireBeforeClearDocumentCache(Document sender, DocumentCacheEventArgs e)
{
if (BeforeClearDocumentCache != null)
{
@@ -701,7 +724,7 @@ namespace umbraco
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.DocumentCacheEventArgs"/> instance containing the event data.</param>
protected virtual void FireAfterClearDocumentCache(Document sender, cms.businesslogic.DocumentCacheEventArgs e)
protected virtual void FireAfterClearDocumentCache(Document sender, DocumentCacheEventArgs e)
{
if (AfterClearDocumentCache != null)
{
@@ -719,7 +742,7 @@ namespace umbraco
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.RefreshContentEventArgs"/> instance containing the event data.</param>
protected virtual void FireBeforeRefreshContent(cms.businesslogic.RefreshContentEventArgs e)
protected virtual void FireBeforeRefreshContent(RefreshContentEventArgs e)
{
if (BeforeRefreshContent != null)
{
@@ -737,7 +760,7 @@ namespace umbraco
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.RefreshContentEventArgs"/> instance containing the event data.</param>
protected virtual void FireAfterRefreshContent(cms.businesslogic.RefreshContentEventArgs e)
protected virtual void FireAfterRefreshContent(RefreshContentEventArgs e)
{
if (AfterRefreshContent != null)
{
@@ -746,16 +769,6 @@ namespace umbraco
}
/// <summary>
/// Occurs when [after loading the xml string from the database and creating the xml node].
/// </summary>
public delegate void ContentCacheLoadNodeEventHandler(XmlNode xmlNode, cms.businesslogic.ContentCacheLoadNodeEventArgs e);
/// <summary>
/// Occurs when [after loading the xml string from the database].
/// </summary>
public delegate void ContentCacheDatabaseLoadXmlStringEventHandler(ref string xml, cms.businesslogic.ContentCacheLoadNodeEventArgs e);
/// <summary>
/// Occurs when [after loading the xml string from the database].
/// </summary>
@@ -766,7 +779,7 @@ namespace umbraco
/// </summary>
/// <param name="node">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.ContentCacheLoadNodeEventArgs"/> instance containing the event data.</param>
internal static void FireAfterContentCacheDatabaseLoadXmlString(ref string xml, cms.businesslogic.ContentCacheLoadNodeEventArgs e)
internal static void FireAfterContentCacheDatabaseLoadXmlString(ref string xml, ContentCacheLoadNodeEventArgs e)
{
if (AfterContentCacheDatabaseLoadXmlString != null)
{
@@ -784,7 +797,7 @@ namespace umbraco
/// </summary>
/// <param name="node">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.ContentCacheLoadNodeEventArgs"/> instance containing the event data.</param>
internal static void FireBeforeContentCacheLoadNode(XmlNode node, cms.businesslogic.ContentCacheLoadNodeEventArgs e)
internal static void FireBeforeContentCacheLoadNode(XmlNode node, ContentCacheLoadNodeEventArgs e)
{
if (BeforeContentCacheLoadNode != null)
{
@@ -802,7 +815,7 @@ namespace umbraco
/// </summary>
/// <param name="node">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.ContentCacheLoadNodeEventArgs"/> instance containing the event data.</param>
internal static void FireAfterContentCacheLoadNodeFromDatabase(XmlNode node, cms.businesslogic.ContentCacheLoadNodeEventArgs e)
internal static void FireAfterContentCacheLoadNodeFromDatabase(XmlNode node, ContentCacheLoadNodeEventArgs e)
{
if (AfterContentCacheLoadNodeFromDatabase != null)
{
@@ -820,7 +833,7 @@ namespace umbraco
/// </summary>
/// <param name="node">The sender.</param>
/// <param name="e">The <see cref="umbraco.cms.businesslogic.ContentCacheLoadNodeEventArgs"/> instance containing the event data.</param>
public static void FireBeforePublishNodeToContentCache(XmlNode node, cms.businesslogic.ContentCacheLoadNodeEventArgs e)
public static void FireBeforePublishNodeToContentCache(XmlNode node, ContentCacheLoadNodeEventArgs e)
{
if (BeforePublishNodeToContentCache != null)
{
@@ -828,11 +841,46 @@ namespace umbraco
}
}
#endregion
#region Protected & Private methods
internal const string PersistenceFlagContextKey = "vnc38ykjnkjdnk2jt98ygkxjng";
internal bool IsXmlQueuedForPersistenceToFile
{
get
{
if (HttpContext.Current != null)
{
bool val = HttpContext.Current.Application[PersistenceFlagContextKey] != null;
if (val)
{
DateTime persistenceTime = DateTime.MinValue;
try
{
persistenceTime = (DateTime)HttpContext.Current.Application[PersistenceFlagContextKey];
if (persistenceTime > GetCacheFileUpdateTime())
{
return true;
}
else
{
HttpContext.Current.Application.Lock();
HttpContext.Current.Application[PersistenceFlagContextKey] = null;
HttpContext.Current.Application.UnLock();
}
}
catch
{
// Nothing to catch here - we'll just persist
}
}
}
return false;
}
}
/// <summary>
/// Invalidates the disk content cache file. Effectively just deletes it.
/// </summary>
@@ -919,7 +967,7 @@ namespace umbraco
{
lock (_readerWriterSyncLock)
{
XmlDocument xmlDoc = new XmlDocument();
var xmlDoc = new XmlDocument();
Log.Add(LogTypes.System, User.GetUser(0), -1, "Loading content from disk cache...");
xmlDoc.Load(UmbracoXmlDiskCacheFileName);
return xmlDoc;
@@ -943,13 +991,12 @@ namespace umbraco
// and we need to guarantee it won't tear down the app pool by throwing an unhandled exception
try
{
// Moved User to a local variable - why are we causing user 0 to load from the DB though?
// Alex N 20100212
User staticUser = null;
try
{
staticUser = User.GetCurrent(); //User.GetUser(0);
staticUser = User.GetCurrent(); //User.GetUser(0);
}
catch
{
@@ -967,7 +1014,7 @@ namespace umbraco
Log.Add(LogTypes.Debug, staticUser, -1, "Republishing starting");
// Lets cache the DTD to save on the DB hit on the subsequent use
var dtd = DocumentType.GenerateDtd();
string dtd = DocumentType.GenerateDtd();
// Prepare an XmlDocument with an appropriate inline DTD to match
// the expected content
@@ -982,14 +1029,18 @@ order by umbracoNode.level, umbracoNode.sortOrder";
lock (_dbReadSyncLock)
{
using (IRecordsReader dr = SqlHelper.ExecuteReader(sql, SqlHelper.CreateParameter("@type", new Guid("C66BA18E-EAF3-4CFF-8A22-41B16D66A972"))))
using (
IRecordsReader dr = SqlHelper.ExecuteReader(sql,
SqlHelper.CreateParameter("@type",
new Guid(
"C66BA18E-EAF3-4CFF-8A22-41B16D66A972")))
)
{
while (dr.Read())
{
int currentId = dr.GetInt("id");
int parentId = dr.GetInt("parentId");
var xml = dr.GetString("xml");
string xml = dr.GetString("xml");
// Call the eventhandler to allow modification of the string
var e1 = new ContentCacheLoadNodeEventArgs();
@@ -999,7 +1050,7 @@ order by umbracoNode.level, umbracoNode.sortOrder";
{
// and parse it into a DOM node
xmlDoc.LoadXml(xml);
var node = xmlDoc.FirstChild;
XmlNode node = xmlDoc.FirstChild;
// same event handler loader form the xml node
var e2 = new ContentCacheLoadNodeEventArgs();
FireAfterContentCacheLoadNodeFromDatabase(node, e2);
@@ -1073,30 +1124,37 @@ order by umbracoNode.level, umbracoNode.sortOrder";
return null;
}
private static void GenerateXmlDocument(IDictionary<int, List<int>> hierarchy, IDictionary<int, XmlNode> nodeIndex, int parentId, XmlNode parentNode)
private static void GenerateXmlDocument(IDictionary<int, List<int>> hierarchy,
IDictionary<int, XmlNode> nodeIndex, int parentId, XmlNode parentNode)
{
List<int> children;
if (hierarchy.TryGetValue(parentId, out children))
{
XmlNode childContainer = UmbracoSettings.UseLegacyXmlSchema || String.IsNullOrEmpty(UmbracoSettings.TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME)
XmlNode childContainer = UmbracoSettings.UseLegacyXmlSchema ||
String.IsNullOrEmpty(UmbracoSettings.TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME)
? parentNode
: parentNode.SelectSingleNode(UmbracoSettings.TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME);
: parentNode.SelectSingleNode(
UmbracoSettings.TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME);
if (!UmbracoSettings.UseLegacyXmlSchema && !String.IsNullOrEmpty(UmbracoSettings.TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME))
if (!UmbracoSettings.UseLegacyXmlSchema &&
!String.IsNullOrEmpty(UmbracoSettings.TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME))
{
if (childContainer == null)
{
childContainer = xmlHelper.addTextNode(parentNode.OwnerDocument, UmbracoSettings.TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME, "");
childContainer = xmlHelper.addTextNode(parentNode.OwnerDocument,
UmbracoSettings.
TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME, "");
parentNode.AppendChild(childContainer);
}
}
foreach (int childId in children)
{
var childNode = nodeIndex[childId];
XmlNode childNode = nodeIndex[childId];
if (UmbracoSettings.UseLegacyXmlSchema || String.IsNullOrEmpty(UmbracoSettings.TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME))
if (UmbracoSettings.UseLegacyXmlSchema ||
String.IsNullOrEmpty(UmbracoSettings.TEMP_FRIENDLY_XML_CHILD_CONTAINER_NODENAME))
{
parentNode.AppendChild(childNode);
}
@@ -1126,7 +1184,8 @@ order by umbracoNode.level, umbracoNode.sortOrder";
{
if (xmlDoc != null)
{
Trace.Write(string.Format("Saving content to disk on thread '{0}' (Threadpool? {1})", Thread.CurrentThread.Name, Thread.CurrentThread.IsThreadPoolThread.ToString()));
Trace.Write(string.Format("Saving content to disk on thread '{0}' (Threadpool? {1})",
Thread.CurrentThread.Name, Thread.CurrentThread.IsThreadPoolThread));
// Moved the user into a variable and avoided it throwing an error if one can't be loaded (e.g. empty / corrupt db on initial install)
User staticUser = null;
@@ -1135,7 +1194,8 @@ order by umbracoNode.level, umbracoNode.sortOrder";
staticUser = User.GetCurrent();
}
catch
{ }
{
}
try
{
@@ -1144,7 +1204,7 @@ order by umbracoNode.level, umbracoNode.sortOrder";
DeleteXmlCache();
// Try to create directory for cache path if it doesn't yet exist
var directoryName = Path.GetDirectoryName(UmbracoXmlDiskCacheFileName);
string directoryName = Path.GetDirectoryName(UmbracoXmlDiskCacheFileName);
if (!File.Exists(UmbracoXmlDiskCacheFileName) && !Directory.Exists(directoryName))
{
// We're already in a try-catch and saving will fail if this does, so don't need another
@@ -1153,7 +1213,9 @@ order by umbracoNode.level, umbracoNode.sortOrder";
xmlDoc.Save(UmbracoXmlDiskCacheFileName);
Trace.Write(string.Format("Saved content on thread '{0}' in {1} (Threadpool? {2})", Thread.CurrentThread.Name, stopWatch.Elapsed, Thread.CurrentThread.IsThreadPoolThread.ToString()));
Trace.Write(string.Format("Saved content on thread '{0}' in {1} (Threadpool? {2})",
Thread.CurrentThread.Name, stopWatch.Elapsed,
Thread.CurrentThread.IsThreadPoolThread));
Log.Add(LogTypes.Debug, staticUser, -1, string.Format("Xml saved in {0}", stopWatch.Elapsed));
}
@@ -1162,14 +1224,15 @@ order by umbracoNode.level, umbracoNode.sortOrder";
// If for whatever reason something goes wrong here, invalidate disk cache
DeleteXmlCache();
Trace.Write(string.Format("Error saving content on thread '{0}' due to '{1}' (Threadpool? {2})", Thread.CurrentThread.Name, ee.Message, Thread.CurrentThread.IsThreadPoolThread.ToString()));
Trace.Write(string.Format(
"Error saving content on thread '{0}' due to '{1}' (Threadpool? {2})",
Thread.CurrentThread.Name, ee.Message, Thread.CurrentThread.IsThreadPoolThread));
Log.Add(LogTypes.Error, staticUser, -1, string.Format("Xml wasn't saved: {0}", ee));
}
}
}
}
internal const string PersistenceFlagContextKey = "vnc38ykjnkjdnk2jt98ygkxjng";
/// <summary>
/// Marks a flag in the HttpContext so that, upon page execution completion, the Xml cache will
/// get persisted to disk. Ensure this method is only called from a thread executing a page request
@@ -1191,7 +1254,6 @@ order by umbracoNode.level, umbracoNode.sortOrder";
}
else
{
//// Save copy of content
if (UmbracoSettings.CloneXmlCacheOnPublish)
{
@@ -1199,7 +1261,6 @@ order by umbracoNode.level, umbracoNode.sortOrder";
ThreadPool.QueueUserWorkItem(
delegate { PersistXmlToFile(xmlContentCopy); });
}
else
ThreadPool.QueueUserWorkItem(
@@ -1207,43 +1268,9 @@ order by umbracoNode.level, umbracoNode.sortOrder";
}
}
internal bool IsXmlQueuedForPersistenceToFile
{
get
{
if (HttpContext.Current != null)
{
var val = HttpContext.Current.Application[PersistenceFlagContextKey] != null;
if (val != false)
{
DateTime persistenceTime = DateTime.MinValue;
try
{
persistenceTime = (DateTime)HttpContext.Current.Application[PersistenceFlagContextKey];
if (persistenceTime > GetCacheFileUpdateTime())
{
return true;
}
else
{
HttpContext.Current.Application.Lock();
HttpContext.Current.Application[PersistenceFlagContextKey] = null;
HttpContext.Current.Application.UnLock();
}
}
catch
{
// Nothing to catch here - we'll just persist
}
}
}
return false;
}
}
internal DateTime GetCacheFileUpdateTime()
{
if (System.IO.File.Exists(UmbracoXmlDiskCacheFileName))
if (File.Exists(UmbracoXmlDiskCacheFileName))
{
return new FileInfo(UmbracoXmlDiskCacheFileName).LastWriteTime;
}
@@ -1262,7 +1289,7 @@ order by umbracoNode.level, umbracoNode.sortOrder";
Log.Add(LogTypes.Debug, -1, "Cloning...");
// Save copy of content
XmlDocument xmlCopy = (XmlDocument)xmlDoc.CloneNode(true);
var xmlCopy = (XmlDocument)xmlDoc.CloneNode(true);
Log.Add(LogTypes.Debug, -1, "Cloning ended...");
return xmlCopy;
}

View File

@@ -1696,9 +1696,12 @@ namespace umbraco
/// <returns>Returns the node with the specified id as xml in the form of a XPathNodeIterator</returns>
public static XPathNodeIterator GetXmlNodeById(string id)
{
if (UmbracoContext.Current.GetXml().GetElementById(id) != null)
// 4.7.1 UmbracoContext is null if we're running in publishing thread which we need to support
XmlDocument xmlDoc = GetThreadsafeXmlDocument();
if (xmlDoc.GetElementById(id) != null)
{
XPathNavigator xp = UmbracoContext.Current.GetXml().CreateNavigator();
XPathNavigator xp = xmlDoc.CreateNavigator();
xp.MoveToId(id);
return xp.Select(".");
}
@@ -1710,6 +1713,13 @@ namespace umbraco
}
}
private static XmlDocument GetThreadsafeXmlDocument()
{
return UmbracoContext.Current != null
? UmbracoContext.Current.GetXml()
: content.Instance.XmlContent;
}
/// <summary>
/// Queries the umbraco Xml cache with the specified Xpath query
/// </summary>
@@ -1717,7 +1727,7 @@ namespace umbraco
/// <returns>Returns nodes matching the xpath query as a XpathNodeIterator</returns>
public static XPathNodeIterator GetXmlNodeByXPath(string xpathQuery)
{
XPathNavigator xp = content.Instance.XmlContent.CreateNavigator();
XPathNavigator xp = GetThreadsafeXmlDocument().CreateNavigator();
return xp.Select(xpathQuery);
}
@@ -1728,7 +1738,7 @@ namespace umbraco
/// <returns>Returns the entire umbraco Xml cache as a XPathNodeIterator</returns>
public static XPathNodeIterator GetXmlAll()
{
XPathNavigator xp = UmbracoContext.Current.GetXml().CreateNavigator();
XPathNavigator xp = GetThreadsafeXmlDocument().CreateNavigator();
return xp.Select("/root");
}

View File

@@ -33,7 +33,7 @@ namespace umbraco.presentation
{
try
{
//d.HttpContext = (HttpContext)sender;
//d.HttpContext = (HttpContext)sender;
d.ReleaseDate = DateTime.MinValue; //new DateTime(1, 1, 1); // Causes release date to be null

View File

@@ -381,7 +381,7 @@ namespace umbraco.presentation
pingTimer = new Timer(new TimerCallback(keepAliveService.PingUmbraco), HttpApp.Context, 60000, 300000);
// Start publishingservice
publishingTimer = new Timer(new TimerCallback(publishingService.CheckPublishing), HttpApp.Context, 600000, 60000);
publishingTimer = new Timer(new TimerCallback(publishingService.CheckPublishing), HttpApp.Context, 30000, 60000);
//Find Applications and event handlers and hook-up the events
//BusinessLogic.Application.RegisterIApplications();

View File

@@ -483,7 +483,7 @@ namespace umbraco.controls
else
{
Panel ph = new Panel();
ph.Attributes.Add("style", "padding: 0; position: relative; z-index: 1;"); // NH 4.7.1, latest styles added to support CP item: 30363
ph.Attributes.Add("style", "padding: 0; position: relative;"); // NH 4.7.1, latest styles added to support CP item: 30363
ph.Controls.Add(pp);
tp.Controls.Add(ph);

View File

@@ -297,7 +297,15 @@ namespace umbraco.NodeFactory
_pageXmlNode = ((IHasXmlNode)library.GetXmlNodeById(NodeId.ToString()).Current).GetNode();
else
{
_pageXmlNode = umbraco.presentation.UmbracoContext.Current.GetXml().DocumentElement;
if (presentation.UmbracoContext.Current != null)
{
_pageXmlNode = umbraco.presentation.UmbracoContext.Current.GetXml().DocumentElement;
}
else
{
_pageXmlNode = content.Instance.XmlContent.DocumentElement;
}
}
initializeStructure();
@@ -566,8 +574,8 @@ namespace umbraco.NodeFactory
);
}
}
// else
// throw new ArgumentNullException("Node xml source is null");
// else
// throw new ArgumentNullException("Node xml source is null");
}
public static Node GetCurrent()
@@ -583,7 +591,7 @@ namespace umbraco.NodeFactory
throw new ArgumentException("Current node is null. This might be due to previewing an unpublished node. As the NodeFactory works with published data, macros using the node factory won't work in preview mode.", "Current node is " + System.Web.HttpContext.Current.Items["pageID"].ToString());
return int.Parse(n.Attributes.GetNamedItem("id").Value);
}
}
}
public class Nodes : CollectionBase

View File

@@ -131,7 +131,7 @@ namespace umbraco.presentation.nodeFactory {
BusinessLogic.Log.Add(
LogTypes.Error,
child.Id,
String.Format("Error adding to SiteMapProvider: {0}", ex));
String.Format("Error adding to SiteMapProvider in loadNodes(): {0}", ex));
}
loadNodes(child.Id.ToString(), childNode);
}
@@ -177,7 +177,6 @@ namespace umbraco.presentation.nodeFactory {
lock (this) {
if (m_nodes.ContainsKey(id))
throw new ProviderException(String.Format("A node with id '{0}' already exists", id));
// Get title, URL, description, and roles from the DataReader
// If roles were specified, turn the list into a string array