예제 #1
0
        /// <summary>
        /// Asynchronously stores a scrobble in the underlying cache file.
        /// Will throw an exception if the cache file cannot be accessed.
        /// This method is thread safe.
        /// </summary>
        public async Task StoreAsync(Scrobble scrobble)
        {
            EnsureFileLockIsAcquired();

            using (await _fileOperationAsyncLock.LockAsync())
            {
                // Note about the file content:
                // The file is line separated.
                // Instead of writing the data followed by a new line, we do the opposite:
                // We always start by writing a new line, followed by the data.
                // This way, we don't risk continuing a corrupted line without a proper line ending.
                // Unreadable lines can then be discarded, and we lose only one record instead of two.

                await EnsureCorrectHeaderAndGetFileVersionAsync(_fileStream);

                // Skip to the end of the file to append a new scrobble.
                _fileStream.Seek(0, SeekOrigin.End);

                var    serializedScrobble = ScrobbleSerializer.Serialize(scrobble);
                byte[] buffer             = Encoding.UTF8.GetBytes(serializedScrobble);
                byte[] newLineBuffer      = Encoding.UTF8.GetBytes("\n");
                await _fileStream.WriteAsync(newLineBuffer, 0, newLineBuffer.Length);

                await _fileStream.WriteAsync(buffer, 0, buffer.Length);
            }
        }
예제 #2
0
        /// <summary>
        /// Erases the file, write a new header, then write the scrobbles.
        /// </summary>
        private static async Task OverwriteFileAsync(FileStream fs, IEnumerable <Scrobble> scrobbles)
        {
            // Truncate the file.
            fs.SetLength(0);
            // Write the header.
            await EnsureCorrectHeaderAndGetFileVersionAsync(fs);

            // Skip to the end of the file to append the scrobbles.
            fs.Seek(0, SeekOrigin.End);

            // To minimize file writes, we use a StringBuilder that will be written in the file
            // in as few buffer lengths as possible.
            StringBuilder sb = new StringBuilder();

            foreach (var scrobble in scrobbles)
            {
                var serialized = ScrobbleSerializer.Serialize(scrobble);
                sb.AppendLine();
                sb.Append(serialized);
            }

            byte[] buffer = Encoding.UTF8.GetBytes(sb.ToString());
            await fs.WriteAsync(buffer, 0, buffer.Length);
        }