예제 #1
0
        public async Task <Possible <CasHash, Failure> > AddToCasAsync(
            string filename,
            FileState fileState,
            CasHash?hash,
            UrgencyHint urgencyHint,
            Guid activityId)
        {
            Contract.Requires(!IsClosed);
            Contract.Requires(filename != null);
            Contract.Assert(!IsReadOnly);

            using (var counter = m_counters.AddToCasCounterFile())
            {
                using (var eventing = new AddToCasFilenameActivity(BasicFilesystemCache.EventSource, activityId, this))
                {
                    eventing.Start(filename, fileState, urgencyHint);

                    Possible <CasHash, Failure> result;

                    // First we need to do the hash of the file
                    // We do this "in place" since the CAS may be
                    // on "slow" storage and this is local
                    try
                    {
                        // We keep the file open during this such that others can't modify it
                        // until the add-to-cas has completed.  It also happens to be needed
                        // in order to compute the hash.
                        using (var fileData = await m_cache.ContendedOpenStreamAsync(filename, FileMode.Open, FileAccess.Read, FileShare.Read, handlePendingDelete: false))
                        {
                            counter.ContentSize(fileData.Length);

                            CasHash casHash = new CasHash(await ContentHashingUtilities.HashContentStreamAsync(fileData));

                            try
                            {
                                if (!await m_cache.AddToCasAsync(filename, casHash))
                                {
                                    counter.DuplicatedContent();
                                }

                                // Pin it and return the hash
                                m_pinnedToCas.TryAdd(casHash, 0);
                                result = casHash;
                            }
                            catch (Exception e)
                            {
                                counter.Failed();
                                result = new AddToCasFailure(CacheId, casHash, filename, e);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        counter.Failed();
                        result = new HashFailure(CacheId, filename, e);
                    }

                    return(eventing.Returns(result));
                }
            }
        }
예제 #2
0
        public async Task <Possible <CasHash, Failure> > AddToCasAsync(Stream filestream, CasHash?hash, UrgencyHint urgencyHint, Guid activityId)
        {
            Contract.Requires(!IsClosed);
            Contract.Requires(filestream != null);

            Contract.Assert(!IsReadOnly);

            // We have this interesting issue - we are not sure if the stream is rewindable
            // and the target CAS may not be local so we will end up streaming this to
            // a temporary file just to pass it up.  (Implementation detail)
            using (var counter = m_counters.AddToCasCounterStream())
            {
                using (var eventing = new AddToCasStreamActivity(BasicFilesystemCache.EventSource, activityId, this))
                {
                    eventing.Start(filestream, urgencyHint);

                    Possible <CasHash, Failure> result;

                    string tmpFile = await m_cache.CreateTempFile();

                    // Since these are longer operations that are synchronous, we wrap them
                    // into a task for potential parallelism
                    try
                    {
                        CasHash casHash = await HashStreamToFileAsync(filestream, tmpFile);

                        try
                        {
                            counter.ContentSize(new FileInfo(tmpFile).Length);

                            if (!await m_cache.AddToCasAsync(tmpFile, casHash))
                            {
                                counter.DuplicatedContent();
                            }

                            // Pin it and return the hash
                            m_pinnedToCas.TryAdd(casHash, 0);

                            result = casHash;
                        }
                        catch (Exception e)
                        {
                            counter.Failed();
                            result = new AddToCasFailure(CacheId, casHash, "<stream>", e);
                        }
                    }
                    catch (Exception e)
                    {
                        counter.Failed();
                        result = new HashFailure(CacheId, "<stream>", e);
                    }
                    finally
                    {
                        try
                        {
                            File.Delete(tmpFile);
                        }
#pragma warning disable ERP022 // TODO: This should really handle specific errors
                        catch
                        {
                            // Ignore the failure - it is likely caused by
                            // a semantic breaking tool such as most virus scanners
                            // or disk indexers.  The file was a local teporary file
                            // in the temp directory
                        }
#pragma warning restore ERP022 // Unobserved exception in generic exception handler
                    }

                    return(eventing.Returns(result));
                }
            }
        }