예제 #1
0
파일: Node.cs 프로젝트: furesoft/SharpHSQL
        private int iId; // id of index this table

        #endregion Fields

        #region Constructors

        public Node(Row r, BinaryReader din, int id)
        {
            iId = id;
            rData = r;
            iBalance = din.ReadInt32();
            iLeft = din.ReadInt32();
            iRight = din.ReadInt32();
            iParent = din.ReadInt32();

            if (TracingHelper.AssertEnabled)
            {
                TracingHelper.Assert(iBalance != -2);
            }
        }
예제 #2
0
파일: Row.cs 프로젝트: furesoft/SharpHSQL
 public void Insert(Row before)
 {
     if (before == null)
     {
         Next = this;
         Last = this;
     }
     else
     {
         Next = before;
         Last = before.Last;
         before.Last = this;
         Last.Next = this;
     }
 }
예제 #3
0
파일: Row.cs 프로젝트: furesoft/SharpHSQL
        public void Free()
        {
            Last.Next = Next;
            Next.Last = Last;

            if (Next == this)
            {
                Next = Last = null;
            }
        }
예제 #4
0
파일: Row.cs 프로젝트: furesoft/SharpHSQL
        internal Row(Table t, BinaryReader din, int pos, Row before)
        {
            tTable = t;

            int index = tTable.IndexCount;

            Pos = pos;
            nFirstIndex = new Node(this, din, 0);

            Node n = nFirstIndex;

            for (int i = 1; i < index; i++)
            {
                n.nNext = new Node(this, din, i);
                n = n.nNext;
            }

            int l = tTable.InternalColumnCount;

            oData = Column.ReadData(din, l);

            int iCurrent = din.ReadInt32();

            LogHelper.Publish( String.Format("Row read with {0} columns. Row read position from file: {1}. Current position: {2}.", oData.Length, iCurrent, Pos ), LogEntryType.Debug );

            TracingHelper.Check(iCurrent == Pos, TracingHelper.INPUTSTREAM_ERROR);
            Insert(before);

            LastAccess = CurrentAccess++;
        }
예제 #5
0
파일: Cache.cs 프로젝트: furesoft/SharpHSQL
        /// <summary>
        /// Remove method declaration.
        /// This method is used to remove Rows from the Cache. It is called
        /// by the CleanUp method.
        /// </summary>
        /// <param name="row">Row to be removed</param>
        private void Remove(Row row)
        {
            if (TracingHelper.AssertEnabled)
                TracingHelper.Assert(!row.Changed);

            // make sure _rowLastChecked does not point to r
            if (row == _rowLastChecked)
            {
                _rowLastChecked = _rowLastChecked.Next;

                if (_rowLastChecked == row)
                    _rowLastChecked = null;
            }

            // make sure _rowData[k] does not point here
            int k = row.Pos & MASK;

            if (_rowData[k] == row)
            {
                Row n = row.Next;

                _rowFirst = n;

                if (n == row || (n.Pos & MASK) != k)
                    n = null;

                _rowData[k] = n;
            }

            // make sure _rowFirst does not point here
            if (row == _rowFirst)
            {
                _rowFirst = _rowFirst.Next;

                if (row == _rowFirst)
                    _rowFirst = null;
            }

            row.Free();

            _cacheSize--;
        }
예제 #6
0
파일: Cache.cs 프로젝트: furesoft/SharpHSQL
        /// <summary>
        /// GetWorst method declaration.
        /// This method finds the Row with the smallest (oldest) iLastAccess member.
        /// Called by the Cleanup method.
        /// </summary>
        /// <returns>The selected Row object</returns>
        private Row GetWorst()
        {
            if (_rowLastChecked == null)
                _rowLastChecked = _rowFirst;

            Row r = _rowLastChecked;

            if (r == null)
                return null;

            Row candidate = r;
            int worst = Row.CurrentAccess;

            // algorithm: check the next rows and take the worst
            for (int i = 0; i < 6; i++)
            {
                int w = r.LastAccess;

                if (w < worst)
                {
                    candidate = r;
                    worst = w;
                }

                r = r.Next;
            }

            _rowLastChecked = r.Next;

            return candidate;
        }
