/*
* Copyright (C) 2012 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.impl.quota;
import org.exoplatform.management.annotations.Managed;
import org.exoplatform.management.annotations.ManagedDescription;
import org.exoplatform.management.annotations.ManagedName;
import org.exoplatform.management.jmx.annotations.NameTemplate;
import org.exoplatform.management.jmx.annotations.Property;
import org.exoplatform.services.jcr.config.RepositoryEntry;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.impl.core.RepositoryImpl;
import org.exoplatform.services.jcr.impl.core.WorkspaceManagingListener;
import org.exoplatform.services.jcr.impl.proccess.WorkerThread;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.picocontainer.Startable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author <a href="abazko@exoplatform.com">Anatoliy Bazko</a>
* @version $Id: RepositoryQuotaManager.java 34360 2009-07-22 23:58:59Z tolusha $
*/
@Managed
@NameTemplate(@Property(key = "service", value = "RepositoryQuotaManager"))
public class RepositoryQuotaManager implements Startable, WorkspaceManagingListener
{
/**
* Logger.
*/
protected final Log LOG = ExoLogger.getLogger("exo.jcr.component.core.RepositoryQuotaManager");
/**
* All {@link WorkspaceQuotaManager} belonging to repository.
*/
private Map<String, WorkspaceQuotaManager> wsQuotaManagers = new ConcurrentHashMap<String, WorkspaceQuotaManager>();
/**
* The repository name.
*/
protected final String rName;
/**
* The quota manager.
*/
protected final BaseQuotaManager globalQuotaManager;
/**
* {@link QuotaPersister}
*/
protected final QuotaPersister quotaPersister;
/**
* {@link ManageableRepository} instance.
*/
protected final RepositoryImpl repository;
/**
* Task is obligated to push all changes to coordinator where they will
* be persisted.
*/
protected final PushTask pushTask;
/**
* Timeout for task.
*/
protected final long DEFAULT_TIMEOUT = 5000; // 5 sec
/**
* RepositoryQuotaManagerImpl constructor.
*/
public RepositoryQuotaManager(RepositoryImpl repository, BaseQuotaManager quotaManager, RepositoryEntry rEntry)
{
this.rName = rEntry.getName();
this.globalQuotaManager = quotaManager;
this.quotaPersister = globalQuotaManager.quotaPersister;
this.repository = repository;
this.pushTask = new PushTask("PushQuotaChangesTask-" + rName, DEFAULT_TIMEOUT);
this.pushTask.start();
globalQuotaManager.registerRepositoryQuotaManager(rName, this);
this.repository.addWorkspaceManagingListener(this);
}
/**
* @see QuotaManager#getNodeDataSize(String, String, String)
*/
public long getNodeDataSize(String workspaceName, String nodePath) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
return wqm.getNodeDataSize(nodePath);
}
/**
* @see QuotaManager#getNodeQuota(String, String, String)
*/
public long getNodeQuota(String workspaceName, String nodePath) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
return wqm.getNodeQuota(nodePath);
}
/**
* @see QuotaManager#setNodeQuota(String, String, String, long, boolean)
*/
public void setNodeQuota(String workspaceName, String nodePath, long quotaLimit, boolean asyncUpdate)
throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
wqm.setNodeQuota(nodePath, quotaLimit, asyncUpdate);
}
/**
* @see QuotaManager#setGroupOfNodesQuota(String, String, String, long, boolean)
*/
public void setGroupOfNodesQuota(String workspaceName, String patternPath, long quotaLimit,
boolean asyncUpdate) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
wqm.setGroupOfNodesQuota(patternPath, quotaLimit, asyncUpdate);
}
/**
* @see QuotaManager#removeNodeQuota(String, String, String)
*/
public void removeNodeQuota(String workspaceName, String nodePath) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
wqm.removeNodeQuota(nodePath);
}
/**
* @see QuotaManager#removeGroupOfNodesQuota(String, String, String)
*/
public void removeGroupOfNodesQuota(String workspaceName, String nodePath) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
wqm.removeGroupOfNodesQuota(nodePath);
}
/**
* @see QuotaManager#getWorkspaceQuota(String, String)
*/
public long getWorkspaceQuota(String workspaceName) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
return wqm.getWorkspaceQuota();
}
/**
* @see QuotaManager#setWorkspaceQuota(String, String, long)
*/
public void setWorkspaceQuota(String workspaceName, long quotaLimti) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
wqm.setWorkspaceQuota(quotaLimti);
}
/**
* @see QuotaManager#removeWorkspaceQuota(String, String)
*/
public void removeWorkspaceQuota(String workspaceName) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
wqm.removeWorkspaceQuota();
}
/**
* @see QuotaManager#getWorkspaceDataSize(String, String)
*/
public long getWorkspaceDataSize(String workspaceName) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
return wqm.getWorkspaceDataSize();
}
/**
* @see QuotaManager#getWorkspaceIndexSize(String, String)
*/
public long getWorkspaceIndexSize(String workspaceName) throws QuotaManagerException
{
WorkspaceQuotaManager wqm = getWorkspaceQuotaManager(workspaceName);
return wqm.getWorkspaceIndexSize();
}
/**
* @see QuotaManager#setRepositoryQuota(String, long)
*/
@Managed
@ManagedDescription("Sets repository quta limit")
public void setRepositoryQuota(@ManagedName("quotaLimit") long quotaLimit) throws QuotaManagerException
{
quotaPersister.setRepositoryQuota(rName, quotaLimit);
}
/**
* @see QuotaManager#removeRepositoryQuota(String)
*/
@Managed
@ManagedDescription("Removes repository quta limit")
public void removeRepositoryQuota() throws QuotaManagerException
{
quotaPersister.removeRepositoryQuota(rName);
}
/**
* @see QuotaManager#getRepositoryQuota(String)
*/
@Managed
@ManagedDescription("Returns repository quta limit")
public long getRepositoryQuota() throws QuotaManagerException
{
return quotaPersister.getRepositoryQuota(rName);
}
/**
* @see QuotaManager#getRepositoryDataSize(String)
*/
@Managed
@ManagedDescription("Returns repository data size")
public long getRepositoryDataSize() throws QuotaManagerException
{
return quotaPersister.getRepositoryDataSize(rName);
}
/**
* @see QuotaManager#getRepositoryIndexSize(String)
*/
@Managed
@ManagedDescription("Returns repository index size")
public long getRepositoryIndexSize() throws QuotaManagerException
{
long size = 0;
for (WorkspaceQuotaManager wQuotaManager : wsQuotaManagers.values())
{
size += wQuotaManager.getWorkspaceIndexSize();
}
return size;
}
/**
* {@inheritDoc}
*/
public void start()
{
}
/**
* {@inheritDoc}
*/
public void stop()
{
wsQuotaManagers.clear();
globalQuotaManager.unregisterRepositoryQuotaManager(rName);
repository.removeWorkspaceManagingListener(this);
pushTask.halt();
}
/**
* Registers {@link WorkspaceQuotaManager} by name. To delegate workspace based operation
* to appropriate level.
*/
public void registerWorkspaceQuotaManager(String workspaceName, WorkspaceQuotaManager wQuotaManager)
{
wsQuotaManagers.put(workspaceName, wQuotaManager);
}
/**
* Unregisters {@link WorkspaceQuotaManager} by name.
*/
public void unregisterWorkspaceQuotaManager(String workspaceName)
{
wsQuotaManagers.remove(workspaceName);
}
/**
* Returns repository data size by summing size of all workspaces.
*/
public long getRepositoryDataSizeDirectly() throws QuotaManagerException
{
long size = 0;
for (WorkspaceQuotaManager wQuotaManager : wsQuotaManagers.values())
{
size += wQuotaManager.getWorkspaceDataSizeDirectly();
}
return size;
}
/**
* {@inheritDoc}
*/
public void onWorkspaceRemove(String workspaceName)
{
long dataSize;
try
{
dataSize = quotaPersister.getWorkspaceDataSize(rName, workspaceName);
}
catch (UnknownDataSizeException e)
{
return;
}
ChangesItem changesItem = new ChangesItem();
changesItem.updateWorkspaceChangedSize(-dataSize);
WorkspaceQuotaContext context =
new WorkspaceQuotaContext(workspaceName, rName, null, null, null, null, quotaPersister, null, null);
Runnable task = new ApplyPersistedChangesTask(context, changesItem);
task.run();
quotaPersister.setWorkspaceDataSize(rName, workspaceName, dataSize); // workaround
}
// ============================================> pushing changes to coordinator
/**
* Push changes to coordinator.
*/
private class PushTask extends WorkerThread
{
/**
* PushTask constructor.
*/
public PushTask(String name, long timeout)
{
super(name, timeout);
}
/**
* {@inheritDoc}
*/
protected void callPeriodically() throws Exception
{
for (WorkspaceQuotaManager wqm : wsQuotaManagers.values())
{
wqm.pushAllChangesToCoordinator();
}
}
}
private WorkspaceQuotaManager getWorkspaceQuotaManager(String workspaceName) throws IllegalStateException
{
WorkspaceQuotaManager wqm = wsQuotaManagers.get(workspaceName);
if (wqm == null)
{
throw new IllegalStateException("Workspace " + workspaceName + " is not registered in " + rName);
}
return wqm;
}
}