/// <summary>Allocate a new page for a specific bucket</summary>
        /// <param name="bucket">Bucet index</param>
        protected TPage CreateNewPage(int bucket)
        {
            uint size = m_buckets[bucket].PageSize;

            UnmanagedHelpers.SafeLocalAllocHandle handle = null;
            try
            {
                handle = UnmanagedHelpers.AllocMemory(size);
                return(m_allocator(handle, size));
            }
            catch (Exception e)
            {
                if (handle != null)
                {
                    if (!handle.IsClosed)
                    {
                        handle.Dispose();
                    }
                    handle = null;
                }
                if (e is OutOfMemoryException)
                {
                    throw new OutOfMemoryException(String.Format("Failed to allocate new memory for new page of size {0}", size), e);
                }
                throw;
            }
            finally
            {
                if (handle != null)
                {
                    GC.AddMemoryPressure(size);
                }
            }
        }
        private unsafe USlice Store(Slice data)
        {
            uint size   = checked ((uint)data.Count);
            var  buffer = m_keys.AllocateAligned(size);

            UnmanagedHelpers.CopyUnsafe(buffer, data);
            return(new USlice(buffer, size));
        }
예제 #3
0
        private IEnumerable <Window> GetTrayWindows()
        {
            var trayWindows = UnmanagedHelpers.FilterWindows((hWnd) =>
            {
                var window       = new Window(hWnd);
                var isTrayWindow = window.ClassName == "Shell_TrayWnd" || window.ClassName == "Shell_SecondaryTrayWnd";
                return(isTrayWindow && Screen.FromHandle(hWnd).Bounds == _screen.Bounds);
            });

            return(trayWindows.Select(hWnd => new Window(hWnd)));
        }
            /// <summary>Copy an existing value to this page, and return the pointer to the copy</summary>
            /// <param name="value">Value that must be copied to this page</param>
            /// <returns>Pointer to the copy in this page</returns>
            public Value *TryAppend(Value *value)
            {
                Contract.Requires(value != null && Entry.GetObjectType(value) == EntryType.Value);

                uint   rawSize = Value.SizeOf + value->Size;
                Value *entry   = (Value *)TryAllocate(rawSize);

                if (entry == null)
                {
                    return(null);                               // the page is full
                }
                UnmanagedHelpers.CopyUnsafe((byte *)entry, (byte *)value, rawSize);

                return(entry);
            }
            public Value *TryAppend(USlice buffer)
            {
                Contract.Requires(buffer.Data != null &&
                                  buffer.Count >= Value.SizeOf &&
                                  ((Key *)buffer.Data)->Size == buffer.Count - Value.SizeOf);

                var entry = (Value *)TryAllocate(buffer.Count);

                if (entry == null)
                {
                    return(null);                               // the page is full
                }
                UnmanagedHelpers.CopyUnsafe((byte *)entry, buffer.Data, buffer.Count);

                return(entry);
            }
예제 #6
0
            public Key *TryAppend(USlice buffer)
            {
                Contract.Requires(buffer.Data != null &&
                                  buffer.Count >= Key.SizeOf &&
                                  ((Key *)buffer.Data)->Size == buffer.Count - Key.SizeOf);

                var entry = (Key *)TryAllocate(buffer.Count);

                if (entry == null)
                {
                    return(null);                               // this page is full
                }
                UnmanagedHelpers.CopyUnsafe((byte *)entry, buffer.Data, buffer.Count);
                entry->Header = ((ushort)EntryType.Key) << Entry.TYPE_SHIFT;

                return(entry);
            }
