Esempio n. 1
0
        public void Delete(T t)
        {
            using (var _dataIndexFile = new BlobIndexFile(_dataIndexFilePath, DiskBufferSizes.Larger, DiskBufferSizes.Default))
            {
                var searchKey = InternalReflectionHelper.GetPropertyValueInt32 <T>(t, "Id");
                var dataIndex = _dataIndexFile.FindIndex(searchKey);

                if (dataIndex == null)
                {
                    return;
                }

                using (var _deletedDataIndexFile = new BlobIndexFile(_deletedDataIndexFilePath, DiskBufferSizes.Larger, DiskBufferSizes.Default))
                {
                    // create a new deleted data index in deleted file pointing to deleted data.
                    _deletedDataIndexFile.AddIndexOverwriteDeleted(dataIndex);
                }

                // no need to delete the data just mark the index entry as deleted
                _dataIndexFile.RemoveIndex(searchKey);

                // update the record count.
                var header = GetDataHeader();
                header.RemoveRecord();
                UpdateDataHeader(header);
            }
        }
Esempio n. 2
0
        public T Update(T entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("Entity argument can't be null");
            }

            // make sure the entity name matches the document store type.
            string requiredEntityName = entity.GetType().Name;

            if (_entityName != requiredEntityName)
            {
                throw new ArgumentException("Entity type is not valid for this data store.");
            }

            // make sure entity has key field
            if (!InternalReflectionHelper.PropertyExists(entity, "Id"))
            {
                throw new Exception("Entity must have an Id property and be of type short, integer or long." +
                                    "This is used as the primary key for the entity being stored.");
            }

            // load the document key from the entity as its needed for adding to the index.
            var documentKey = InternalReflectionHelper.GetPropertyValueInt64(entity, "Id");

            using (var _dataIndexFile = new BlobIndexFile(_dataIndexFilePath, DiskBufferSizes.Larger, DiskBufferSizes.Default))
            {
                // search the data store for the document.
                var dataIndex = _dataIndexFile.FindIndex(documentKey);
                if (dataIndex == null)
                {
                    throw new Exception("Could not find an existing entity to update.");
                }

                // either overwrite entity in existing data slot or append to the the end of the file.
                // parse the document into a binary json document
                byte[] binaryJson = _serializer.Serialize <T>(entity);

                // write the data record to the data file
                // update the record index to the documents data size.
                dataIndex.UpdateRecordLength(binaryJson.Length);

                using (var _fileStreamWriter = new FileStream(_dataFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read,
                                                              (int)DiskBufferSizes.Default, FileOptions.SequentialScan))
                {
                    using (var _binaryWriter = new BinaryWriter(_fileStreamWriter))
                    {
                        // check to see if the record needs relocated.
                        // if it does then set the position to the end of the file.
                        if (dataIndex.RequiresRelocation == true)
                        {
                            using (var _deletedDataIndexFile = new BlobIndexFile(_deletedDataIndexFilePath, DiskBufferSizes.Larger, DiskBufferSizes.Default))
                            {
                                // create a deleted record pointer to the data file.
                                _deletedDataIndexFile.AddIndexOverwriteDeleted(dataIndex);
                            }

                            // set position of the document to the end of the file
                            _binaryWriter.BaseStream.Position = this.FileSize;

                            // update the record pointer in the data index
                            dataIndex.UpdateRecordPointer(_binaryWriter.BaseStream.Position, this.PaddingFactor);

                            // update the file size.
                            this.FileSize = this.FileSize + dataIndex.RecordLength + dataIndex.PaddingLength;
                        }
                        else
                        {
                            // set the position of where the document is in the datafile.
                            _binaryWriter.BaseStream.Position = dataIndex.Pointer;
                        }

                        // make changes to the data
                        _binaryWriter.Write(binaryJson);

                        // write the padding bytes
                        if (dataIndex.PaddingLength > 0)
                        {
                            _binaryWriter.Write(new Byte[dataIndex.PaddingLength]);
                        }

                        // update data index pointer to point to new location.
                        _dataIndexFile.UpdateIndex(dataIndex);

                        // save the data
                        _binaryWriter.Flush();
                    }
                }
            }

            return(entity);
        }
