【问题标题】:[OpenStack .NET API]: Is there a way to combine the Object creation and Container creation in one call?[OpenStack .NET API]:有没有办法在一次调用中结合对象创建和容器创建?
【发布时间】:2013-08-05 22:35:37
【问题描述】:

目前我正在这样做

try
{
    cloudFilesProvider.CreateObjectFromFile(inStrContainerName, inStrSrcFilePath, strDesFileName, 4096, FileMetaData);

}
catch (ItemNotFoundException ex1)
{
     try
     {
         cloudFilesProvider.CreateContainer(inStrContainerName);
         cloudFilesProvider.CreateObjectFromFile(inStrContainerName, inStrSrcFilePath, strDesFileName, 4096, FileMetaData);
     }
     catch(Exception ex2)
     {
         return false;
     }
}

所以本质上如果容器不存在,那么它的 3 个单独的 API 调用。

有没有更有效的方法来做到这一点?

【问题讨论】:

    标签: openstack rackspace-cloud rackspace


    【解决方案1】:

    您可以通过将代码减少到以下两行来简化代码。

    cloudFilesProvider.CreateContainer(inStrContainerName);
    cloudFilesProvider.CreateObjectFromFile(inStrContainerName, inStrSrcFilePath, strDesFileName, 4096, FileMetaData);
    

    CreateContainer 可以安全地调用已存在的容器。如果容器已创建,则返回 ContainerCreated,如果容器已存在而未创建,则返回 ContainerExists

    PS:IObjectStorageProvider 方法的返回值(包含上述信息)将在 1.2.0.0 版中有详细记录。


    编辑:为了减少代码调用的 API 次数,您可以使用如下所示的缓存类。 CreateIfNecessary 方法仅在容器之前不知道时才尝试创建容器存在。 ClearCache 方法提供了一种手动方法,即使您删除了容器,也可以继续使用缓存。

    此代码目前未经测试。

    public class ContainerManager
    {
        private readonly CloudFilesProvider _provider;
        private readonly string _region;
        private readonly bool _useInternalUrl;
        private readonly CloudIdentity _identity;
    
        private readonly HashSet<string> _containers = new HashSet<string>();
    
        public ContainerManager(CloudFilesProvider provider, string region, bool useInternalUrl, CloudIdentity identity)
        {
            if (provider == null)
                throw new ArgumentNullException("provider");
    
            _provider = provider;
            _region = region;
            _useInternalUrl = useInternalUrl;
            _identity = identity;
        }
    
        /// <summary>
        /// Clears the cache of known containers.
        /// </summary>
        /// <remarks>
        /// <alert class="warning">
        /// If a container was deleted after this cache was in use, this method must be called or
        /// <see cref="CreateIfNecessary(string)"/> could fail to create a container which does not
        /// exist.
        /// </alert>
        /// </remarks>
        public void ClearCache()
        {
            lock (_containers)
            {
                _containers.Clear();
            }
        }
    
        /// <summary>
        /// Ensures that a container exists in the Cloud Files store.
        /// </summary>
        /// <remarks>
        /// <alert class="warning">
        /// If a container was deleted after this cache was in use, and <see cref="ClearCache()"/>
        /// has not been called, this method could fail to create a container which does not exist.
        /// </alert>
        /// </remarks>
        /// <param name="container">The name of the container to create.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="container"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">If <paramref name="container"/> is empty.</exception>
        /// <returns><c>true</c> if the container was created; otherwise <c>false</c> if the container already existed.</returns>
        public bool CreateIfNecessary(string container)
        {
            if (container == null)
                throw new ArgumentNullException("container");
            if (string.IsNullOrEmpty(container))
                throw new ArgumentException("container cannot be empty");
    
            // don't try to create the same container multiple times
            if (_containers.Contains(container))
                return false;
    
            ObjectStore result = _provider.CreateContainer(container, _region, _useInternalUrl, _identity);
            if (result == ObjectStore.ContainerCreated || result == ObjectStore.ContainerExists)
            {
                lock (_containers)
                {
                    // add to _containers even if the result is ContainerExists, because that
                    // means it simply wasn't known to this cache.
                    _containers.Add(container);
                }
            }
    
            // only return true if the container was actually created
            return result == ObjectStore.ContainerCreated;
        }
    }
    

    【讨论】:

    • 通常会有比容器多得多的对象(至少在我的情况下)。因此,如果我每次想在云文件中存储一个对象时都使用 cloudFilesProvider.CreateContainer 和 cloudFilesProvider.CreateObjectFromFile ,这只会使请求数量增加一倍,在这种情况下,我拥有的代码将导致较长时间的请求数量减少。我基本上在寻找的是看看是否有一种方法只发出一个请求,如果容器不存在则创建容器然后创建对象。 -谢谢
    • 我用一个示例 ContainerManager 缓存更新了我的答案,您可以使用它来避免多次调用 CreateContainer
    • 所以这适用于我在创建多个具有“ContainerManager”对象生命周期的容器的情况下。但是在我从多个客户端上传文件的情况下,实用程序每天都重新启动,那么我猜每次重新启动实用程序时都会重新创建缓存“_containers”,对吗?
    • 没错,但是在任何一种情况下,它都会将 API 调用的数量减少到最低限度,因此您不应该遇到策略问题。
    猜你喜欢
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-18
    • 2018-04-06
    • 1970-01-01
    • 2021-08-14
    • 1970-01-01
    相关资源
    最近更新 更多