예제 #7
0
        public unsafe void Add(ulong sequence, USlice userKey, USlice userValue)
        {
            // allocate the key
            var  tmp = MemoryDatabaseHandler.PackUserKey(m_scratch, userKey);
            Key *key = m_keys.Append(tmp);

            Contract.Assert(key != null, "key == null");

            // allocate the value
            uint   size  = userValue.Count;
            Value *value = m_values.Allocate(size, sequence, null, key);

            Contract.Assert(value != null, "value == null");
            UnmanagedHelpers.CopyUnsafe(&(value->Data), userValue);

            key->Values = value;

            m_list.Add(new IntPtr(key));
        }
        public void ReadHeader(CancellationToken ct)
        {
            ct.ThrowIfCancellationRequested();

            // minimum header prolog size is 64 but most will only a single page
            // we can preallocate a full page, and we will resize it later if needed

            var reader = m_file.CreateReader(0, SnapshotFormat.HEADER_METADATA_BYTES);

            // "PNDB"
            var signature = reader.ReadFixed32();
            // v1.0
            uint major = reader.ReadFixed16();
            uint minor = reader.ReadFixed16();

            m_version = new Version((int)major, (int)minor);
            // FLAGS
            m_dbFlags = (SnapshotFormat.Flags)reader.ReadFixed64();
            // Database ID
            m_uid = new Uuid128(reader.ReadBytes(16).GetBytes());
            // Database Version
            m_sequence = reader.ReadFixed64();
            // Number of items in the database
            m_itemCount = checked ((long)reader.ReadFixed64());
            // Database Timestamp
            m_timestamp = reader.ReadFixed64();
            // Page Size
            m_pageSize = reader.ReadFixed32();
            // Header Size
            m_headerSize = reader.ReadFixed32();

            Contract.Assert(!reader.HasMore);

            #region Sanity checks

            // Signature
            if (signature != SnapshotFormat.HEADER_MAGIC_NUMBER)
            {
                throw ParseError("Invalid magic number");
            }

            // Version
            if (m_version.Major != 1)
            {
                throw ParseError("Unsupported file version (major)");
            }
            if (m_version.Minor > 0)
            {
                throw ParseError("Unsupported file version (minor)");
            }

            // Flags

            // Page Size
            if (m_pageSize != UnmanagedHelpers.NextPowerOfTwo(m_pageSize))
            {
                throw ParseError("Page size ({0}) is not a power of two", m_pageSize);
            }
            if (m_pageSize < SnapshotFormat.HEADER_METADATA_BYTES)
            {
                throw ParseError("Page size ({0}) is too small", m_pageSize);
            }
            if (m_pageSize > 1 << 20)
            {
                throw ParseError("Page size ({0}) is too big", m_pageSize);
            }

            // Header Size
            if (m_headerSize < 64 + 4 + 4)
            {
                throw ParseError("Header size ({0}) is too small", m_headerSize);
            }
            if (m_headerSize > m_file.Length)
            {
                throw ParseError("Header size is bigger than the file itself ({0} < {1})", m_headerSize, m_file.Length);
            }
            if (m_headerSize > 1 << 10)
            {
                throw ParseError("Header size ({0}) exceeds the maximum allowed size", m_headerSize);
            }

            #endregion

            // we know the page size and header size, read the rest...

            // read the rest
            reader = m_file.CreateReader(0, m_headerSize);
            reader.Skip(SnapshotFormat.HEADER_METADATA_BYTES);

            // parse the attributes
            Contract.Assert(reader.Offset == SnapshotFormat.HEADER_METADATA_BYTES);
            var attributeCount = checked ((int)reader.ReadFixed32());
            if (attributeCount < 0 || attributeCount > 1024)
            {
                throw ParseError("Attributes count is invalid");
            }

            var attributes = new Dictionary <string, IFdbTuple>(attributeCount);
            for (int i = 0; i < attributeCount; i++)
            {
                var name = reader.ReadVarbytes().ToSlice();                 //TODO: max size ?
                if (name.IsNullOrEmpty)
                {
                    throw ParseError("Header attribute name is empty");
                }

                var data  = reader.ReadVarbytes().ToSlice();                    //TODO: max size + have a small scratch pad buffer for these ?
                var value = FdbTuple.Unpack(data);
                attributes.Add(name.ToUnicode(), value);
            }
            m_attributes = attributes;

            // read the header en marker
            var marker = reader.ReadFixed32();
            if (marker != uint.MaxValue)
            {
                throw ParseError("Header end marker is invalid");
            }

            // verify the header checksum
            uint actualHeaderChecksum = SnapshotFormat.ComputeChecksum(reader.Base, reader.Offset);
            uint headerChecksum       = reader.ReadFixed32();
            m_headerChecksum = headerChecksum;

            if (headerChecksum != actualHeaderChecksum)
            {
                throw ParseError("The header checksum does not match ({0} != {1}). This may be an indication of data corruption", headerChecksum, actualHeaderChecksum);
            }

            m_dataStart = RoundUp(m_headerSize, m_pageSize);
            m_hasHeader = true;
        }
예제 #9
0
        private static IEnumerable <Window> GetTaskbarWindows()
        {
            var trayWindows = UnmanagedHelpers.FilterWindows(IsAltTabWindow);

            return(trayWindows.Select(hWnd => new Window(hWnd)));
        }