Exemplo n.º 1
0
        /// <summary>
        /// Write data to file
        /// </summary>
        /// <param name="key">Key which identifies the data. If the key already exists, previous data will be overwritten.</param>
        /// <param name="data">Data bytes to store</param>
        public void Write(Guid key, byte[] data, int offset, int length)
        {
            lock (sync)
            {
                CheckDisposed();
                GrowFile(data.Length == 0 ? 1 : length);

                HeaderCluster entry = null;
                int           safeCopyClusterNumber = -1;

                if (index.ContainsKey(key))
                {
                    safeCopyClusterNumber = (int)index[key];
                    entry      = AllocateNewHeader(key, length);
                    index[key] = entry.ClusterNumber;

                    MarkAsSafeCopy(safeCopyClusterNumber);
                }
                else
                {
                    entry = AllocateNewHeader(key, length);
                    index.Add(key, entry.ClusterNumber);
                }

                // Write to allocated head
                int         dataOffset = offset;
                DataCluster cluster    = entry;
                byte[]      buffer     = new byte[clusterSize];

                do
                {
                    int headerBytes    = (cluster is HeaderCluster ? HeaderCluster.HeaderBytes : DataCluster.HeaderBytes);
                    int remainingBytes = clusterSize - headerBytes;
                    // Position to start of the stream
                    PositionToCluster(cluster.ClusterNumber);
                    // Write cluster header information to prepared buffer
                    WriteCluster(cluster, buffer);
                    // See how many bytes we are writing
                    int writtenBytes = Math.Min(remainingBytes, length - (dataOffset - offset));
                    // Copy the data from the incomming buffer to prepared buffer
                    Array.Copy(data, dataOffset, buffer, headerBytes, writtenBytes);
                    // Write the prepared buffer
                    fs.Write(buffer, 0, clusterSize);
                    // Advance the dataOffset
                    dataOffset += remainingBytes;
                    // Move to next cluster
                    cluster = cluster.NextCluster;
                }while ((dataOffset - offset) < length);

                if (safeCopyClusterNumber != -1)
                {
                    DeleteChain(safeCopyClusterNumber, true);
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Reads the chain of clusters
        /// </summary>
        /// <param name="clusterNumber">Cluster number</param>
        /// <returns>Cluster chain</returns>
        private DataCluster ReadChain(int clusterNumber)
        {
            if (clusterNumber == -1)
            {
                return(null);
            }

            // Position to start of cluster
            PositionToCluster(clusterNumber);

            byte[] buffer = new byte[HeaderCluster.HeaderBytes];
            fs.Read(buffer, 0, buffer.Length);

            ClusterFlags flags = (ClusterFlags)buffer[0];

            if ((flags & ClusterFlags.StreamHeader) != 0)
            {
                HeaderCluster cluster = new HeaderCluster(
                    flags,
                    new Guid(new byte[] { buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10], buffer[11], buffer[12], buffer[13], buffer[14], buffer[15], buffer[16], buffer[17], buffer[18], buffer[19], buffer[20] }),
                    clusterNumber,
                    BitConverter.ToInt32(buffer, 21),
                    ReadChain(BitConverter.ToInt32(buffer, 1))
                    );

                return(cluster);
            }
            else
            {
                if ((flags & ClusterFlags.StreamData) != 0)
                {
                    DataCluster cluster = new DataCluster(
                        flags,
                        clusterNumber,
                        ReadChain(BitConverter.ToInt32(buffer, 1)));

                    return(cluster);
                }
                else
                {
                    return(null);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Writes cluster information to byte array
        /// </summary>
        /// <param name="cluster">Cluster to write</param>
        /// <param name="buffer">Byte array</param>
        private static void WriteCluster(DataCluster cluster, byte[] buffer)
        {
            if (cluster is HeaderCluster)
            {
                HeaderCluster head = cluster as HeaderCluster;
                // Store information in format [Flags][Next][Key][Length]
                buffer[0] = (byte)cluster.Flags;
                Array.Copy(BitConverter.GetBytes(head.NextCluster == null ? -1 : head.NextCluster.ClusterNumber), 0, buffer, 1, 4);
                Array.Copy(head.Key.ToByteArray(), 0, buffer, 5, 16);
                Array.Copy(BitConverter.GetBytes(head.DataLength), 0, buffer, 21, 4);
            }
            else
            {
#if DEBUG
                Debug.Assert(cluster is DataCluster);
#endif
                buffer[0] = (byte)cluster.Flags;
                Array.Copy(BitConverter.GetBytes(cluster.NextCluster == null ? -1 : cluster.NextCluster.ClusterNumber), 0, buffer, 1, 4);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Takes empty clusters and reserves a header cluster
        /// </summary>
        /// <param name="key">Key for the data</param>
        /// <param name="length">Bytes required</param>
        /// <returns>Head allocation</returns>
        private HeaderCluster AllocateNewHeader(Guid key, int length)
        {
            HeaderCluster head = new HeaderCluster(ClusterFlags.StreamHeader,
                                                   key,
                                                   emptyClusters.Dequeue(),
                                                   length,
                                                   null);

            int         remainingLength = length - (clusterSize - HeaderCluster.HeaderBytes);
            DataCluster prev            = head;

            while (remainingLength > 0)
            {
                DataCluster data = new DataCluster(ClusterFlags.StreamData,
                                                   emptyClusters.Dequeue(),
                                                   null);

                remainingLength -= (clusterSize - DataCluster.HeaderBytes);
                prev.NextCluster = data;
                prev             = data;
            }

            return(head);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Reads the chain of clusters
        /// </summary>
        /// <param name="clusterNumber">Cluster number</param>
        /// <returns>Cluster chain</returns>
        private DataCluster ReadChain(int clusterNumber)
        {
            if (clusterNumber == -1)
            {
                return null;
            }

            // Position to start of cluster
            PositionToCluster(clusterNumber);

            byte[] buffer = new byte[HeaderCluster.HeaderBytes];
            fs.Read(buffer, 0, buffer.Length);

            ClusterFlags flags = (ClusterFlags)buffer[0];

            if ((flags & ClusterFlags.StreamHeader) != 0)
            {
                HeaderCluster cluster = new HeaderCluster(
                flags,
                new Guid(new byte[] { buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10], buffer[11], buffer[12], buffer[13], buffer[14], buffer[15], buffer[16], buffer[17], buffer[18], buffer[19], buffer[20] }),
                clusterNumber,
                BitConverter.ToInt32(buffer, 21),
                ReadChain(BitConverter.ToInt32(buffer, 1))
                );

                return cluster;
            }
            else
            {
                if ((flags & ClusterFlags.StreamData) != 0)
                {

                    DataCluster cluster = new DataCluster(
                    flags,
                    clusterNumber,
                    ReadChain(BitConverter.ToInt32(buffer, 1)));

                    return cluster;
                }
                else
                {
                    return null;
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Takes empty clusters and reserves a header cluster
        /// </summary>
        /// <param name="key">Key for the data</param>
        /// <param name="length">Bytes required</param>
        /// <returns>Head allocation</returns>
        private HeaderCluster AllocateNewHeader(Guid key, int length)
        {
            HeaderCluster head = new HeaderCluster(ClusterFlags.StreamHeader,
                                                   key,
                                                   emptyClusters.Dequeue(),
                                                   length,
                                                   null);

            int remainingLength = length - (clusterSize - HeaderCluster.HeaderBytes);
            DataCluster prev = head;

            while (remainingLength > 0)
            {
                DataCluster data = new DataCluster(ClusterFlags.StreamData,
                                                          emptyClusters.Dequeue(),
                                                          null);

                remainingLength -= (clusterSize - DataCluster.HeaderBytes);
                prev.NextCluster = data;
                prev = data;
            }

            return head;
        }