/// <summary>
        /// Opens the file in write mode and allows appending items to it. The filepointer is set to the end of the file.
        /// </summary>
        /// <param name="path">The path of the file. </param>
        /// <param name="elementsToValidate">The elements of the ItemDescription to validate.
        /// <see cref="ItemDescriptionElements"/> for details. </param>
        /// <returns>. </returns>
        /// <exception cref="ArgumentException">If path is null.</exception>
        public static TeaFile <T> Append(string path, ItemDescriptionElements elementsToValidate = ItemDescriptionElements.All)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            Stream headerStream = null;
            Stream stream       = new FileStream(path, FileMode.Append, FileAccess.Write, FileShare.Read);

            try
            {
                headerStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                return(Append(stream, true, headerStream, elementsToValidate));
            }
            catch (Exception)
            {
                stream.Dispose();
                throw;
            }
            finally
            {
                if (headerStream != null)
                {
                    headerStream.Dispose();
                }
            }
        }
        static TeaFile <T> OpenRead(Stream stream, bool ownsStream, ItemDescriptionElements elementsToValidate)
        {
            var tf = new TeaFile <T>();

            try
            {
                tf.core   = new TeaFileCore(stream, ownsStream);
                tf.buffer = new SafeBuffer <T>(stream);
                tf.core.ReadHeader();

                //  reflecting the current type incurs some cost, so we do it only if we are asked to consider
                //  current item layout to check it against to layout described in the file
                ItemDescription accessorDescription = null;
                if (elementsToValidate != ItemDescriptionElements.None)
                {
                    accessorDescription = ItemDescription.FromAnalysis <T>();
                }
                tf.core.IsAccessibleWith(accessorDescription, elementsToValidate);
                return(tf);
            }
            catch (Exception)
            {
                tf.Dispose();
                throw;
            }
        }
 /// <summary>Opens a TeFile in write mode. </summary>
 /// <exception cref="ArgumentNullException"><paramref name="stream"/> is null. </exception>
 /// <param name="stream">The underlying storage media. </param>
 /// <param name="elementsToValidate">Elements of the ItemDescription to be checked.
 /// <see cref="ItemDescriptionElements"/> for details. </param>
 /// <returns>A TeaFile, open in write mode. </returns>
 public static TeaFile <T> OpenWrite(Stream stream, ItemDescriptionElements elementsToValidate = ItemDescriptionElements.All)
 {
     if (stream == null)
     {
         throw new ArgumentNullException("stream");
     }
     return(OpenWrite(stream, false, elementsToValidate));
 }
        /// <summary>Opens a TeaFile in read only mode. </summary>
        /// <exception cref="ArgumentNullException">Thrown when path is null. </exception>
        /// <param name="path">The path of the file. </param>
        /// <param name="elementsToValidate">Elements of the ItemDescription of <typeparamref name="T"/> compared against hose inside thefile.
        /// <see cref="ItemDescriptionElements"/> for details. </param>
        /// <returns>The file, open for reading. </returns>
        public static TeaFile <T> OpenRead(string path, ItemDescriptionElements elementsToValidate = ItemDescriptionElements.All)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            Stream stream = new FileStream(path, FileMode.Open);

            return(OpenRead(stream, true, elementsToValidate));
        }
Exemplo n.º 5
0
        public void IsAccessibleWith(ItemDescription accessorDescription, ItemDescriptionElements elements)
        {
            // without descriptions in the file we cannot check anything. No warning will be issued in such case,
            // the user is responsible to check that files have descriptions if desired.
            if (this.Description == null)
            {
                return;
            }
            if (this.Description.ItemDescription == null)
            {
                return;
            }

            var fileDescription = this.Description.ItemDescription;

            fileDescription.IsAccessibleWith(accessorDescription, elements);
        }
        /// <summary>Opens a TeFile in write mode. </summary>
        /// <exception cref="ArgumentNullException">Path is null. </exception>
        /// <param name="path">The path of the file. </param>
        /// <param name="elementsToValidate">Elements of the ItemDescription to be checked.
        /// <see cref="ItemDescriptionElements"/> for details. </param>
        /// <returns>A TeaFile in write mode. </returns>
        /// <remarks><see cref="OpenRead(string,TeaTime.ItemDescriptionElements)"/> about the <paramref name="elementsToValidate"/> parameter.</remarks>
        public static TeaFile <T> OpenWrite(string path, ItemDescriptionElements elementsToValidate = ItemDescriptionElements.All)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }
            Stream stream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read);

            try
            {
                return(OpenWrite(stream, true, elementsToValidate));
            }
            catch
            {
                stream.Dispose();
                throw;
            }
        }
        static TeaFile <T> OpenWrite(Stream stream, bool ownsStream, ItemDescriptionElements elementsToValidate)
        {
            var tf = new TeaFile <T>();

            try
            {
                tf.buffer = new SafeBuffer <T>(stream);
                tf.core   = new TeaFileCore(stream, ownsStream);
                tf.core.ReadHeader();
                tf.core.IsAccessibleWith(ItemDescription.FromAnalysis <T>(), elementsToValidate);
                // filepointer is at begin of item area. finally, the user might want to read.
                // using filepointer is essential here.
                // check the item api to allow this.
                return(tf);
            }
            catch (Exception)
            {
                tf.Dispose();
                throw;
            }
        }
