Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id EB16017D60 for ; Fri, 17 Jul 2015 11:07:34 +0000 (UTC) Received: (qmail 20488 invoked by uid 500); 17 Jul 2015 11:07:34 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 20448 invoked by uid 500); 17 Jul 2015 11:07:34 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 20439 invoked by uid 99); 17 Jul 2015 11:07:34 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Jul 2015 11:07:34 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id AF6F8DFF0B; Fri, 17 Jul 2015 11:07:34 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: dahn@apache.org To: commits@cloudstack.apache.org Date: Fri, 17 Jul 2015 11:07:34 -0000 Message-Id: <561b3e60b7ff4131932f187bf8af89d7@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] git commit: updated refs/heads/4.5 to fd459b8 Repository: cloudstack Updated Branches: refs/heads/4.5 56522fda6 -> fd459b89f CLOUDSTACK-7539: [S3] Parallel deployment makes reference count of a cache in nfs secondary staging store negative(-1) Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/9cb4a913 Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/9cb4a913 Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/9cb4a913 Branch: refs/heads/4.5 Commit: 9cb4a913d377867a33f62a9a172acb42c5253e5f Parents: 56522fd Author: Hiroki Ohashi Authored: Thu Oct 2 17:21:06 2014 +0900 Committer: Daan Hoogland Committed: Fri Jul 17 13:05:21 2015 +0200 ---------------------------------------------------------------------- .../cache/manager/StorageCacheManagerImpl.java | 95 ++++++++++++++++++-- 1 file changed, 88 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/9cb4a913/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java ---------------------------------------------------------------------- diff --git a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java index 3a502d1..6be3581 100644 --- a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java +++ b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.Date; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -40,6 +41,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event; import org.apache.cloudstack.engine.subsystem.api.storage.Scope; import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; @@ -60,6 +62,8 @@ import com.cloud.utils.db.QueryBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.agent.api.to.DataObjectType; + public class StorageCacheManagerImpl implements StorageCacheManager, Manager { private static final Logger s_logger = Logger.getLogger(StorageCacheManagerImpl.class); @Inject @@ -78,6 +82,9 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { int workers; ScheduledExecutorService executors; int cacheReplaceMentInterval; + private static final Object templateLock = new Object(); + private static final Object volumeLock = new Object(); + private static final Object snapshotLock = new Object(); @Override public DataStore getCacheStorage(Scope scope) { @@ -216,15 +223,82 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { @Override public DataObject createCacheObject(DataObject data, DataStore store) { - DataObjectInStore obj = objectInStoreMgr.findObject(data, store); - if (obj != null && obj.getState() == ObjectInDataStoreStateMachine.State.Ready) { - s_logger.debug("there is already one in the cache store"); - DataObject dataObj = objectInStoreMgr.get(data, store); - dataObj.incRefCount(); - return dataObj; + DataObject objOnCacheStore; + final Object lock; + final DataObjectType type = data.getType(); + final String typeName; + final DataStoreRole role = store.getRole(); + final long storeId = store.getId(); + final long dataId = data.getId(); + + /* + * Make sure any thread knows own lock type. + */ + if (type == DataObjectType.TEMPLATE) { + lock = templateLock; + typeName = "template"; + } else if (type == DataObjectType.VOLUME) { + lock = volumeLock; + typeName = "volume"; + } else if (type == DataObjectType.SNAPSHOT) { + lock = snapshotLock; + typeName = "snapshot"; + } else { + String msg = "unsupported DataObject comes, then can't acquire correct lock object"; + throw new CloudRuntimeException(msg); } + s_logger.debug("check " + typeName + " cache entry(id: " + dataId + ") on store(id: " + storeId + ")"); + + synchronized (lock) { + DataObjectInStore obj = objectInStoreMgr.findObject(data, store); + if (obj != null) { + State st = obj.getState(); + + long miliSeconds = 10000; + long timeoutSeconds = 3600; + long timeoutMiliSeconds = timeoutSeconds * 1000; + Date now = new Date(); + long expiredEpoch = now.getTime() + timeoutMiliSeconds; + Date expiredDate = new Date(expiredEpoch); + + /* + * Waiting for completion of cache copy. + */ + while (st == ObjectInDataStoreStateMachine.State.Allocated || + st == ObjectInDataStoreStateMachine.State.Creating || + st == ObjectInDataStoreStateMachine.State.Copying) { + + /* + * Threads must release lock within waiting for cache copy and + * must be waken up at completion. + */ + s_logger.debug("waiting cache copy completion type: " + typeName + ", id: " + obj.getObjectId() + ", lock: " + lock.hashCode()); + try { + lock.wait(miliSeconds); + } catch (InterruptedException e) {} + s_logger.debug("waken up"); + + now = new Date(); + if (now.after(expiredDate)) { + String msg = "Waiting time exceeds timeout limit(" + timeoutSeconds + " s)"; + throw new CloudRuntimeException(msg); + } - DataObject objOnCacheStore = store.create(data); + obj = objectInStoreMgr.findObject(data, store); + st = obj.getState(); + } + + if (st == ObjectInDataStoreStateMachine.State.Ready) { + s_logger.debug("there is already one in the cache store"); + DataObject dataObj = objectInStoreMgr.get(data, store); + dataObj.incRefCount(); + return dataObj; + } + } + + s_logger.debug("create " + typeName + " cache entry(id: " + dataId + ") on store(id: " + storeId + ")"); + objOnCacheStore = store.create(data); + } AsyncCallFuture future = new AsyncCallFuture(); CopyCommandResult result = null; @@ -251,6 +325,13 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { if (result == null) { objOnCacheStore.processEvent(Event.OperationFailed); } + synchronized (lock) { + /* + * Wake up all threads waiting for cache copy. + */ + s_logger.debug("wake up all waiting threads(lock: " + lock.hashCode() + ")"); + lock.notifyAll(); + } } return null; }