Exemplo n.º 1
0
        public void StoreAsset(AssetBase asset)
        {
            if (asset == null)
            {
                throw new ArgumentNullException("asset cannot be null");
            }
            if (asset.FullID == OpenMetaverse.UUID.Zero)
            {
                throw new ArgumentException("assets must not have a null ID");
            }

            StratusAsset wireAsset = StratusAsset.FromAssetBase(asset);

            //for now we're not going to use compression etc, so set to zero
            wireAsset.StorageFlags = 0;

            //attempt to cache the full (wire) asset in case the CF StoreAsset call takes a while or throws (or both)
            // Call this with a null stream in order to pre-cache the asset before the StoreAsset delay.
            // Makes the asset available immediately after upload in spite of CF write delays.
            if (this.CacheAssetIfAppropriate(asset.FullID, null, wireAsset))
            {
                statPutCached++;
            }

            statTotal++;
            statPut++;

            if (Config.Settings.Instance.UseAsyncStore)
            {
                // Now do the actual CF storage asychronously so as to not block the caller.
                _threadPool.QueueWorkItem(() => StoreCFAsset(asset, wireAsset));
            }
            else
            {
                // This is a blocking write, session/caller will be blocked awaiting completion.
                StoreCFAsset(asset, wireAsset);
            }
        }
        public void StoreAsset(AssetBase asset)
        {
            if (asset == null)
            {
                throw new ArgumentNullException("asset cannot be null");
            }
            if (asset.FullID == OpenMetaverse.UUID.Zero)
            {
                throw new ArgumentException("assets must not have a null ID");
            }

            bool isRetry = false;

            StratusAsset wireAsset = StratusAsset.FromAssetBase(asset);

            //for now we're not going to use compression etc, so set to zero
            wireAsset.StorageFlags = 0;

            Util.Retry(2, new List <Type> {
                typeof(AssetAlreadyExistsException), typeof(UnrecoverableAssetServerException)
            }, () =>
            {
                CloudFilesAssetWorker worker;
                try
                {
                    worker = _asyncAssetWorkers.LeaseObject();
                }
                catch (Exception e)
                {
                    throw new UnrecoverableAssetServerException(e.Message, e);
                }

                try
                {
                    if (Config.Settings.Instance.UnitTest_ThrowTimeout)
                    {
                        throw new System.Net.WebException("Timeout for unit testing", System.Net.WebExceptionStatus.Timeout);
                    }

                    using (System.IO.MemoryStream assetStream = worker.StoreAsset(wireAsset))
                    {
                        //cache the stored asset to eliminate roudtripping when
                        //someone performs an upload
                        this.CacheAssetIfAppropriate(asset.FullID, assetStream, wireAsset);
                    }
                }
                catch (AssetAlreadyExistsException)
                {
                    if (!isRetry) //don't throw if this is a retry. this can happen if a write times out and then succeeds
                    {
                        throw;
                    }
                }
                catch (System.Net.WebException e)
                {
                    if (e.Status == System.Net.WebExceptionStatus.Timeout || e.Status == System.Net.WebExceptionStatus.RequestCanceled)
                    {
                        DoTimeout(asset, wireAsset, e);
                    }
                    else
                    {
                        ReportThrowStorageError(asset, e);
                    }
                }
                catch (System.IO.IOException e)
                {
                    //this sucks, i think timeouts on writes are causing .net to claim the connection
                    //was forcibly closed by the remote host.
                    if (e.Message.Contains("forcibly closed"))
                    {
                        DoTimeout(asset, wireAsset, e);
                    }
                    else
                    {
                        ReportThrowStorageError(asset, e);
                    }
                }
                catch (Exception e)
                {
                    m_log.ErrorFormat("[InWorldz.Stratus]: Unable to store asset {0}: {1}", asset.FullID, e);
                    throw new AssetServerException(String.Format("Unable to store asset {0}: {1}", asset.FullID, e.Message), e);
                }
                finally
                {
                    isRetry = true;
                    _asyncAssetWorkers.ReturnObject(worker);
                }
            });
        }