DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
InMemoryStore.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 using System;
18 using System.Collections.Generic;
19 using System.IO;
20 using System.Threading;
21 
22 namespace Deveel.Data.Store {
27  public class InMemoryStore : IStore {
30  private long uniqueIdKey;
31 
32  internal InMemoryStore(string name, int hashSize) {
33  Name = name;
34  areaMap = new InMemoryBlock[hashSize];
35  uniqueIdKey = 0;
36  }
37 
39  Dispose(false);
40  }
41 
45  public string Name { get; private set; }
46 
47  private InMemoryBlock FixedAreaBlock {
48  get {
49  lock (this) {
50  if (fixedAreaBlock == null)
51  fixedAreaBlock = new InMemoryBlock(-1, 64);
52 
53  return fixedAreaBlock;
54  }
55  }
56  }
57 
58  private void Dispose(bool disposing) {
59  if (disposing) {
60  fixedAreaBlock = null;
61  areaMap = null;
62  }
63  }
64 
65  public void Dispose() {
66  Dispose(true);
67  GC.SuppressFinalize(this);
68  }
69 
70  private InMemoryBlock GetBlock(long pointer) {
71  if (pointer == -1)
72  return FixedAreaBlock;
73 
74  return GetAreaBlock(pointer);
75  }
76 
77  private InMemoryBlock GetAreaBlock(long pointer) {
78  lock (this) {
79  // Find the pointer in the hash
80  var hashPos = (int)(pointer % areaMap.Length);
81  InMemoryBlock prev = null;
82  var block = areaMap[hashPos];
83 
84  // Search for this pointer
85  while (block != null && block.Id != pointer) {
86  prev = block;
87  block = block.Next;
88  }
89 
90  if (block == null)
91  throw new IOException("Pointer " + pointer + " is invalid.");
92 
93  // Move the element to the start of the list.
94  if (prev != null) {
95  prev.Next = block.Next;
96  block.Next = areaMap[hashPos];
97  areaMap[hashPos] = block;
98  }
99 
100  return block;
101  }
102  }
103 
105  public IArea CreateArea(long size) {
106  if (size > Int32.MaxValue)
107  throw new IOException("'size' is too large.");
108 
109  lock (this) {
110  // Generate a unique id for this area.
111  long id = uniqueIdKey;
112  ++uniqueIdKey;
113 
114  // Create the element.
115  var element = new InMemoryBlock(id, (int)size);
116 
117  // The position in the hash map
118  int hashPos = (int)(id % areaMap.Length);
119 
120  // Add to the chain
121  element.Next = areaMap[hashPos];
122  areaMap[hashPos] = element;
123 
124  return element.GetArea(false);
125  }
126  }
127 
129  public void DeleteArea(long id) {
130  lock (this) {
131  // Find the pointer in the hash
132  var hashPos = (int)(id % areaMap.Length);
133  InMemoryBlock prev = null;
134  InMemoryBlock block = areaMap[hashPos];
135 
136  // Search for this pointer
137  while (block != null && block.Id != id) {
138  prev = block;
139  block = block.Next;
140  }
141 
142  // If not found
143  if (block == null)
144  throw new IOException("Area ID " + id + " is invalid.");
145 
146  // Remove
147  if (prev == null) {
148  areaMap[hashPos] = block.Next;
149  } else {
150  prev.Next = block.Next;
151  }
152 
153  // Garbage collector should do the rest...
154  }
155  }
156 
158  public IArea GetArea(long id, bool readOnly) {
159  return GetBlock(id).GetArea(readOnly);
160  }
161 
163  public void Lock() {
164  }
165 
167  public void Unlock() {
168  }
169 
171  public void CheckPoint() {
172  }
173 
175  public bool ClosedClean {
176  get { return true; }
177  }
178 
180  public IEnumerable<long> GetAllAreas() {
181  throw new NotImplementedException();
182  }
183 
184  #region InMemoryBlock
185 
187  private readonly byte[] block;
188 
189  public InMemoryBlock(long id, int size) {
190  Id = id;
191  block = new byte[size];
192  }
193 
194  public long Id { get; private set; }
195 
196  public InMemoryBlock Next { get; set; }
197 
198  public IArea GetArea(bool readOnly) {
199  return new InMemoryArea(Id, readOnly, block, 0, block.Length);
200  }
201  }
202 
203  #endregion
204 
205  #region InMemoryArea
206 
207  class InMemoryArea : IArea {
208  private readonly byte[] data;
209  private long position;
210  private readonly int startPosition;
211  private readonly int endPosition;
212 
213  public InMemoryArea(long id, bool readOnly, byte[] data, int offset, int length) {
214  this.data = data;
215  Length = length;
216 
217  position = startPosition = offset;
218  endPosition = offset + length;
219 
220  Id = id;
221  IsReadOnly = readOnly;
222  }
223 
224  public long Id { get; private set; }
225 
226  public bool IsReadOnly { get; private set; }
227 
228  public long Position {
229  get { return position; }
230  set {
231  var actPosition = startPosition + value;
232  if (actPosition < 0 || actPosition >= endPosition)
233  throw new IOException("Moved position out of bounds.");
234 
235  position = actPosition;
236  }
237  }
238 
239  public int Capacity {
240  get { return endPosition - startPosition; }
241  }
242 
243  public int Length { get; private set; }
244 
245  private long CheckPositionBounds(int diff) {
246  var newPos = position + diff;
247  if (newPos > endPosition)
248  throw new IOException(String.Format("Attempt to read out of bounds: from {0} to {1} (position {2} to {3})",
249  startPosition, endPosition, position, newPos));
250 
251  var oldPos = position;
252  position = newPos;
253  return oldPos;
254  }
255 
256  public void CopyTo(IArea destArea, int size) {
257  const int bufferSize = 2048;
258  byte[] buf = new byte[bufferSize];
259  int toCopy = System.Math.Min(size, bufferSize);
260 
261  while (toCopy > 0) {
262  Read(buf, 0, toCopy);
263  destArea.Write(buf, 0, toCopy);
264  size -= toCopy;
265  toCopy = System.Math.Min(size, bufferSize);
266  }
267  }
268 
269  public int Read(byte[] buffer, int offset, int length) {
270 #if PCL
271  Array.Copy(data, (int)CheckPositionBounds(length), buffer, offset, length);
272 #else
273  Array.Copy(data, CheckPositionBounds(length), buffer, offset, length);
274 #endif
275  return length;
276  }
277 
278  public void Write(byte[] buffer, int offset, int length) {
279 #if PCL
280  Array.Copy(buffer, offset, data, (int) CheckPositionBounds(length), length);
281 #else
282  Array.Copy(buffer, offset, data, CheckPositionBounds(length), length);
283 #endif
284  }
285 
286  public void Flush() {
287  }
288  }
289 
290  #endregion
291  }
292 }
InMemoryBlock GetAreaBlock(long pointer)
void DeleteArea(long id)
Deletes an area that was previously allocated by the CreateArea method by the area id...
void Write(byte[] buffer, int offset, int length)
An implementation of IStore that persists data in the application memory.
IArea CreateArea(long size)
Allocates a block of memory in the store of the specified size and returns an IArea object that can b...
InMemoryStore(string name, int hashSize)
void Dispose(bool disposing)
void Lock()
This method is called before the start of a sequence of Write commands between consistant states of s...
void Unlock()
This method is called after the end of a sequence of Write commands between consistant states of some...
int Read(byte[] buffer, int offset, int length)
Reads an array of bytes from the underlying IArea and advances the position by length ...
An interface for access the contents of an area of a store.
Definition: IArea.cs:23
IArea GetArea(long id, bool readOnly)
Returns an object that allows for the contents of an area (represented by the id parameter) to be Re...
InMemoryBlock GetBlock(long pointer)
IEnumerable< long > GetAllAreas()
Returns a complete list of pointers to all areas in the Store as long objects sorted from lowest poin...
InMemoryArea(long id, bool readOnly, byte[] data, int offset, int length)
void Write(byte[] buffer, int offset, int length)
A store is a resource where areas can be allocated and freed to store information (a memory allocator...
Definition: IStore.cs:56
void CopyTo(IArea destArea, int size)
Copies the given amount of bytes from the current position of the this area to another one...