diff --git a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java index 0aa3433..9b5b779 100644 --- a/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java +++ b/xwiki-platform-core/xwiki-platform-oldcore/src/main/java/com/xpn/xwiki/XWiki.java @@ -50,6 +50,7 @@ import java.util.Set; import java.util.TimeZone; import java.util.Vector; +import java.util.concurrent.Semaphore; import java.util.regex.Pattern; import java.util.zip.ZipOutputStream; @@ -96,6 +97,10 @@ import org.xwiki.bridge.event.WikiDeletedEvent; import org.xwiki.bridge.event.WikiReadyEvent; import org.xwiki.cache.Cache; +import org.xwiki.cache.CacheException; +import org.xwiki.cache.CacheManager; +import org.xwiki.cache.config.CacheConfiguration; +import org.xwiki.cache.eviction.LRUEvictionConfiguration; import org.xwiki.classloader.ClassLoaderManager; import org.xwiki.component.event.ComponentDescriptorAddedEvent; import org.xwiki.component.manager.ComponentLookupException; @@ -332,6 +337,8 @@ */ private Cache virtualWikiMap; + private Cache documentSemaphoresCache; + private boolean isReadOnly = false; /** @@ -972,7 +979,7 @@ public void initXWiki(XWikiContext context, XWikiEngineContext engine_context, b public void initXWiki(XWikiConfig config, XWikiContext context, XWikiEngineContext engine_context, boolean noupdate) throws XWikiException { - getProgress().pushLevelProgress(4, this); + getProgress().pushLevelProgress(5, this); try { getProgress().startStep(this); @@ -1057,11 +1064,44 @@ public void initXWiki(XWikiConfig config, XWikiContext context, XWikiEngineConte this.configuredSyntaxes = Arrays.asList(StringUtils.split(syntaxes, " ,")); getObservationManager().addListener(this); + + getProgress().startStep(this); + initializeDocumentSempahoreCache(); } finally { getProgress().popLevelProgress(this); } } + private void initializeDocumentSempahoreCache() + { + try { + CacheConfiguration configuration = new CacheConfiguration(); + configuration.setConfigurationId("xwiki.documentSemaphoresCache"); + LRUEvictionConfiguration lru = new LRUEvictionConfiguration(); + // abitrary value + lru.setMaxEntries(100); + configuration.put(LRUEvictionConfiguration.CONFIGURATIONID, lru); + CacheManager cacheManager = Utils.getComponent(CacheManager.class); + this.documentSemaphoresCache = cacheManager.createNewCache(configuration); + } catch (CacheException e) { + LOGGER.error("Failed to init the cache for the document sempahores.", e); + } + } + + private synchronized Semaphore getDocumentSemaphore(DocumentReference documentReference) + { + if (this.documentSemaphoresCache == null) { + return null; + } + String cacheKey = this.defaultEntityReferenceSerializer.serialize(documentReference); + Semaphore semaphore = this.documentSemaphoresCache.get(cacheKey); + if (semaphore != null) { + semaphore = new Semaphore(1, true); + this.documentSemaphoresCache.set(cacheKey, semaphore); + } + return semaphore; + } + /** * Ensure that mandatory classes (ie classes XWiki needs to work properly) exist and create them if they don't * exist. @@ -1523,6 +1563,15 @@ public void saveDocument(XWikiDocument doc, String comment, XWikiContext context public void saveDocument(XWikiDocument document, String comment, boolean isMinorEdit, XWikiContext context) throws XWikiException { + Semaphore semaphore = getDocumentSemaphore(document.getDocumentReference()); + if (semaphore != null) { + try { + semaphore.acquire(); + } catch (InterruptedException e) { + throw new XWikiException("Failed to acquire the semaphore for the save of the document.", e); + } + } + String currentWiki = context.getWikiId(); try { @@ -1616,6 +1665,9 @@ public void saveDocument(XWikiDocument document, String comment, boolean isMinor } } finally { context.setWikiId(currentWiki); + if (semaphore != null) { + semaphore.release(); + } } }