예제 #7
0
파일: Cache.cs 프로젝트: furesoft/SharpHSQL
        /// <summary>
        /// </summary>
        private static void Swap(Row[] w, int a, int b)
        {
            Row t = w[a];

            w[a] = w[b];
            w[b] = t;
        }
예제 #8
0
파일: Cache.cs 프로젝트: furesoft/SharpHSQL
        /// <summary>
        /// </summary>
        private static void Sort(Row[] w, int l, int r)
        {
            int i, j, p;

            while (r - l > 10)
            {
                i = (r + l) >> 1;

                if (w[l].Pos > w[r].Pos)
                {
                    Swap(w, l, r);
                }

                if (w[i].Pos < w[l].Pos)
                {
                    Swap(w, l, i);
                }
                else if (w[i].Pos > w[r].Pos)
                {
                    Swap(w, i, r);
                }

                j = r - 1;

                Swap(w, i, j);

                p = w[j].Pos;
                i = l;

                while (true)
                {
                    if (TracingHelper.StopEnabled)
                        TracingHelper.Stop();

                    while (w[++i].Pos < p);

                    while (w[--j].Pos > p);

                    if (i >= j)
                        break;

                    Swap(w, i, j);
                }

                Swap(w, i, r - 1);
                Sort(w, l, i - 1);

                l = i + 1;
            }

            for (i = l + 1; i <= r; i++)
            {
                if (TracingHelper.StopEnabled)
                    TracingHelper.Stop();

                Row t = w[i];

                for (j = i - 1; j >= l && w[j].Pos > t.Pos; j--)
                {
                    w[j + 1] = w[j];
                }

                w[j + 1] = t;
            }
        }
예제 #9
0
파일: Cache.cs 프로젝트: furesoft/SharpHSQL
        /// <summary>
        /// GetRow method declaration.
        /// This method reads a Row object from the cache.
        /// </summary>
        /// <param name="pos">Offset of the requested Row in the cache</param>
        /// <param name="table">Table this Row belongs to</param>
        /// <returns>The Row object as read from the cache.</returns>
        public Row GetRow(int pos, Table table)
        {
            int k = pos & MASK;
            Row r = _rowData[k];
            Row start = r;

            while (r != null)
            {
                if (TracingHelper.StopEnabled)
                    TracingHelper.Stop();

                int p = r.Pos;

                if (p == pos)
                    return r;
                else if ((p & MASK) != k)
                    break;

                r = r.Next;

                if (r == start)
                    break;
            }

            Row before = _rowData[k];

            if (before == null)
            {
                before = _rowFirst;
            }

            try
            {
                LogHelper.Publish( String.Format("Retrieving row at position: {0}.", pos ), LogEntryType.Debug );

                _fileStream.Seek(pos, SeekOrigin.Begin);

                BinaryReader b = new BinaryReader(_fileStream);

                int  size = b.ReadInt32();
                byte[] buffer = new byte[size];

                buffer = b.ReadBytes(size);

                LogHelper.Publish( String.Format("Row Size: {0}. Retrieved {1} bytes.", size, buffer.Length ), LogEntryType.Debug );

                MemoryStream bin = new MemoryStream(buffer);
                BinaryReader din = new BinaryReader(bin, System.Text.Encoding.Unicode);

                r = new Row(table, din, pos, before);
                r.Size = size;
            }
            catch (IOException e)
            {
                #if !POCKETPC
                Console.WriteLine(e.StackTrace);
                #endif

                throw TracingHelper.Error(TracingHelper.FILE_IO_ERROR, "reading: " + e);
            }

            _cacheSize++;
            _rowData[k] = r;
            _rowFirst = r;

            return r;
        }
예제 #10
0
파일: Cache.cs 프로젝트: furesoft/SharpHSQL
        /// <summary>
        /// Free method declaration.
        /// This method marks space in the database file as free.
        /// </summary>
        /// <remarks>
        /// If more than MAX_FREE_COUNT free positios then
        /// they are probably all are too small anyway; so we start a new list.
        /// TODO: This is wrong when deleting lots of records.
        /// </remarks>
        /// 
        /// <param name="row">Row object to be marked free</param>
        /// <param name="pos">Offset in the file this Row was stored at</param>
        /// <param name="length">Size of the Row object to free</param>
        public void Free(Row row, int pos, int length)
        {
            _freeCount++;

            CacheFree n = new CacheFree();

            n.Pos = pos;
            n.Length = length;

            if (_freeCount > MAX_FREE_COUNT)
                _freeCount = 0;
            else
                n.Next = _cacheRoot;

            _cacheRoot = n;

            // it's possible to remove roots to
            Remove(row);
        }
