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); } }); }