Ensure U4-8720 is properly merged into v8
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web.PublishedCache.NuCache;
|
||||
|
||||
@@ -448,7 +449,7 @@ namespace Umbraco.Tests.Cache
|
||||
|
||||
Assert.AreEqual(3, d.Test.LiveGen);
|
||||
Assert.IsFalse(d.Test.NextGen);
|
||||
|
||||
|
||||
Assert.AreEqual(3, d.SnapCount);
|
||||
|
||||
s1.Dispose();
|
||||
@@ -706,5 +707,38 @@ namespace Umbraco.Tests.Cache
|
||||
Assert.IsFalse(d.Test.NextGen);
|
||||
Assert.AreEqual("ein", s4.Get(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetAll()
|
||||
{
|
||||
var d = new SnapDictionary<int, string>();
|
||||
d.Test.CollectAuto = false;
|
||||
|
||||
Assert.AreEqual(0, d.Test.GetValues(1).Length);
|
||||
|
||||
d.Set(1, "one");
|
||||
d.Set(2, "two");
|
||||
d.Set(3, "three");
|
||||
d.Set(4, "four");
|
||||
|
||||
var s1 = d.CreateSnapshot();
|
||||
var all = s1.GetAll().ToArray();
|
||||
Assert.AreEqual(4, all.Length);
|
||||
Assert.AreEqual("one", all[0]);
|
||||
Assert.AreEqual("four", all[3]);
|
||||
|
||||
d.Set(1, "uno");
|
||||
var s2 = d.CreateSnapshot();
|
||||
|
||||
all = s1.GetAll().ToArray();
|
||||
Assert.AreEqual(4, all.Length);
|
||||
Assert.AreEqual("one", all[0]);
|
||||
Assert.AreEqual("four", all[3]);
|
||||
|
||||
all = s2.GetAll().ToArray();
|
||||
Assert.AreEqual(4, all.Length);
|
||||
Assert.AreEqual("uno", all[0]);
|
||||
Assert.AreEqual("four", all[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,8 @@ namespace Umbraco.Tests.PublishedContent
|
||||
base.MoreSetUp();
|
||||
}
|
||||
|
||||
private readonly Guid _node1173Guid = Guid.NewGuid();
|
||||
|
||||
protected override string GetXmlContent(int templateId)
|
||||
{
|
||||
return @"<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
@@ -87,7 +89,7 @@ namespace Umbraco.Tests.PublishedContent
|
||||
<umbracoUrlAlias><![CDATA[this/is/my/alias, anotheralias]]></umbracoUrlAlias>
|
||||
<umbracoNaviHide>1</umbracoNaviHide>
|
||||
<testRecursive><![CDATA[This is the recursive val]]></testRecursive>
|
||||
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""">
|
||||
<Home id=""1173"" parentID=""1046"" level=""2"" writerID=""0"" creatorID=""0"" nodeType=""1044"" template=""" + templateId + @""" sortOrder=""1"" createDate=""2012-07-20T18:06:45"" updateDate=""2012-07-20T19:07:31"" nodeName=""Sub1"" urlName=""sub1"" writerName=""admin"" creatorName=""admin"" path=""-1,1046,1173"" isDoc="""" key=""" + _node1173Guid + @""">
|
||||
<content><![CDATA[<div>This is some content</div>]]></content>
|
||||
<umbracoUrlAlias><![CDATA[page2/alias, 2ndpagealias]]></umbracoUrlAlias>
|
||||
<testRecursive><![CDATA[]]></testRecursive>
|
||||
@@ -122,6 +124,23 @@ namespace Umbraco.Tests.PublishedContent
|
||||
return doc;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GetNodeByIds()
|
||||
{
|
||||
var ctx = GetUmbracoContext("/test");
|
||||
var contentById = ctx.ContentCache.GetById(1173);
|
||||
Assert.IsNotNull(contentById);
|
||||
var contentByGuid = ctx.ContentCache.GetById(_node1173Guid);
|
||||
Assert.IsNotNull(contentByGuid);
|
||||
Assert.AreEqual(contentById.Id, contentByGuid.Id);
|
||||
Assert.AreEqual(contentById.Key, contentByGuid.Key);
|
||||
|
||||
contentById = ctx.ContentCache.GetById(666);
|
||||
Assert.IsNull(contentById);
|
||||
contentByGuid = ctx.ContentCache.GetById(Guid.NewGuid());
|
||||
Assert.IsNull(contentByGuid);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Is_Last_From_Where_Filter_Dynamic_Linq()
|
||||
{
|
||||
|
||||
@@ -21,9 +21,9 @@ namespace Umbraco.Web
|
||||
IEnumerable<IPublishedContent> ContentAtRoot();
|
||||
|
||||
IPublishedContent Media(int id);
|
||||
//IPublishedContent Media(Guid id);
|
||||
IPublishedContent Media(Guid id);
|
||||
IEnumerable<IPublishedContent> Media(IEnumerable<int> ids);
|
||||
//IEnumerable<IPublishedContent> Media(IEnumerable<Guid> ids);
|
||||
IEnumerable<IPublishedContent> Media(IEnumerable<Guid> ids);
|
||||
IEnumerable<IPublishedContent> MediaAtRoot();
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -15,7 +15,7 @@ using Umbraco.Web.Routing;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigableData, IDisposable
|
||||
internal class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigableData, IDisposable
|
||||
{
|
||||
private readonly ContentStore2.Snapshot _snapshot;
|
||||
private readonly ICacheProvider _facadeCache;
|
||||
@@ -209,11 +209,15 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
: n.Published;
|
||||
}
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Guid nodeId)
|
||||
public override IPublishedContent GetById(bool preview, Guid contentId)
|
||||
{
|
||||
// fixme - implement in a more efficient way
|
||||
const string xpath = "//* [@isDoc and @key=$guid]";
|
||||
return GetSingleByXPath(preview, xpath, new[] { new XPathVariable("guid", nodeId.ToString()) });
|
||||
var n = _snapshot.Get(contentId);
|
||||
if (n == null) return null;
|
||||
|
||||
// both .Draft and .Published cannot be null at the same time
|
||||
return preview
|
||||
? n.Draft ?? GetPublishedContentAsPreviewing(n.Published)
|
||||
: n.Published;
|
||||
}
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
_localDb = null;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Content types
|
||||
@@ -295,7 +295,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// unknown = bad
|
||||
if (_contentTypesById.TryGetValue(kit.ContentTypeId, out link) == false || link.Value == null)
|
||||
return false;
|
||||
|
||||
|
||||
// not checking ByAlias, assuming we don't have internal errors
|
||||
|
||||
// register
|
||||
@@ -560,7 +560,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// already in the dict
|
||||
if (link.Gen != _liveGen)
|
||||
{
|
||||
// for an older gen - if value is different then insert a new
|
||||
// for an older gen - if value is different then insert a new
|
||||
// link for the new gen, with the new value
|
||||
if (link.Value != value)
|
||||
dict.TryUpdate(key, new LinkedNode<TValue>(value, _liveGen, link), link);
|
||||
@@ -619,7 +619,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
break;
|
||||
link = link.Next;
|
||||
}
|
||||
if (link != null && link.Value != null)
|
||||
if (link?.Value != null)
|
||||
yield return Get(kvp.Key, gen);
|
||||
}
|
||||
}
|
||||
@@ -638,6 +638,27 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return null;
|
||||
}
|
||||
|
||||
public IEnumerable<ContentNode> GetAll(long gen)
|
||||
{
|
||||
// enumerating on .Values locks the concurrent dictionary,
|
||||
// so better get a shallow clone in an array and release
|
||||
var links = _contentNodes.Values.ToArray();
|
||||
foreach (var l in links)
|
||||
{
|
||||
var link = l;
|
||||
while (link != null)
|
||||
{
|
||||
if (link.Gen <= gen)
|
||||
{
|
||||
if (link.Value != null)
|
||||
yield return link.Value;
|
||||
break;
|
||||
}
|
||||
link = link.Next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEmpty(long gen)
|
||||
{
|
||||
var has = _contentNodes.Any(x =>
|
||||
@@ -737,7 +758,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
if (_collectTask != null)
|
||||
return _collectTask;
|
||||
|
||||
|
||||
// ReSharper disable InconsistentlySynchronizedField
|
||||
var task = _collectTask = Task.Run(() => Collect());
|
||||
_collectTask.ContinueWith(_ =>
|
||||
@@ -795,7 +816,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
#if DEBUG
|
||||
//_logger.Debug<ContentStore2>("Collect id:" + kvp.Key + ", gen:" + link.Gen +
|
||||
// ", nxt:" + (link.Next == null ? "null" : "link") +
|
||||
// ", nxt:" + (link.Next == null ? "null" : "link") +
|
||||
// ", val:" + (link.Value == null ? "null" : "value"));
|
||||
#endif
|
||||
|
||||
@@ -807,7 +828,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
if (link.Gen < liveGen && link.Value == null
|
||||
&& (link.Next == null || link.Gen <= _floorGen))
|
||||
{
|
||||
// not live, null value, no next link = remove that one -- but only if
|
||||
// not live, null value, no next link = remove that one -- but only if
|
||||
// the dict has not been updated, have to do it via ICollection<> (thanks
|
||||
// Mr Toub) -- and if the dict has been updated there is nothing to collect
|
||||
var idict = dict as ICollection<KeyValuePair<TKey, LinkedNode<TValue>>>;
|
||||
@@ -891,7 +912,7 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
}
|
||||
|
||||
internal TestHelper Test { get { return _unitTesting ?? (_unitTesting = new TestHelper(this)); } }
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Classes
|
||||
@@ -951,6 +972,14 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return _store.Get(id, _gen);
|
||||
}
|
||||
|
||||
public ContentNode Get(Guid id)
|
||||
{
|
||||
if (_gen < 0)
|
||||
throw new ObjectDisposedException("snapshot" /*+ " (" + _thisCount + ")"*/);
|
||||
// fixme - optimize with an index - getAll/iterating is expensive
|
||||
return _store.GetAll(_gen).FirstOrDefault(x => x.Uid == id);
|
||||
}
|
||||
|
||||
public IEnumerable<ContentNode> GetAtRoot()
|
||||
{
|
||||
if (_gen < 0)
|
||||
@@ -972,6 +1001,17 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
return _store.GetContentType(alias, _gen);
|
||||
}
|
||||
|
||||
// this code is here just so you don't try to implement it
|
||||
// the only way we can iterate over "all" without locking the entire cache forever
|
||||
// is by shallow cloning the cache, which is quite expensive, so we should probably not do it,
|
||||
// and implement cache-level indexes
|
||||
//public IEnumerable<ContentNode> GetAll()
|
||||
//{
|
||||
// if (_gen < 0)
|
||||
// throw new ObjectDisposedException("snapshot" /*+ " (" + _thisCount + ")"*/);
|
||||
// return _store.GetAll(_gen);
|
||||
//}
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
using Umbraco.Core.Xml;
|
||||
using Umbraco.Core.Xml.XPath;
|
||||
@@ -12,7 +10,7 @@ using Umbraco.Web.PublishedCache.NuCache.Navigable;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.NuCache
|
||||
{
|
||||
class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableData, IDisposable
|
||||
internal class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableData, IDisposable
|
||||
{
|
||||
private readonly ContentStore2.Snapshot _snapshot;
|
||||
private readonly ICacheProvider _facadeCache;
|
||||
@@ -40,9 +38,8 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Guid contentId)
|
||||
{
|
||||
// fixme - test + implement in a more efficient way
|
||||
const string xpath = "//* [@isDoc and @key=$guid]";
|
||||
return GetSingleByXPath(preview, xpath, new[] { new XPathVariable("guid", contentId.ToString()) });
|
||||
var n = _snapshot.Get(contentId);
|
||||
return n?.Published;
|
||||
}
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
|
||||
@@ -252,16 +252,20 @@ namespace Umbraco.Web.PublishedCache.NuCache
|
||||
// enumerating on .Values locks the concurrent dictionary,
|
||||
// so better get a shallow clone in an array and release
|
||||
var links = _items.Values.ToArray();
|
||||
return links.Select(link =>
|
||||
foreach (var l in links)
|
||||
{
|
||||
var link = l;
|
||||
while (link != null)
|
||||
{
|
||||
if (link.Gen <= gen)
|
||||
return link.Value; // may be null
|
||||
{
|
||||
if (link.Value != null)
|
||||
yield return link.Value;
|
||||
break;
|
||||
}
|
||||
link = link.Next;
|
||||
}
|
||||
return null;
|
||||
}).Where(x => x != null);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEmpty(long gen)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Xml.XPath;
|
||||
using Umbraco.Core.Configuration;
|
||||
@@ -11,8 +10,6 @@ using Umbraco.Core.Xml;
|
||||
using Umbraco.Web.Routing;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Services;
|
||||
using Task = System.Threading.Tasks.Task;
|
||||
|
||||
namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
{
|
||||
@@ -358,9 +355,45 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache
|
||||
|
||||
public override IPublishedContent GetById(bool preview, Guid nodeId)
|
||||
{
|
||||
// todo - implement in a more efficient way
|
||||
const string xpath = "//* [@isDoc and @key=$guid]";
|
||||
return GetSingleByXPath(preview, xpath, new [] { new XPathVariable("guid", nodeId.ToString()) });
|
||||
// implement this, but in a more efficient way
|
||||
//const string xpath = "//* [@isDoc and @key=$guid]";
|
||||
//return GetSingleByXPath(preview, xpath, new[] { new XPathVariable("guid", nodeId.ToString()) });
|
||||
|
||||
var keyMatch = nodeId.ToString();
|
||||
|
||||
var nav = GetXml(preview).CreateNavigator();
|
||||
if (nav.MoveToFirstChild() == false) return null; // from / to /root
|
||||
if (nav.MoveToFirstChild() == false) return null; // from /root to /root/*
|
||||
|
||||
while (true)
|
||||
{
|
||||
var isDoc = false;
|
||||
string key = null;
|
||||
|
||||
if (nav.HasAttributes)
|
||||
{
|
||||
nav.MoveToFirstAttribute();
|
||||
do
|
||||
{
|
||||
if (nav.Name == "isDoc") isDoc = true;
|
||||
if (nav.Name == "key") key = nav.Value;
|
||||
if (isDoc && key != null) break;
|
||||
} while (nav.MoveToNextAttribute());
|
||||
nav.MoveToParent();
|
||||
}
|
||||
|
||||
if (isDoc == false || key != keyMatch)
|
||||
{
|
||||
if (isDoc && nav.MoveToFirstChild())
|
||||
continue;
|
||||
while (nav.MoveToNext(XPathNodeType.Element) == false)
|
||||
if (nav.MoveToParent() == false || nav.NodeType == XPathNodeType.Root) return null;
|
||||
continue;
|
||||
}
|
||||
|
||||
var elt = nav.UnderlyingObject as XmlNode;
|
||||
return ConvertToDocument(elt, preview);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HasById(bool preview, int contentId)
|
||||
|
||||
@@ -110,6 +110,13 @@ namespace Umbraco.Web
|
||||
: _query.Media(id);
|
||||
}
|
||||
|
||||
public IPublishedContent Media(Guid id)
|
||||
{
|
||||
return _query == null
|
||||
? ItemById(id, _mediaCache)
|
||||
: _query.Media(id);
|
||||
}
|
||||
|
||||
public IEnumerable<IPublishedContent> Media(IEnumerable<int> ids)
|
||||
{
|
||||
return _query == null
|
||||
@@ -117,6 +124,13 @@ namespace Umbraco.Web
|
||||
: _query.Media(ids);
|
||||
}
|
||||
|
||||
public IEnumerable<IPublishedContent> Media(IEnumerable<Guid> ids)
|
||||
{
|
||||
return _query == null
|
||||
? ItemsByIds(_mediaCache, ids)
|
||||
: _query.Media(ids);
|
||||
}
|
||||
|
||||
public IEnumerable<IPublishedContent> MediaAtRoot()
|
||||
{
|
||||
return _query == null
|
||||
|
||||
@@ -670,7 +670,7 @@ namespace Umbraco.Web
|
||||
int intId;
|
||||
if (ConvertIdObjectToInt(id, out intId))
|
||||
return ContentQuery.Media(intId);
|
||||
Guid guidId;
|
||||
//Guid guidId;
|
||||
//if (ConvertIdObjectToGuid(id, out guidId))
|
||||
// return ContentQuery.Media(guidId);
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user