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); } }
public T Find(params object[] keys) { byte[] dataBytes = null; using (var _dataIndexFile = new BlobIndexFile(_dataIndexFilePath, DiskBufferSizes.Larger, DiskBufferSizes.Default)) { using (var _fileStreamReader = new FileStream(_dataFilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write, (int)DiskBufferSizes.Default, FileOptions.SequentialScan)) { using (var _binaryReader = new BinaryReader(_fileStreamReader)) { var dataIndex = _dataIndexFile.FindIndex((long)Convert.ChangeType(keys[0], typeof(long))); if (dataIndex == null) { return(default(T)); } // locate the data in the data store file. _binaryReader.BaseStream.Position = dataIndex.Pointer; dataBytes = _binaryReader.ReadBytes(dataIndex.RecordLength); } } } // parse bytes into an entity and then return var entity = _serializer.Deserialize <T>(dataBytes); return(entity); }
public IQueryable <T> All() { // create a list to hold the documents. var documentList = new List <T>(); long count = 1; using (var _dataIndexFile = new BlobIndexFile(_dataIndexFilePath, DiskBufferSizes.Larger, DiskBufferSizes.Default)) { using (var _fileStreamReader = new FileStream(_dataFilePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write, (int)DiskBufferSizes.Default, FileOptions.SequentialScan)) { using (var _binaryReader = new BinaryReader(_fileStreamReader)) { var dataIndex = _dataIndexFile.GetBlobIndex(count); while (dataIndex != null) { // load the data from the pointer specified in the data index. // locate the data in the data store file. _binaryReader.BaseStream.Position = dataIndex.Pointer; var dataBytes = _binaryReader.ReadBytes(dataIndex.RecordLength); // parse bytes into an entity and then return var entity = _serializer.Deserialize <T>(dataBytes); documentList.Add(entity); count++; dataIndex = _dataIndexFile.GetBlobIndex(count); } } } } return(documentList.AsQueryable <T>()); }
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); }
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); }