diff --git a/src/Umbraco.Core/Cache/IJsonCacheRefresher.cs b/src/Umbraco.Core/Cache/IJsonCacheRefresher.cs
index c72c2569a1..006cc4fec0 100644
--- a/src/Umbraco.Core/Cache/IJsonCacheRefresher.cs
+++ b/src/Umbraco.Core/Cache/IJsonCacheRefresher.cs
@@ -7,7 +7,10 @@ namespace Umbraco.Core.Cache
///
interface IJsonCacheRefresher : ICacheRefresher
{
+ ///
+ /// Refreshes, clears, etc... any cache based on the information provided in the json
+ ///
+ ///
void Refresh(string jsonPayload);
- void Remove(string jsonPayload);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Cache/JsonCacheRefresherBase.cs b/src/Umbraco.Core/Cache/JsonCacheRefresherBase.cs
index 72c484645b..708e2e1605 100644
--- a/src/Umbraco.Core/Cache/JsonCacheRefresherBase.cs
+++ b/src/Umbraco.Core/Cache/JsonCacheRefresherBase.cs
@@ -16,10 +16,5 @@ namespace Umbraco.Core.Cache
{
OnCacheUpdated(Instance, new CacheRefresherEventArgs(jsonPayload, MessageType.RefreshByJson));
}
-
- public virtual void Remove(string jsonPayload)
- {
- OnCacheUpdated(Instance, new CacheRefresherEventArgs(jsonPayload, MessageType.RemoveByJson));
- }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Sync/DefaultServerMessenger.cs b/src/Umbraco.Core/Sync/DefaultServerMessenger.cs
index 973bbb055d..0f9e81d7fd 100644
--- a/src/Umbraco.Core/Sync/DefaultServerMessenger.cs
+++ b/src/Umbraco.Core/Sync/DefaultServerMessenger.cs
@@ -91,15 +91,6 @@ namespace Umbraco.Core.Sync
instances);
}
- public void PerformRemove(IEnumerable servers, ICacheRefresher refresher, string jsonPayload)
- {
- if (servers == null) throw new ArgumentNullException("servers");
- if (refresher == null) throw new ArgumentNullException("refresher");
- if (jsonPayload == null) throw new ArgumentNullException("jsonPayload");
-
- MessageSeversForIdsOrJson(servers, refresher, MessageType.RemoveByJson, jsonPayload: jsonPayload);
- }
-
public void PerformRemove(IEnumerable servers, ICacheRefresher refresher, Func getNumericId, params T[] instances)
{
if (servers == null) throw new ArgumentNullException("servers");
@@ -283,15 +274,7 @@ namespace Umbraco.Core.Sync
}
//if we are not, then just invoke the call on the cache refresher
- switch (dispatchType)
- {
- case MessageType.RefreshByJson:
- jsonRefresher.Refresh(jsonPayload);
- break;
- case MessageType.RemoveByJson:
- jsonRefresher.Remove(jsonPayload);
- break;
- }
+ jsonRefresher.Refresh(jsonPayload);
}
}
}
@@ -380,12 +363,7 @@ namespace Umbraco.Core.Sync
asyncResultsList.Add(
cacheRefresher.BeginRefreshByJson(
refresher.UniqueIdentifier, jsonPayload, _login, _password, null, null));
- break;
- case MessageType.RemoveByJson:
- asyncResultsList.Add(
- cacheRefresher.BeginRemoveByJson(
- refresher.UniqueIdentifier, jsonPayload, _login, _password, null, null));
- break;
+ break;
case MessageType.RefreshAll:
asyncResultsList.Add(
cacheRefresher.BeginRefreshAll(
@@ -438,9 +416,6 @@ namespace Umbraco.Core.Sync
case MessageType.RefreshByJson:
cacheRefresher.EndRefreshByJson(t);
break;
- case MessageType.RemoveByJson:
- cacheRefresher.EndRemoveByJson(t);
- break;
case MessageType.RefreshAll:
cacheRefresher.EndRefreshAll(t);
break;
diff --git a/src/Umbraco.Core/Sync/IServerMessenger.cs b/src/Umbraco.Core/Sync/IServerMessenger.cs
index b39a6367db..45e0a92385 100644
--- a/src/Umbraco.Core/Sync/IServerMessenger.cs
+++ b/src/Umbraco.Core/Sync/IServerMessenger.cs
@@ -40,16 +40,6 @@ namespace Umbraco.Core.Sync
///
void PerformRefresh(IEnumerable servers, ICacheRefresher refresher, Func getGuidId, params T[] instances);
- ///
- /// Performs a remove and sends along the JSON payload to each server
- ///
- ///
- ///
- ///
- /// A pre-formatted custom json payload to be sent to the servers, the cache refresher will deserialize and use to remove cache
- ///
- void PerformRemove(IEnumerable servers, ICacheRefresher refresher, string jsonPayload);
-
///
/// Removes the cache for the specified items
///
diff --git a/src/Umbraco.Core/Sync/MessageType.cs b/src/Umbraco.Core/Sync/MessageType.cs
index 3c107fba8c..aa8733be33 100644
--- a/src/Umbraco.Core/Sync/MessageType.cs
+++ b/src/Umbraco.Core/Sync/MessageType.cs
@@ -9,7 +9,6 @@
RefreshById,
RefreshByJson,
RemoveById,
- RemoveByJson,
RefreshByInstance,
RemoveByInstance
}
diff --git a/src/Umbraco.Core/Sync/ServerSyncWebServiceClient.cs b/src/Umbraco.Core/Sync/ServerSyncWebServiceClient.cs
index c45ceace23..dd7d0db01d 100644
--- a/src/Umbraco.Core/Sync/ServerSyncWebServiceClient.cs
+++ b/src/Umbraco.Core/Sync/ServerSyncWebServiceClient.cs
@@ -45,34 +45,7 @@ namespace Umbraco.Core.Sync
{
this.EndInvoke(asyncResult);
}
-
- ///
- [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://umbraco.org/webservices/RemoveByJson", RequestNamespace = "http://umbraco.org/webservices/", ResponseNamespace = "http://umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
- public void RemoveByJson(System.Guid uniqueIdentifier, string jsonPayload, string Login, string Password)
- {
- this.Invoke("RemoveByJson", new object[] {
- uniqueIdentifier,
- jsonPayload,
- Login,
- Password});
- }
-
- ///
- public System.IAsyncResult BeginRemoveByJson(System.Guid uniqueIdentifier, string jsonPayload, string Login, string Password, System.AsyncCallback callback, object asyncState)
- {
- return this.BeginInvoke("RemoveByJson", new object[] {
- uniqueIdentifier,
- jsonPayload,
- Login,
- Password}, callback, asyncState);
- }
-
- ///
- public void EndRemoveByJson(System.IAsyncResult asyncResult)
- {
- this.EndInvoke(asyncResult);
- }
-
+
///
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://umbraco.org/webservices/RefreshByJson", RequestNamespace = "http://umbraco.org/webservices/", ResponseNamespace = "http://umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public void RefreshByJson(System.Guid uniqueIdentifier, string jsonPayload, string Login, string Password)
diff --git a/src/Umbraco.Tests/BusinessLogic/DictionaryTest.cs b/src/Umbraco.Tests/BusinessLogic/DictionaryTest.cs
index ac2376dc0c..92f3d34c60 100644
--- a/src/Umbraco.Tests/BusinessLogic/DictionaryTest.cs
+++ b/src/Umbraco.Tests/BusinessLogic/DictionaryTest.cs
@@ -238,6 +238,7 @@ namespace Umbraco.Tests.BusinessLogic
var newKey = "NEWKEY" + Guid.NewGuid().ToString("N");
d.key = newKey;
+ d.Save();
Assert.AreNotEqual(oldKey, d.key);
Assert.AreEqual(newKey, d.key);
diff --git a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
index 3831242ce8..d1ddd03827 100644
--- a/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
+++ b/src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
@@ -23,6 +23,15 @@ namespace Umbraco.Web.Cache
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
+ //Bind to dictionary events
+ //NOTE: we need to bind to legacy and new API events currently: http://issues.umbraco.org/issue/U4-1979
+
+ global::umbraco.cms.businesslogic.Dictionary.DictionaryItem.New += DictionaryItemNew;
+ global::umbraco.cms.businesslogic.Dictionary.DictionaryItem.Saving +=DictionaryItemSaving;
+ global::umbraco.cms.businesslogic.Dictionary.DictionaryItem.Deleted +=DictionaryItemDeleted;
+ LocalizationService.DeletedDictionaryItem += LocalizationServiceDeletedDictionaryItem;
+ LocalizationService.SavedDictionaryItem += LocalizationServiceSavedDictionaryItem;
+
//Bind to data type events
//NOTE: we need to bind to legacy and new API events currently: http://issues.umbraco.org/issue/U4-1979
@@ -97,6 +106,35 @@ namespace Umbraco.Web.Cache
MediaService.Trashing += MediaServiceTrashing;
}
+ #region Dictionary event handlers
+
+ static void LocalizationServiceSavedDictionaryItem(ILocalizationService sender, Core.Events.SaveEventArgs e)
+ {
+ e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshDictionaryCache(x.Id));
+ }
+
+ static void LocalizationServiceDeletedDictionaryItem(ILocalizationService sender, Core.Events.DeleteEventArgs e)
+ {
+ e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveDictionaryCache(x.Id));
+ }
+
+ static void DictionaryItemDeleted(global::umbraco.cms.businesslogic.Dictionary.DictionaryItem sender, System.EventArgs e)
+ {
+ DistributedCache.Instance.RemoveDictionaryCache(sender.id);
+ }
+
+ static void DictionaryItemSaving(global::umbraco.cms.businesslogic.Dictionary.DictionaryItem sender, System.EventArgs e)
+ {
+ DistributedCache.Instance.RefreshDictionaryCache(sender.id);
+ }
+
+ static void DictionaryItemNew(global::umbraco.cms.businesslogic.Dictionary.DictionaryItem sender, System.EventArgs e)
+ {
+ DistributedCache.Instance.RefreshDictionaryCache(sender.id);
+ }
+
+ #endregion
+
#region DataType event handlers
static void DataTypeServiceSaved(IDataTypeService sender, Core.Events.SaveEventArgs e)
{
@@ -132,12 +170,12 @@ namespace Umbraco.Web.Cache
static void FileServiceDeletedStylesheet(IFileService sender, Core.Events.DeleteEventArgs e)
{
- e.DeletedEntities.ForEach(DistributedCache.Instance.RemoveStylesheetCache);
+ e.DeletedEntities.ForEach(x => DistributedCache.Instance.RemoveStylesheetCache(x));
}
static void FileServiceSavedStylesheet(IFileService sender, Core.Events.SaveEventArgs e)
{
- e.SavedEntities.ForEach(DistributedCache.Instance.RefreshStylesheetCache);
+ e.SavedEntities.ForEach(x => DistributedCache.Instance.RefreshStylesheetCache(x));
}
static void StyleSheetAfterSave(StyleSheet sender, SaveEventArgs e)
diff --git a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
index 89698caa4b..0e31bf0bc3 100644
--- a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
@@ -156,17 +156,6 @@ namespace Umbraco.Web.Cache
base.Refresh(jsonPayload);
}
- ///
- /// Removes the cache using the custom jsonPayload provided
- ///
- ///
- public override void Remove(string jsonPayload)
- {
- var payload = DeserializeFromJsonPayload(jsonPayload);
- ClearContentTypeCache(payload);
- base.Remove(jsonPayload);
- }
-
///
/// This clears out all cache associated with a content type
///
diff --git a/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs b/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs
new file mode 100644
index 0000000000..d9ca422f86
--- /dev/null
+++ b/src/Umbraco.Web/Cache/DictionaryCacheRefresher.cs
@@ -0,0 +1,42 @@
+using System;
+using Umbraco.Core.Cache;
+
+namespace Umbraco.Web.Cache
+{
+ ///
+ /// A cache refresher to ensure the dictionary cache is refreshed when dictionary change
+ ///
+ public sealed class DictionaryCacheRefresher : CacheRefresherBase
+ {
+ protected override DictionaryCacheRefresher Instance
+ {
+ get { return this; }
+ }
+
+ public override Guid UniqueIdentifier
+ {
+ get { return new Guid(DistributedCache.DictionaryCacheRefresherId); }
+ }
+
+ public override string Name
+ {
+ get { return "Dictionary cache refresher"; }
+ }
+
+ public override void Refresh(int id)
+ {
+ global::umbraco.cms.businesslogic.Dictionary.ClearCache();
+ //when a dictionary item is updated we must also clear the text cache!
+ global::umbraco.cms.businesslogic.language.Item.ClearCache();
+ base.Refresh(id);
+ }
+
+ public override void Remove(int id)
+ {
+ global::umbraco.cms.businesslogic.Dictionary.ClearCache();
+ //when a dictionary item is removed we must also clear the text cache!
+ global::umbraco.cms.businesslogic.language.Item.ClearCache();
+ base.Remove(id);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Cache/DistributedCache.cs b/src/Umbraco.Web/Cache/DistributedCache.cs
index 29959e75e2..15d54ef151 100644
--- a/src/Umbraco.Web/Cache/DistributedCache.cs
+++ b/src/Umbraco.Web/Cache/DistributedCache.cs
@@ -47,6 +47,7 @@ namespace Umbraco.Web.Cache
public const string StylesheetCacheRefresherId = "E0633648-0DEB-44AE-9A48-75C3A55CB670";
public const string StylesheetPropertyCacheRefresherId = "2BC7A3A4-6EB1-4FBC-BAA3-C9E7B6D36D38";
public const string DataTypeCacheRefresherId = "35B16C25-A17E-45D7-BC8F-EDAB1DCC28D2";
+ public const string DictionaryCacheRefresherId = "D1D7E227-F817-4816-BFE9-6C39B6152884";
#endregion
@@ -206,21 +207,7 @@ namespace Umbraco.Web.Cache
GetRefresherById(factoryGuid),
getNumericId,
instances);
- }
-
- ///
- /// Sends a request to all registered load-balanced servers to remove data based on the custom json payload
- /// using the specified ICacheRefresher with the guid factoryGuid.
- ///
- ///
- ///
- public void RemoveByJson(Guid factoryGuid, string jsonPayload)
- {
- ServerMessengerResolver.Current.Messenger.PerformRemove(
- ServerRegistrarResolver.Current.Registrar.Registrations,
- GetRefresherById(factoryGuid),
- jsonPayload);
- }
+ }
private static ICacheRefresher GetRefresherById(Guid uniqueIdentifier)
{
diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs
index 736c173c44..1f72b2daed 100644
--- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs
+++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs
@@ -11,7 +11,7 @@ namespace Umbraco.Web.Cache
///
/// Extension methods for DistrubutedCache
///
- public static class DistributedCacheExtensions
+ internal static class DistributedCacheExtensions
{
#region User cache
public static void RemoveUserCache(this DistributedCache dc, int userId)
@@ -48,6 +48,30 @@ namespace Umbraco.Web.Cache
#endregion
+ #region Dictionary cache
+ ///
+ /// Refreshes the cache amongst servers for a dictionary item
+ ///
+ ///
+ ///
+ public static void RefreshDictionaryCache(this DistributedCache dc, int dictionaryItemId)
+ {
+ dc.Refresh(new Guid(DistributedCache.DictionaryCacheRefresherId), dictionaryItemId);
+ }
+
+ ///
+ /// Refreshes the cache amongst servers for a dictionary item
+ ///
+ ///
+ ///
+ public static void RemoveDictionaryCache(this DistributedCache dc, int dictionaryItemId)
+ {
+ dc.Remove(new Guid(DistributedCache.DictionaryCacheRefresherId), dictionaryItemId);
+ }
+
+ #endregion
+
+
#region Data type cache
///
/// Refreshes the cache amongst servers for a template
@@ -179,7 +203,7 @@ namespace Umbraco.Web.Cache
///
public static void RemoveMediaCache(this DistributedCache dc, params IMedia[] media)
{
- dc.RemoveByJson(new Guid(DistributedCache.MediaCacheRefresherId),
+ dc.RefreshByJson(new Guid(DistributedCache.MediaCacheRefresherId),
MediaCacheRefresher.SerializeToJsonPayload(media));
}
@@ -220,7 +244,7 @@ namespace Umbraco.Web.Cache
{
if (macro != null)
{
- dc.RemoveByJson(new Guid(DistributedCache.MacroCacheRefresherId),
+ dc.RefreshByJson(new Guid(DistributedCache.MacroCacheRefresherId),
MacroCacheRefresher.SerializeToJsonPayload(macro));
}
}
@@ -234,7 +258,7 @@ namespace Umbraco.Web.Cache
{
if (macro != null && macro.Model != null)
{
- dc.RemoveByJson(new Guid(DistributedCache.MacroCacheRefresherId),
+ dc.RefreshByJson(new Guid(DistributedCache.MacroCacheRefresherId),
MacroCacheRefresher.SerializeToJsonPayload(macro));
}
}
@@ -282,7 +306,7 @@ namespace Umbraco.Web.Cache
if (contentType != null)
{
//dc.Remove(new Guid(DistributedCache.ContentTypeCacheRefresherId), x => x.Id, contentType);
- dc.RemoveByJson(new Guid(DistributedCache.ContentTypeCacheRefresherId),
+ dc.RefreshByJson(new Guid(DistributedCache.ContentTypeCacheRefresherId),
ContentTypeCacheRefresher.SerializeToJsonPayload(true, contentType));
}
}
@@ -297,7 +321,7 @@ namespace Umbraco.Web.Cache
if (mediaType != null)
{
//dc.Remove(new Guid(DistributedCache.ContentTypeCacheRefresherId), x => x.Id, mediaType);
- dc.RemoveByJson(new Guid(DistributedCache.ContentTypeCacheRefresherId),
+ dc.RefreshByJson(new Guid(DistributedCache.ContentTypeCacheRefresherId),
ContentTypeCacheRefresher.SerializeToJsonPayload(true, mediaType));
}
}
diff --git a/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs b/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs
index 59214b7258..09d9affa96 100644
--- a/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/LanguageCacheRefresher.cs
@@ -31,8 +31,10 @@ namespace Umbraco.Web.Cache
}
public override void Remove(int id)
- {
+ {
ApplicationContext.Current.ApplicationCache.ClearCacheItem(CacheKeys.LanguageCacheKey);
+ //when a language is removed we must also clear the text cache!
+ global::umbraco.cms.businesslogic.language.Item.ClearCache();
base.Remove(id);
}
}
diff --git a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs
index 850f56f84d..e747149245 100644
--- a/src/Umbraco.Web/Cache/MacroCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/MacroCacheRefresher.cs
@@ -148,23 +148,18 @@ namespace Umbraco.Web.Cache
}
public override void Refresh(string jsonPayload)
- {
- Remove(jsonPayload);
- base.Refresh(jsonPayload);
- }
-
- public override void Remove(string jsonPayload)
{
var payloads = DeserializeFromJsonPayload(jsonPayload);
payloads.ForEach(payload =>
- {
- GetCacheKeysForAlias(payload.Alias).ForEach(
- alias =>
- ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(alias));
- });
+ {
+ GetCacheKeysForAlias(payload.Alias).ForEach(
+ alias =>
+ ApplicationContext.Current.ApplicationCache.ClearCacheByKeySearch(alias));
+ });
- base.Remove(jsonPayload);
+ base.Refresh(jsonPayload);
}
+
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs
index fab9e6264d..2536165057 100644
--- a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs
@@ -95,12 +95,6 @@ namespace Umbraco.Web.Cache
base.Refresh(jsonPayload);
}
- public override void Remove(string jsonPayload)
- {
- ClearCache(DeserializeFromJsonPayload(jsonPayload));
- base.Remove(jsonPayload);
- }
-
public override void Refresh(int id)
{
ClearCache(FromMedia(ApplicationContext.Current.Services.MediaService.GetById(id)));
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 2ec1e78969..b1a2e67dbb 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -265,6 +265,7 @@
+
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CacheRefresher.asmx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CacheRefresher.asmx.cs
index 2be399f850..9a335599b4 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CacheRefresher.asmx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/webservices/CacheRefresher.asmx.cs
@@ -132,30 +132,6 @@ namespace umbraco.presentation.webservices
}
}
- ///
- /// Removes objects using the passed in Json payload, it will be up to the cache refreshers to deserialize
- ///
- ///
- /// A custom JSON payload used by the cache refresher
- ///
- ///
- ///
- /// NOTE: the cache refresher defined by the ID MUST be of type IJsonCacheRefresher or an exception will be thrown
- ///
- [WebMethod]
- public void RemoveByJson(Guid uniqueIdentifier, string jsonPayload, string Login, string Password)
- {
- if (BusinessLogic.User.validateCredentials(Login, Password))
- {
- var cr = CacheRefreshersResolver.Current.GetById(uniqueIdentifier) as IJsonCacheRefresher;
- if (cr == null)
- {
- throw new InvalidOperationException("The cache refresher: " + uniqueIdentifier + " is not of type " + typeof(IJsonCacheRefresher));
- }
- cr.Remove(jsonPayload);
- }
- }
-
[WebMethod]
public void RemoveById(Guid uniqueIdentifier, int Id, string Login, string Password) {
diff --git a/src/umbraco.cms/businesslogic/ContentType.cs b/src/umbraco.cms/businesslogic/ContentType.cs
index f7d7e7ff25..a61ed770e9 100644
--- a/src/umbraco.cms/businesslogic/ContentType.cs
+++ b/src/umbraco.cms/businesslogic/ContentType.cs
@@ -245,9 +245,7 @@ namespace umbraco.cms.businesslogic
private List m_AllowedChildContentTypeIDs = null;
private List m_VirtualTabs = null;
-
- private static readonly object propertyTypesCacheSyncLock = new object();
-
+
protected internal IContentTypeComposition ContentTypeItem;
#endregion
diff --git a/src/umbraco.cms/businesslogic/Dictionary.cs b/src/umbraco.cms/businesslogic/Dictionary.cs
index 16db467e61..7a655f8373 100644
--- a/src/umbraco.cms/businesslogic/Dictionary.cs
+++ b/src/umbraco.cms/businesslogic/Dictionary.cs
@@ -59,6 +59,16 @@ namespace umbraco.cms.businesslogic
}
}
+ ///
+ /// Used by the cache refreshers to clear the cache on distributed servers
+ ///
+ internal static void ClearCache()
+ {
+ DictionaryItems.Clear();
+ //ensure the flag is reset so that EnsureCache will re-cache everything
+ _cacheIsEnsured = false;
+ }
+
///
/// Retrieve a list of toplevel DictionaryItems
///
@@ -159,7 +169,8 @@ namespace umbraco.cms.businesslogic
///
public bool IsTopMostItem()
{
- return DictionaryItems.Values.Cast()
+ EnsureCache();
+ return DictionaryItems.Values
.Where(x => x.id == id)
.Select(x => x.ParentId)
.SingleOrDefault() == TopLevelParent;
@@ -172,9 +183,10 @@ namespace umbraco.cms.businesslogic
{
get
{
+ EnsureCache();
if (_parent == null)
{
- var p = DictionaryItems.Values.Cast().SingleOrDefault(x => x.UniqueId == this.ParentId);
+ var p = DictionaryItems.Values.SingleOrDefault(x => x.UniqueId == this.ParentId);
if (p == null)
{
@@ -203,7 +215,8 @@ namespace umbraco.cms.businesslogic
{
get
{
- return DictionaryItems.Values.Cast()
+ EnsureCache();
+ return DictionaryItems.Values
.Where(x => x.ParentId == this.UniqueId).OrderBy(item => item.key)
.ToArray();
}
@@ -219,7 +232,8 @@ namespace umbraco.cms.businesslogic
{
get
{
- return (SqlHelper.ExecuteScalar("select count([key]) as tmp from cmsDictionary where parent=@uniqueId", SqlHelper.CreateParameter("@uniqueId", UniqueId)) > 0);
+ EnsureCache();
+ return DictionaryItems.Values.Any(x => x.ParentId == UniqueId);
}
}
@@ -237,11 +251,7 @@ namespace umbraco.cms.businesslogic
{
SqlHelper.ExecuteNonQuery("Update cmsDictionary set [key] = @key WHERE pk = @Id", SqlHelper.CreateParameter("@key", value),
SqlHelper.CreateParameter("@Id", id));
-
- //remove the cached item since the key is different
- DictionaryItem val;
- DictionaryItems.TryRemove(key, out val);
-
+
using (IRecordsReader dr =
SqlHelper.ExecuteReader("Select pk, id, [key], parent from cmsDictionary where id=@id",
SqlHelper.CreateParameter("@id", this.UniqueId)))
@@ -253,8 +263,6 @@ namespace umbraco.cms.businesslogic
dr.GetString("key"),
dr.GetGuid("id"),
dr.GetGuid("parent"));
-
- DictionaryItems.AddOrUpdate(item.key, s => item, (s, dictionaryItem) => item);
}
else
{
@@ -284,13 +292,13 @@ namespace umbraco.cms.businesslogic
public void setValue(int languageId, string value)
{
- // Calling Save method triggers the Saving event
- Save();
-
if (Item.hasText(UniqueId, languageId))
Item.setText(languageId, UniqueId, value);
else
Item.addText(languageId, UniqueId, value);
+
+ // Calling Save method triggers the Saving event
+ Save();
}
public string Value()
@@ -309,13 +317,13 @@ namespace umbraco.cms.businesslogic
///
public void setValue(string value)
{
- // Calling Save method triggers the Saving event
- Save();
-
if (Item.hasText(UniqueId, 0))
Item.setText(0, UniqueId, value);
else
Item.addText(0, UniqueId, value);
+
+ // Calling Save method triggers the Saving event
+ Save();
}
public static int addKey(string key, string defaultValue, string parentKey)
@@ -352,12 +360,12 @@ namespace umbraco.cms.businesslogic
// remove key from database
SqlHelper.ExecuteNonQuery("delete from cmsDictionary where [key] = @key", SqlHelper.CreateParameter("@key", key));
- // Remove key from cache
- DictionaryItem val;
- DictionaryItems.TryRemove(key, out val);
+ OnDeleted(EventArgs.Empty);
}
- [Obsolete("Does not save the dictionary item, use setValue() instead.")]
+ ///
+ /// ensures events fire after setting proeprties
+ ///
public void Save()
{
OnSaving(EventArgs.Empty);
@@ -467,9 +475,7 @@ namespace umbraco.cms.businesslogic
dr.GetString("key"),
dr.GetGuid("id"),
dr.GetGuid("parent"));
-
- DictionaryItems.AddOrUpdate(item.key, s => item, (s, dictionaryItem) => item);
-
+
item.setValue(defaultValue);
item.OnNew(EventArgs.Empty);
@@ -514,6 +520,13 @@ namespace umbraco.cms.businesslogic
if (Deleting != null)
Deleting(this, e);
}
+
+ public static event DeleteEventHandler Deleted;
+ protected virtual void OnDeleted(EventArgs e)
+ {
+ if (Deleted != null)
+ Deleted(this, e);
+ }
#endregion
}
}
diff --git a/src/umbraco.cms/businesslogic/language/Text.cs b/src/umbraco.cms/businesslogic/language/Item.cs
similarity index 73%
rename from src/umbraco.cms/businesslogic/language/Text.cs
rename to src/umbraco.cms/businesslogic/language/Item.cs
index 3c87c4a9f3..30ce7089f7 100644
--- a/src/umbraco.cms/businesslogic/language/Text.cs
+++ b/src/umbraco.cms/businesslogic/language/Item.cs
@@ -10,14 +10,13 @@ using System.Collections.Generic;
namespace umbraco.cms.businesslogic.language
{
///
- /// Item class contains method for accessing language translated text, its a generic component which
- /// can be used for storing language translated content, all items are associated to an unique identifier (Guid)
- ///
- /// The data is cached and are usable in the public website.
- ///
- /// Primarily used by the built-in dictionary
- ///
+ /// THIS CLASS IS NOT INTENDED TO BE USED DIRECTLY IN YOUR CODE, USE THE umbraco.cms.businesslogic.Dictionary class instead
///
+ ///
+ /// This class is used by the DictionaryItem, all caching is handled in the DictionaryItem.Save() method which will ensure that
+ /// cache is invalidated if anything is changed.
+ ///
+ [Obsolete("THIS CLASS IS NOT INTENDED TO BE USED DIRECTLY IN YOUR CODE, USE THE umbraco.cms.businesslogic.Dictionary class instead")]
public class Item
{
private static readonly ConcurrentDictionary> Items = new ConcurrentDictionary>();
@@ -36,7 +35,7 @@ namespace umbraco.cms.businesslogic.language
///
/// Populates the global hash table with the data from the database.
///
- private static void EnsureData()
+ private static void EnsureCache()
{
if (!_isInitialize)
{
@@ -54,7 +53,16 @@ namespace umbraco.cms.businesslogic.language
var uniqueId = dr.GetGuid("UniqueId");
var text = dr.GetString("value");
- UpdateCache(languageId, uniqueId, text);
+ Items.AddOrUpdate(uniqueId, guid =>
+ {
+ var languagevalues = new Dictionary { { languageId, text } };
+ return languagevalues;
+ }, (guid, dictionary) =>
+ {
+ // add/update the text for the id
+ dictionary[languageId] = text;
+ return dictionary;
+ });
}
}
_isInitialize = true;
@@ -64,20 +72,16 @@ namespace umbraco.cms.businesslogic.language
}
}
- private static void UpdateCache(int languageId, Guid key, string text)
+ ///
+ /// Clears the cache, this is used for cache refreshers to ensure that the cache is up to date across all servers
+ ///
+ internal static void ClearCache()
{
- Items.AddOrUpdate(key, guid =>
- {
- var languagevalues = new Dictionary {{languageId, text}};
- return languagevalues;
- }, (guid, dictionary) =>
- {
- // add/update the text for the id
- dictionary[languageId] = text;
- return dictionary;
- });
+ Items.Clear();
+ //reset the flag so that we re-lookup the cache
+ _isInitialize = false;
}
-
+
///
/// Retrieves the value of a languagetranslated item given the key
///
@@ -86,7 +90,7 @@ namespace umbraco.cms.businesslogic.language
/// The language translated text
public static string Text(Guid key, int languageId)
{
- EnsureData();
+ EnsureCache();
Dictionary val;
if (Items.TryGetValue(key, out val))
@@ -104,7 +108,7 @@ namespace umbraco.cms.businesslogic.language
/// returns True if there is a value associated to the unique identifier with the specified language
public static bool hasText(Guid key, int languageId)
{
- EnsureData();
+ EnsureCache();
Dictionary val;
if (Items.TryGetValue(key, out val))
@@ -124,16 +128,12 @@ namespace umbraco.cms.businesslogic.language
public static void setText(int languageId, Guid key, string value)
{
- EnsureData();
-
if (!hasText(key, languageId)) throw new ArgumentException("Key does not exist");
SqlHelper.ExecuteNonQuery("Update cmsLanguageText set [value] = @value where LanguageId = @languageId And UniqueId = @key",
SqlHelper.CreateParameter("@value", value),
SqlHelper.CreateParameter("@languageId", languageId),
SqlHelper.CreateParameter("@key", key));
-
- UpdateCache(languageId, key, value);
}
///
@@ -145,16 +145,12 @@ namespace umbraco.cms.businesslogic.language
///
public static void addText(int languageId, Guid key, string value)
{
- EnsureData();
-
if (hasText(key, languageId)) throw new ArgumentException("Key being add'ed already exists");
SqlHelper.ExecuteNonQuery("Insert Into cmsLanguageText (languageId,UniqueId,[value]) values (@languageId, @key, @value)",
SqlHelper.CreateParameter("@languageId", languageId),
SqlHelper.CreateParameter("@key", key),
SqlHelper.CreateParameter("@value", value));
-
- UpdateCache(languageId, key, value);
}
///
@@ -163,15 +159,9 @@ namespace umbraco.cms.businesslogic.language
/// Unique identifier
public static void removeText(Guid key)
{
- EnsureData();
-
// remove from database
SqlHelper.ExecuteNonQuery("Delete from cmsLanguageText where UniqueId = @key",
SqlHelper.CreateParameter("@key", key));
-
- // remove from cache
- Dictionary val;
- Items.TryRemove(key, out val);
}
///
@@ -181,25 +171,10 @@ namespace umbraco.cms.businesslogic.language
///
public static void RemoveByLanguage(int languageId)
{
- EnsureData();
-
// remove from database
SqlHelper.ExecuteNonQuery("Delete from cmsLanguageText where languageId = @languageId",
SqlHelper.CreateParameter("@languageId", languageId));
- //we need to lock here because the inner dictionary is not concurrent, seems overkill to have a nested concurrent dictionary
- lock (Locker)
- {
- //delete all of the items belonging to the language
- foreach (var entry in Items.Values)
- {
- if (entry.ContainsKey(languageId))
- {
- entry.Remove(languageId);
- }
- }
- }
-
}
}
}
\ No newline at end of file
diff --git a/src/umbraco.cms/businesslogic/language/Language.cs b/src/umbraco.cms/businesslogic/language/Language.cs
index 7d3d6236a5..55c010d655 100644
--- a/src/umbraco.cms/businesslogic/language/Language.cs
+++ b/src/umbraco.cms/businesslogic/language/Language.cs
@@ -82,29 +82,31 @@ namespace umbraco.cms.businesslogic.language
/// Creates a new language given the culture code - ie. da-dk (denmark)
///
/// Culturecode of the language
- [MethodImpl(MethodImplOptions.Synchronized)]
public static void MakeNew(string cultureCode)
{
- var culture = GetCulture(cultureCode);
- if (culture != null)
+ lock (Locker)
{
- //insert it
- SqlHelper.ExecuteNonQuery(
- "insert into umbracoLanguage (languageISOCode) values (@CultureCode)",
- SqlHelper.CreateParameter("@CultureCode", cultureCode));
-
- //get it's id
- var newId = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM umbracoLanguage WHERE languageISOCode=@cultureCode", SqlHelper.CreateParameter("@cultureCode", cultureCode));
-
- //load it and raise events
- using (var dr = SqlHelper.ExecuteReader(string.Format("{0} where id = {1}", m_SQLOptimizedGetAll, newId)))
+ var culture = GetCulture(cultureCode);
+ if (culture != null)
{
- while (dr.Read())
+ //insert it
+ SqlHelper.ExecuteNonQuery(
+ "insert into umbracoLanguage (languageISOCode) values (@CultureCode)",
+ SqlHelper.CreateParameter("@CultureCode", cultureCode));
+
+ //get it's id
+ var newId = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM umbracoLanguage WHERE languageISOCode=@cultureCode", SqlHelper.CreateParameter("@cultureCode", cultureCode));
+
+ //load it and raise events
+ using (var dr = SqlHelper.ExecuteReader(string.Format("{0} where id = {1}", m_SQLOptimizedGetAll, newId)))
{
-
- var ct = new Language();
- ct.PopulateFromReader(dr);
- ct.OnNew(new NewEventArgs());
+ while (dr.Read())
+ {
+
+ var ct = new Language();
+ ct.PopulateFromReader(dr);
+ ct.OnNew(new NewEventArgs());
+ }
}
}
}
diff --git a/src/umbraco.cms/umbraco.cms.csproj b/src/umbraco.cms/umbraco.cms.csproj
index 29e453ebac..53950bc131 100644
--- a/src/umbraco.cms/umbraco.cms.csproj
+++ b/src/umbraco.cms/umbraco.cms.csproj
@@ -330,7 +330,7 @@
Code
-
+
Code