18 using System.Collections.Generic;
22 namespace Deveel.Data.Store {
24 private readonly
object objectLock =
new object();
29 if (fileSystem == null)
30 throw new ArgumentNullException(
"fileSystem");
32 FileSystem = fileSystem;
33 MaxFileSlice = maxFileSlice;
34 FileExtention = fileExtention;
37 fileSlices =
new List<FileStoreData>();
44 public string BasePath {
get;
private set; }
46 public string FileName {
get;
private set; }
48 public string FileExtention {
get;
private set; }
50 public int MaxFileSlice {
get;
private set; }
54 public int FileCount {
57 string f = SliceFileName(i);
58 while (FileSystem.FileExists(f)) {
66 public bool IsOpen {
get;
private set; }
70 return FileSystem.CombinePath(BasePath, String.Format(
"{0}.{1}", FileName, FileExtention));
72 var fn =
new StringBuilder();
81 return Path.Combine(BasePath, fn.ToString());
85 long runningTotal = 0;
90 string f = SliceFileName(i);
91 while (FileSystem.FileExists(f)) {
92 var fileLength = FileSystem.GetFileSize(f);
94 runningTotal += fileLength;
106 foreach (var slice
in fileSlices) {
118 GC.SuppressFinalize(
this);
122 get {
return FileSystem.FileExists(SliceFileName(0)); }
128 return IsOpen ? trueFileLength : DiscoverSize();
133 public bool IsReadOnly {
get;
private set; }
137 int countFiles = FileCount;
139 for (
int i = countFiles - 1; i >= 0; --i) {
140 string f = SliceFileName(i);
148 public void Open(
bool readOnly) {
151 string f = SliceFileName(0);
152 bool openExisting = FileSystem.FileExists(f);
156 if (openExisting && f.Length > MaxFileSlice) {
157 string f2 = SliceFileName(1);
158 if (FileSystem.FileExists(f2))
159 throw new IOException(
"File length exceeds maximum slice size setting.");
163 throw new IOException(
"Unable to convert to a scattered store because Read-only.");
168 slice.Open(readOnly);
170 fileSlices.Add(slice);
171 long runningLength = slice.Length;
177 string slicePart = SliceFileName(i);
178 while (FileSystem.FileExists(slicePart)) {
181 slice.Open(readOnly);
183 fileSlices.Add(slice);
184 runningLength += slice.Length;
187 slicePart = SliceFileName(i);
191 trueFileLength = runningLength;
193 IsReadOnly = readOnly;
200 foreach (var slice
in fileSlices) {
206 public int Read(
long position, byte[] buffer,
int offset,
int length) {
210 int fileI = (int)(position / MaxFileSlice);
211 long fileP = (position % MaxFileSlice);
212 int fileLen = (int)
System.Math.Min((
long)length, MaxFileSlice - fileP);
217 if (fileI < 0 || fileI >= fileSlices.Count) {
220 throw new IOException(
"Store not open.");
224 slice = fileSlices[fileI];
227 int readCount =slice.
Read(fileP, buffer, offset, fileLen);
231 position += readCount;
240 public void Write(
long position, byte[] buffer,
int offset,
int length) {
243 var fileI = (int)(position / MaxFileSlice);
244 var fileP = (position % MaxFileSlice);
245 var fileLen = (int)
System.Math.Min((
long)length, MaxFileSlice - fileP);
250 if (fileI < 0 || fileI >= fileSlices.Count) {
252 throw new IOException(
"Store not open.");
256 slice = fileSlices[fileI];
259 slice.
Write(fileP, buffer, offset, fileLen);
269 foreach (var slice
in fileSlices) {
278 long totalSizeToGrow = value - trueFileLength;
280 if (totalSizeToGrow < 0) {
281 throw new IOException(
"Unable to make the data area size " +
282 "smaller for this type of store.");
285 while (totalSizeToGrow > 0) {
287 int last = fileSlices.Count - 1;
288 var slice = fileSlices[last];
289 long oldSliceLength = slice.Length;
290 long toGrow =
System.Math.Min(totalSizeToGrow, (MaxFileSlice - oldSliceLength));
293 slice.SetLength(oldSliceLength + toGrow);
296 totalSizeToGrow -= toGrow;
298 if (totalSizeToGrow > 0) {
299 string sliceFile = SliceFileName(last + 1);
304 fileSlices.Add(slice);
307 trueFileLength = value;
void Dispose(bool disposing)
void Write(long position, byte[] buffer, int offset, int length)
Writes a given buffer into the block, starting at the absolute position given.
ScatteringFileStoreData(IFileSystem fileSystem, string basePath, string fileName, string fileExtention, int maxFileSlice)
void Close()
Closes the block and make it unavailable.
string SliceFileName(int i)
void Write(long position, byte[] buffer, int offset, int length)
Writes a given buffer into the block, starting at the absolute position given.
bool Delete()
Deletes the data block.
List< FileStoreData > fileSlices
bool Delete()
Deletes the data block.
~ScatteringFileStoreData()
int Read(long position, byte[] buffer, int offset, int length)
Reads a given amount of data from the block, starting at the absolute position given and copying into...
void SetLength(long value)
Sets the length of the data block.
An interface for low level store data access methods.
A data store that is backed by a file located at the path given.
void Open(bool readOnly)
Opens the data block and make it ready to be accessed.
int Read(long position, byte[] buffer, int offset, int length)
Reads a given amount of data from the block, starting at the absolute position given and copying into...
void Flush()
Flushes the data written in the temporary store of the block to the underlying medium.