Exemplo n.º 8
0
        public void IsAccessibleWith(ItemDescription accessorDescription, ItemDescriptionElements elements)
        {
            // without descriptions in the file we cannot check anything. No warning will be issued in such case, 
            // the user is responsible to check that files have descriptions if desired.
            if (this.Description == null) return;
            if (this.Description.ItemDescription == null) return;

            var fileDescription = this.Description.ItemDescription;
            fileDescription.IsAccessibleWith(accessorDescription, elements);
        }
        /// <summary>
        /// Checks it the access description can access a time series based on this ItemDescription.
        /// </summary>
        /// <remarks>
        /// policies:<br></br>
        /// If <paramref name="accessorDescription"/> has no fields, the check will always succeed.<br></br>
        ///
        /// </remarks>
        /// <param name="accessorDescription">ItemDescription that describes the type used to access the file.</param>
        /// <param name="elementsToConsider">The amount of details used for the test.</param>
        /// <exception cref="TypeMismatchException">If the accessor type is not suitable to access the file.</exception>
        public void IsAccessibleWith(ItemDescription accessorDescription, ItemDescriptionElements elementsToConsider)
        {
            if (elementsToConsider.HasFlag(ItemDescriptionElements.ItemName))
            {
                if (this.ItemTypeName != accessorDescription.itemTypeName)
                {
                    throw new TypeMismatchException("ItemNames do not match: '{0}' vs '{1}'".Formatted(this.ItemTypeName, accessorDescription.ItemTypeName), "ItemName Check");
                }
            }
            if (elementsToConsider.HasFlag(ItemDescriptionElements.ItemSize))
            {
                if (this.ItemSize != accessorDescription.ItemSize)
                {
                    throw new TypeMismatchException("ItemSizes do not match: {0} vs {1}".Formatted(this.ItemSize, accessorDescription.ItemSize), "ItemSize Check");
                }
            }

            if (elementsToConsider.HasFlag(ItemDescriptionElements.FieldOffsets))
            {
                if (accessorDescription == null)
                {
                    throw new ArgumentNullException("accessorDescription");
                }
                if (!this.fields.Any())
                {
                    throw new TypeMismatchException("No fields are available in {0} to check field offsets. Empty structs are not supported by this API.".Formatted(this.Source.ToString()), "No ItemFields");
                }
                if (!accessorDescription.fields.Any())
                {
                    throw new TypeMismatchException("No fields are available in {0} to check field offsets. Empty structs are not supported by this API.".Formatted(accessorDescription.Source.ToString()), "No ItemFields Accessor");
                }

                var f = this.Fields.FirstOrDefault(ff => accessorDescription.FindFieldByOffset(ff.Offset) == null);
                if (f != null)
                {
                    throw new TypeMismatchException("Field has no field with matching byte offset:'{0}'".Formatted(f), "FieldOffsets Check");
                }
            }
            if (elementsToConsider.HasFlag(ItemDescriptionElements.FieldNames))
            {
                if (accessorDescription == null)
                {
                    throw new ArgumentNullException("accessorDescription");
                }
                // ItemDescriptionDetails.FieldNames includes ItemDescriptionDetails.FieldOffsets by the definition of ItemDescriptionDetails values!
                var f = this.Fields.FirstOrDefault(ff => accessorDescription.FindFieldByOffset(ff.Offset).Name != ff.Name);
                if (f != null)
                {
                    throw new TypeMismatchException("Fields have different names: '{0}' vs '{1}'".Formatted(f, accessorDescription.FindFieldByOffset(f.Offset).Name), "FieldNames Check");
                }
            }
            if (elementsToConsider.HasFlag(ItemDescriptionElements.FieldTypes))
            {
                if (accessorDescription == null)
                {
                    throw new ArgumentNullException("accessorDescription");
                }
                // ItemDescriptionDetails.FieldNames includes ItemDescriptionDetails.FieldOffsets by the definition of ItemDescriptionDetails values!
                var f = this.Fields.FirstOrDefault(ff => accessorDescription.FindFieldByOffset(ff.Offset).FieldType != ff.FieldType);
                if (f != null)
                {
                    throw new TypeMismatchException("Fields have different types: '{0}' vs '{1}'".Formatted(f, accessorDescription.FindFieldByOffset(f.Offset).Name), "FieldTypes Check");
                }
            }
        }
        static TeaFile <T> Append(Stream stream, bool ownsStream, Stream headerReadStream, ItemDescriptionElements elementsToValidate = ItemDescriptionElements.All)
        {
            var tf = new TeaFile <T>();

            try
            {
                TeaFileDescription description;
                tf.core = new TeaFileCore(stream, ownsStream);

                // A file opened for appending, cannot be read. Therefore we create a second file, read it and assign its description to the current TeaFile<> instance.
                using (var tfheader = OpenRead(headerReadStream, false, elementsToValidate)) // we pass headerStream ownership to tfheader, so it will be closed after header reaeding.
                {
                    description = tfheader.Description;
                    if (!tfheader.core.CanAppend)
                    {
                        throw new IOException("Cannot append to file because it has preallocated space between the end of the item area and the end of the file.");
                    }
                    tf.core.Assign(tfheader.ItemAreaStart, tfheader.core.ItemAreaEndMarker);
                }

                // if the stream is a filestream that was opened in FileMode.Append, this call is redundant.
                // this line is here for the allowed case were the stream and headerstream point to the same stream.
                tf.SetFilePointerToEnd();

                tf.core.Description = description;
                tf.buffer           = new SafeBuffer <T>(stream);
                return(tf);
            }
            catch (Exception)
            {
                tf.Dispose();
                throw;
            }
        }