DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
IndexBlock.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.Linq;
20 
21 using Deveel.Data.Store;
22 using Deveel.Data.Util;
23 
24 namespace Deveel.Data.Index {
25  internal class IndexBlock {
26  private readonly IndexSetStore indexSetStore;
27  private readonly int indexNum;
28  private readonly long blockEntries;
29 
30  private List<int> deletedAreas;
31 
32  private int refCount;
33 
34  public IndexBlock(IndexSetStore indexSetStore, int indexNum, int blockSize, long startOffset) {
35  this.indexSetStore = indexSetStore;
36  this.indexNum = indexNum;
37  BlockSize = blockSize;
38  StartOffset = startOffset;
39 
40  // Read the index count
41  var indexBlockArea = indexSetStore.Store.GetArea(startOffset);
42  indexBlockArea.Position = 8;
43  blockEntries = indexBlockArea.ReadInt8();
44 
45  refCount = 0;
46  }
47 
48  public IndexBlock Parent { get; set; }
49 
50  public bool IsFreed { get; private set; }
51 
52  public bool IsDeleted { get; private set; }
53 
54  public int BlockSize { get; private set; }
55 
56  public long StartOffset { get; private set; }
57 
58  public long[] GetBlockPointers() {
59  // Create an area for the index block pointer
60  var indexBlockArea = indexSetStore.Store.GetArea(StartOffset);
61 
62  // First create the list of block entries for this list
63  long[] blocks = new long[(int)blockEntries];
64  if (blockEntries != 0) {
65  indexBlockArea.Position = 16;
66 
67  for (int i = 0; i < blockEntries; ++i) {
68  // NOTE: We cast to 'int' here because of internal limitations.
69  indexBlockArea.ReadInt8();
70  indexBlockArea.ReadInt8();
71  long elementP = indexBlockArea.ReadInt8();
72  indexBlockArea.ReadInt4();
73 
74  blocks[i] = elementP;
75  }
76  }
77 
78  return blocks;
79  }
80 
81  private IEnumerable<IMappedBlock> CreateMappedBlocks() {
82  // Create an area for the index block pointer
83  var indexBlockArea = indexSetStore.Store.GetArea(StartOffset);
84 
85  // First create the list of block entries for this list
86  var blocks = new IMappedBlock[(int) blockEntries];
87  if (blockEntries != 0) {
88  indexBlockArea.Position = 16;
89  for (int i = 0; i < blockEntries; ++i) {
90  // NOTE: We cast to 'int' here because of internal limitations.
91  var firstEntry = indexBlockArea.ReadInt8();
92  var lastEntry = indexBlockArea.ReadInt8();
93  var blockPointer = indexBlockArea.ReadInt8();
94  var typeSize = indexBlockArea.ReadInt4();
95 
96  //TODO: check this...
97  // size is the first 24 bits (max size = 16MB)
98  int elementCount = typeSize & 0x0FFF;
99  byte type = (byte) (ByteBuffer.URShift(typeSize, 24) & 0x0F);
100 
101  blocks[i] = StoreIndex.NewMappedBlock(indexSetStore, firstEntry, lastEntry, blockPointer, elementCount, type,
102  BlockSize);
103  }
104  }
105 
106  return blocks;
107  }
108 
109  public IIndex CreateIndex() {
110  // Create the MappedListBlock objects for this view
111  var blocks = CreateMappedBlocks().Cast<IIndexBlock<int>>();
112  // And return the Index
113  return new StoreIndex(indexSetStore, indexNum, BlockSize, blocks);
114  }
115 
116  private bool DeleteBlockChain() {
117  bool parentDeleted = true;
118  if (Parent != null) {
119  parentDeleted = Parent.DeleteBlockChain();
120  if (parentDeleted) {
121  Parent = null;
122  }
123  }
124 
125  // If the parent is deleted,
126  if (parentDeleted) {
127  // Can we delete this block?
128  if (refCount <= 0) {
129  if (IsDeleted && deletedAreas != null) {
130  indexSetStore.DeleteAreas(deletedAreas);
131  }
132  deletedAreas = null;
133  } else {
134  // We can't delete this block so return false
135  return false;
136  }
137  }
138 
139  return parentDeleted;
140  }
141 
142  public void AddReference() {
143  lock (this) {
144  if (IsFreed)
145  throw new Exception("Assertion failed: Block was freed.");
146 
147  ++refCount;
148  }
149  }
150 
151  public void RemoveReference() {
152  bool pendingDelete = false;
153  lock (this) {
154  --refCount;
155  if (refCount <= 0) {
156  if (IsFreed)
157  throw new Exception("Assertion failed: remove reference called too many times.");
158 
159  if (!IsDeleted && deletedAreas != null)
160  throw new Exception("Assertion failed: not deleted and with deleted areas");
161 
162  IsFreed = true;
163 
164  if (IsDeleted) {
165  AddDeletedArea(StartOffset);
166  // Delete these areas
167  pendingDelete = true;
168  }
169  }
170  } // lock(this)
171 
172  if (pendingDelete) {
173  lock (indexSetStore.Store) {
174  DeleteBlockChain();
175  }
176  }
177  }
178 
179  public void MarkAsDeleted() {
180  lock (this) {
181  IsDeleted = true;
182  }
183  }
184 
185  public void AddDeletedArea(long pointer) {
186  lock (this) {
187  if (deletedAreas == null) {
188  deletedAreas = new List<int>();
189  }
190 
191  deletedAreas.Add((int)pointer);
192  }
193  }
194  }
195 }
readonly IndexSetStore indexSetStore
Definition: IndexBlock.cs:26
long Position
Returns or sets the current position of the pointer within the area.
Definition: IArea.cs:48
static IMappedBlock NewMappedBlock(IndexSetStore indexSetStore, long firstEntry, long lastEntry, long blockPointer, int size, byte compactType, int blockSize)
Definition: StoreIndex.cs:87
IndexBlock(IndexSetStore indexSetStore, int indexNum, int blockSize, long startOffset)
Definition: IndexBlock.cs:34
readonly long blockEntries
Definition: IndexBlock.cs:28
static int URShift(int number, int bits)
Operates a shift on the given integer by the number of bits specified.
Definition: ByteBuffer.cs:277
An interface for querying and accessing an index of primitive integers.
Definition: IIndex.cs:37
A wrapper for an array of byte.
Definition: ByteBuffer.cs:27
IEnumerable< IMappedBlock > CreateMappedBlocks()
Definition: IndexBlock.cs:81
void AddDeletedArea(long pointer)
Definition: IndexBlock.cs:185
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...