예제 #11
0
파일: Cache.cs 프로젝트: furesoft/SharpHSQL
        /// <summary>
        /// Add method declaration.
        /// This method adds a Row to the Cache.  It walks the
        /// list of CacheFree objects to see if there is available space
        /// to store the new Row, reusing space if it exists, otherwise
        /// we grow the file.
        /// </summary>
        /// <param name="row">Row to be added to Cache</param>
        public void Add(Row row)
        {
            int       size = row.Size;
            CacheFree f = _cacheRoot;
            CacheFree last = null;
            int       i = _freePos;

            while (f != null)
            {
                if (TracingHelper.TraceEnabled)
                {
                    TracingHelper.Stop();
                }
                // first that is long enough
                if (f.Length >= size)
                {
                    i = f.Pos;
                    size = f.Length - size;

                    if (size < 8)
                    {
                        // remove almost empty blocks
                        if (last == null)
                        {
                            _cacheRoot = f.Next;
                        }
                        else
                        {
                            last.Next = f.Next;
                        }

                        _freeCount--;
                    }
                    else
                    {
                        f.Length = size;
                        f.Pos += row.Size;
                    }

                    break;
                }

                last = f;
                f = f.Next;
            }

            row.Pos = i;

            if (i == _freePos)
            {
                _freePos += size;
            }

            int k = i & MASK;
            Row before = _rowData[k];

            if (before == null)
            {
                before = _rowFirst;
            }

            row.Insert(before);

            _cacheSize++;
            _rowData[k] = row;
            _rowFirst = row;
        }
예제 #12
0
파일: Node.cs 프로젝트: furesoft/SharpHSQL
 public Node(Row r, int id)
 {
     iId = id;
     rData = r;
 }
예제 #13
0
파일: Table.cs 프로젝트: furesoft/SharpHSQL
        public void InsertNoCheck(object[] row, Channel c, bool log)
        {
            int i;

            if (iIdentityColumn != -1)
            {
                if (row[iIdentityColumn] == null)
                {
                    if (c != null)
                    {
                        c.LastIdentity = iIdentityId;
                    }

                    row[iIdentityColumn] = iIdentityId++;
                }
                else
                {
                    i = (int) row[iIdentityColumn];

                    if (iIdentityId <= i)
                    {
                        if (c != null)
                        {
                            c.LastIdentity = i;
                        }

                        iIdentityId = i + 1;
                    }
                }
            }

            if (iTimestampColumn != -1)
            {
                if (row[iTimestampColumn] == null)
                {
                    row[iTimestampColumn] = DateTime.Now;
                }
                else
                {
                    DateTime timestamp = DateTime.Now;
                    DateTime original = (DateTime) row[iTimestampColumn];

                    // just in case to assure our timestamp is unique
                    if ( timestamp == original )
                    {
                        row[iTimestampColumn] = timestamp.AddMilliseconds(1);
                    }
                    else
                    {
                        row[iTimestampColumn] = timestamp;
                    }
                }
            }

            for (i = 0; i < iColumnCount; i++)
            {
                if (row[i] == null &&!GetColumn(i).IsNullable)
                {
                    throw TracingHelper.Error(TracingHelper.TRY_TO_INSERT_NULL);
                }
            }

            try
            {
                Row r = new Row(this, row);

                for (i = 0; i < iIndexCount; i++)
                {
                    Node n = r.GetNode(i);

                    GetIndex(i).Insert(n);
                }
            }
            catch (Exception e)
            {    // rollback insert
                for (--i; i >= 0; i--)
                {
                    GetIndex(i).Delete(row, i == 0);
                }

                throw e;		      // and throw error again
            }

            if (c != null)
            {
                c.AddTransactionInsert(this, row);
            }

            if (lLog != null)
            {
                lLog.Write(c, GetInsertStatement(row));
            }
        }