Esempio n. 3
0
        public T Create(T entity)
        {
            if (entity == null)
            {
                throw new ArgumentNullException("Entity argument can't be null");
            }

            // make sure the entity name matches the document store type.
            string requiredEntityName = entity.GetType().Name;

            if (_entityName != requiredEntityName)
            {
                throw new ArgumentException("Entity type is not valid for this data store.");
            }

            // make sure entity has key field
            if (!InternalReflectionHelper.PropertyExists(entity, "Id"))
            {
                throw new Exception("Entity must have an Id property and be of type short, integer or long." +
                                    "This is used as the primary key for the entity being stored.");
            }

            // load the document key from the entity as its needed for adding to the index.
            var documentKey = InternalReflectionHelper.GetPropertyValueInt64(entity, "Id");

            // get the data store header so we can generate keys and store record counts.
            var header = GetDataHeader();

            // boolean so we know to check for duplicate or not on insert.
            // duplicates only need checked when the user has specified the document key.
            bool checkForDuplicate = true;

            if (documentKey == 0)
            {
                checkForDuplicate = false;
            }

            // get the next document key from the data file header record.
            documentKey = header.GenerateNextRecord(documentKey);

            // update the entity value so that the callers entity gets the saved document key.
            InternalReflectionHelper.SetPropertyValue(entity, "Id", documentKey);

            // parse the document into a binary json document for storing in the data file.
            byte[] binaryJson = _serializer.Serialize <T>(entity);

            using (var _deletedDataIndexFile = new BlobIndexFile(_deletedDataIndexFilePath, DiskBufferSizes.Larger, DiskBufferSizes.Default))
            {
                // create the data index with the data pointer at the end of the document.
                // check to see if there is a deleted slot that can be used to store the data.
                var dataIndex = _deletedDataIndexFile.GetBlobIndexWithEnoughSpace(binaryJson.Length);
                if (dataIndex != null)
                {
                    // assign this document key to the deleted index.
                    dataIndex.ChangeDocumentKey(documentKey);
                    dataIndex.UpdateRecordLength(binaryJson.Length);
                }
                else
                {
                    // create a new data index.
                    dataIndex = new BlobIndex(documentKey, this.FileSize, binaryJson.Length, this.PaddingFactor);

                    // update the size of the datafile
                    this.FileSize = this.FileSize + dataIndex.RecordLength + dataIndex.PaddingLength;
                }

                using (var _dataIndexFile = new BlobIndexFile(_dataIndexFilePath, DiskBufferSizes.Larger, DiskBufferSizes.Default))
                {
                    // create the data index (AddIndex throws ConcurrencyException so no data will save)
                    if (checkForDuplicate)
                    {
                        _dataIndexFile.AddIndexCheckForDuplicate(dataIndex);
                    }
                    else
                    {
                        _dataIndexFile.AddIndex(dataIndex);
                    }
                }

                // remove the index from the deleted index file if it exists
                _deletedDataIndexFile.RemoveIndex(dataIndex.DocumentKey);

                using (var _fileStreamWriter = new FileStream(_dataFilePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read,
                                                              (int)DiskBufferSizes.Default, FileOptions.SequentialScan))
                {
                    using (var _binaryWriter = new BinaryWriter(_fileStreamWriter))
                    {
                        // add the data record to the data file
                        _binaryWriter.BaseStream.Position = dataIndex.Pointer;

                        // write the record
                        _binaryWriter.Write(binaryJson);

                        // write the padding.
                        if (dataIndex.PaddingLength > 0)
                        {
                            _binaryWriter.Write(new Byte[dataIndex.PaddingLength]);
                        }

                        // save the data
                        _binaryWriter.Flush();
                    }
                }
                // update the header record
                UpdateDataHeader(header);
            }

            return(entity);
        }