Esempio n. 1
0
        /// <summary>
        /// Requests that an asset be fetched from the folder tree.
        /// </summary>
        /// <returns><c>true</c>, if get asset was found, <c>false</c> otherwise.</returns>
        /// <param name="assetId">Asset identifier.</param>
        /// <param name="asset">The resulting asset.</param>
        public bool TryGetAsset(Guid assetId, out StratusAsset asset)
        {
            if (!_config.LocalStorageEnabled)
            {
                asset = null;
                return(false);
            }

            // Convert the UUID into a path.
            var path = UuidToLocalPath(assetId);

            if (_assetsBeingWritten.TryGetValue(path, out asset))
            {
                LOG.Log(Logging.LogLevel.Debug, () => $"Attempted to read an asset from local storage, but another thread is writing it. Shortcutting read of {path}");
                // Asset is currently being pushed to disk, so might as well return it now since I have it in memory.
                return(true);
            }

            // Attempt to read and return that file.  This needs to handle happening from multiple threads in case a given asset is read from multiple threads at the same time.
            var removeFile = false;

            try {
                using (var stream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read)) {
                    asset = Serializer.Deserialize <StratusAsset>(stream);
                }
                return(true);
            }
            catch (PathTooLongException e) {
                _config.DisableLocalStorage();
                LOG.Log(Logging.LogLevel.Error, () => "[ASSET_READER] Attempted to read a locally stored asset, but the path was too long for the filesystem. Disabling local storage.", e);
            }
            catch (DirectoryNotFoundException) {
                // Kinda expected if that's an item that's not been stored locally.
            }
            catch (UnauthorizedAccessException e) {
                _config.DisableLocalStorage();
                LOG.Log(Logging.LogLevel.Error, () => "[ASSET_READER] Attempted to read a locally stored asset, but this user is not allowed access. Disabling local storage.", e);
            }
            catch (FileNotFoundException) {
                // Kinda expected if that's an item that's not been stored locally.
            }
            catch (IOException e) {
                // This could be temporary.
                LOG.Log(Logging.LogLevel.Warn, () => "[ASSET_READER] Attempted to read a locally stored asset, but there was an IO error.", e);
            }
            catch (ProtoException e) {
                LOG.Log(Logging.LogLevel.Warn, () => $"[ASSET_READER] Attempted to read a locally stored asset, but there was a protobuf decoding error. Removing the offending local storage file as it is either corrupt or from an older installation: {path}", e);
                removeFile = true;
            }

            if (removeFile)
            {
                try {
                    File.Delete(path);
                    // TODO: at some point the folder tree should be checked for folders that should be removed.
                }
#pragma warning disable RECS0022 // A catch clause that catches System.Exception and has an empty body
                catch {
                    // If there's a delete failure it'll just keep trying as the asset is called for again.
                }
#pragma warning restore RECS0022 // A catch clause that catches System.Exception and has an empty body
            }

            // Nope, no ability to get the asset.
            asset = null;
            return(false);
        }