//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void setLength(org.neo4j.io.pagecache.PageCursor cursor, long length) throws java.io.IOException
        private void SetLength(PageCursor cursor, long length)
        {
            if (!cursor.Next((length - 1) / EntriesPerPage))
            {
                throw new System.InvalidOperationException(string.Format("Unable to extend the backing file {0} to desired size {1:D}.", PagedFile, length));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Calls <seealso cref="PageCursor.next(long)"/> with the {@code pageId} and throws <seealso cref="System.InvalidOperationException"/>
        /// if that call returns {@code false}.
        /// Purpose of this method is to unify exception handling when moving between pages.
        /// </summary>
        /// <param name="cursor"> <seealso cref="PageCursor"/> to call <seealso cref="PageCursor.next(long)"/> on. </param>
        /// <param name="messageOnError"> additional error message to include in exception if <seealso cref="PageCursor.next(long)"/>
        /// returned {@code false}, providing more context to the exception message. </param>
        /// <param name="pageId"> page id to move to. </param>
        /// <exception cref="IOException"> on <seealso cref="PageCursor.next(long)"/> exception. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: static void goTo(org.neo4j.io.pagecache.PageCursor cursor, String messageOnError, long pageId) throws java.io.IOException
        internal static void GoTo(PageCursor cursor, string messageOnError, long pageId)
        {
            if (!cursor.Next(pageId))
            {
                throw new System.InvalidOperationException("Could not go to page:" + pageId + " [" + messageOnError + "]");
            }
        }
Beispiel #3
0
        /// <summary>
        /// Visit key value pairs that are greater than or equal to the specified key. Visitation will continue as long as
        /// the visitor <seealso cref="KeyValueVisitor.visit(ReadableBuffer, ReadableBuffer) returns true"/>.
        /// </summary>
        /// <returns> {@code true} if an exact match was found, meaning that the first visited key/value pair was a perfect
        /// match for the specified key. </returns>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public boolean scan(SearchKey search, KeyValueVisitor visitor) throws java.io.IOException
        public virtual bool Scan(SearchKey search, KeyValueVisitor visitor)
        {
            BigEndianByteArrayBuffer searchKey = newBuffer(_keySize);
            BigEndianByteArrayBuffer key       = newBuffer(_keySize);
            BigEndianByteArrayBuffer value     = newBuffer(_valueSize);

            search.SearchKeyConflict(searchKey);
            int page = FindPage(searchKey, _pageCatalogue);

            if (page < 0 || (page >= _pageCatalogue.Length / (_keySize * 2)))
            {
                return(false);
            }
            using (PageCursor cursor = _file.io(page, PF_SHARED_READ_LOCK))
            {
                if (!cursor.Next())
                {
                    return(false);
                }
                // finds and reads the first key/value pair
                int offset = FindByteOffset(cursor, searchKey, key, value);
                try
                {
                    return(Arrays.Equals(searchKey.Buffer, key.Buffer));
                }
                finally
                {
                    VisitKeyValuePairs(_file.pageSize(), cursor, offset, visitor, false, key, value);
                }
            }
        }
Beispiel #4
0
 public DataProviderAnonymousInnerClass(KeyValueStoreFile outerInstance, PageCursor cursor)
 {
     this.outerInstance = outerInstance;
     this._cursor       = cursor;
     offset             = outerInstance.headerEntries * (outerInstance.keySize + outerInstance.valueSize);
     done = !cursor.Next();
 }
Beispiel #5
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public void read(RECORD record, org.neo4j.io.pagecache.PageCursor primaryCursor, org.neo4j.kernel.impl.store.record.RecordLoad mode, int recordSize) throws java.io.IOException
        public override void Read(RECORD record, PageCursor primaryCursor, RecordLoad mode, int recordSize)
        {
            int   primaryStartOffset = primaryCursor.Offset;
            sbyte headerByte         = primaryCursor.Byte;
            bool  inUse            = isInUse(headerByte);
            bool  doubleRecordUnit = has(headerByte, HeaderBitRecordUnit);

            record.UseFixedReferences = false;
            if (doubleRecordUnit)
            {
                bool firstRecordUnit = has(headerByte, HeaderBitFirstRecordUnit);
                if (!firstRecordUnit)
                {
                    // This is a record unit and not even the first one, so you cannot go here directly and read it,
                    // it may only be read as part of reading the primary unit.
                    record.clear();
                    // Return and try again
                    primaryCursor.CursorException = "Expected record to be the first unit in the chain, but record header says it's not";
                    return;
                }

                // This is a record that is split into multiple record units. We need a bit more clever
                // data structures here. For the time being this means instantiating one object,
                // but the trade-off is a great reduction in complexity.
                long       secondaryId     = Reference.decode(primaryCursor);
                long       pageId          = pageIdForRecord(secondaryId, primaryCursor.CurrentPageSize, recordSize);
                int        offset          = offsetForId(secondaryId, primaryCursor.CurrentPageSize, recordSize);
                PageCursor secondaryCursor = primaryCursor.OpenLinkedCursor(pageId);
                if ((!secondaryCursor.Next()) | offset < 0)
                {
                    // We must have made an inconsistent read of the secondary record unit reference.
                    // No point in trying to read this.
                    record.clear();
                    primaryCursor.CursorException = IllegalSecondaryReferenceMessage(pageId);
                    return;
                }
                secondaryCursor.Offset = offset + HeaderByte;
                int primarySize = recordSize - (primaryCursor.Offset - primaryStartOffset);
                // We *could* sanity check the secondary record header byte here, but we won't. If it is wrong, then we most
                // likely did an inconsistent read, in which case we'll just retry. Otherwise, if the header byte is wrong,
                // then there is little we can do about it here, since we are not allowed to throw exceptions.

                int        secondarySize = recordSize - HeaderByte;
                PageCursor composite     = CompositePageCursor.compose(primaryCursor, primarySize, secondaryCursor, secondarySize);
                DoReadInternal(record, composite, recordSize, headerByte, inUse);
                record.SecondaryUnitId = secondaryId;
            }
            else
            {
                record.UseFixedReferences = IsUseFixedReferences(headerByte);
                DoReadInternal(record, primaryCursor, recordSize, headerByte, inUse);
            }

            // Set cursor offset to next record to prepare next read in case of scanning.
            primaryCursor.Offset = primaryStartOffset + recordSize;
        }
Beispiel #6
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public void write(RECORD record, org.neo4j.io.pagecache.PageCursor primaryCursor, int recordSize) throws java.io.IOException
        public override void Write(RECORD record, PageCursor primaryCursor, int recordSize)
        {
            if (record.inUse())
            {
                // Let the specific implementation provide the additional header bits and we'll provide the core format bits.
                sbyte headerByte = HeaderBits(record);
                assert(headerByte & 0x7) == 0 : "Format-specific header bits (" + headerByte +
                ") collides with format-generic header bits";
                headerByte = set(headerByte, IN_USE_BIT, record.inUse());
                headerByte = set(headerByte, HeaderBitRecordUnit, record.requiresSecondaryUnit());
                if (record.requiresSecondaryUnit())
                {
                    headerByte = set(headerByte, HeaderBitFirstRecordUnit, true);
                }
                else
                {
                    headerByte = set(headerByte, HeaderBitFixedReference, !record.UseFixedReferences);
                }
                primaryCursor.PutByte(headerByte);

                if (record.requiresSecondaryUnit())
                {
                    // Write using the normal adapter since the first reference we write cannot really overflow
                    // into the secondary record
                    long       secondaryUnitId = record.SecondaryUnitId;
                    long       pageId          = pageIdForRecord(secondaryUnitId, primaryCursor.CurrentPageSize, recordSize);
                    int        offset          = offsetForId(secondaryUnitId, primaryCursor.CurrentPageSize, recordSize);
                    PageCursor secondaryCursor = primaryCursor.OpenLinkedCursor(pageId);
                    if (!secondaryCursor.Next())
                    {
                        // We are not allowed to write this much data to the file, apparently.
                        record.clear();
                        return;
                    }
                    secondaryCursor.Offset = offset;
                    secondaryCursor.PutByte(( sbyte )(IN_USE_BIT | HeaderBitRecordUnit));
                    int        recordSizeWithoutHeader = recordSize - HeaderByte;
                    PageCursor composite = CompositePageCursor.compose(primaryCursor, recordSizeWithoutHeader, secondaryCursor, recordSizeWithoutHeader);

                    Reference.encode(secondaryUnitId, composite);
                    DoWriteInternal(record, composite);
                }
                else
                {
                    DoWriteInternal(record, primaryCursor);
                }
            }
            else
            {
                MarkAsUnused(primaryCursor, record, recordSize);
            }
        }
Beispiel #7
0
//JAVA TO C# CONVERTER TODO TASK: There is no .NET equivalent to the Java 'super' constraint:
//ORIGINAL LINE: static <Buffer extends BigEndianByteArrayBuffer> void scanAll(org.neo4j.io.pagecache.PagedFile file, int startOffset, EntryVisitor<? super Buffer> visitor, Buffer key, Buffer value) throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        internal static void ScanAll <Buffer, T1>(PagedFile file, int startOffset, EntryVisitor <T1> visitor, Buffer key, Buffer value) where Buffer : BigEndianByteArrayBuffer
        {
            bool visitHeaders = !(visitor is KeyValueVisitor);

            using (PageCursor cursor = file.Io(startOffset / file.PageSize(), PF_SHARED_READ_LOCK))
            {
                if (!cursor.Next())
                {
                    return;
                }
                ReadKeyValuePair(cursor, startOffset, key, value);
                VisitKeyValuePairs(file.PageSize(), cursor, startOffset, visitor, visitHeaders, key, value);
            }
        }
Beispiel #8
0
        /*
         * Use this instead of {@link #markFirstByteAsUnused(PageCursor)} to mark both record units,
         * if record has a reference to a secondary unit.
         */
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: protected void markAsUnused(org.neo4j.io.pagecache.PageCursor cursor, RECORD record, int recordSize) throws java.io.IOException
        protected internal virtual void MarkAsUnused(PageCursor cursor, RECORD record, int recordSize)
        {
            markAsUnused(cursor);
            if (record.hasSecondaryUnitId())
            {
                long secondaryUnitId          = record.SecondaryUnitId;
                long pageIdForSecondaryRecord = pageIdForRecord(secondaryUnitId, cursor.CurrentPageSize, recordSize);
                int  offsetForSecondaryId     = offsetForId(secondaryUnitId, cursor.CurrentPageSize, recordSize);
                if (!cursor.Next(pageIdForSecondaryRecord))
                {
                    throw new UnderlyingStorageException("Couldn't move to secondary page " + pageIdForSecondaryRecord);
                }
                cursor.Offset = offsetForSecondaryId;
                markAsUnused(cursor);
            }
        }
Beispiel #9
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private long acquireNewIdFromFreelistOrEnd(long stableGeneration, long unstableGeneration, boolean allowTakeLastFromPage) throws java.io.IOException
        private long AcquireNewIdFromFreelistOrEnd(long stableGeneration, long unstableGeneration, bool allowTakeLastFromPage)
        {
            if ((_readPageId != _writePageId || _readPos < _writePos) && (allowTakeLastFromPage || _readPos < _freelistNode.maxEntries() - 1))
            {
                // It looks like reader isn't even caught up to the writer page-wise,
                // or the read pos is < write pos so check if we can grab the next id (generation could still mismatch).
                using (PageCursor cursor = _pagedFile.io(_readPageId, Org.Neo4j.Io.pagecache.PagedFile_Fields.PF_SHARED_READ_LOCK))
                {
                    if (!cursor.Next())
                    {
                        throw new IOException("Couldn't go to free-list read page " + _readPageId);
                    }

                    long resultPageId;
                    do
                    {
                        resultPageId = _freelistNode.read(cursor, stableGeneration, _readPos);
                    } while (cursor.ShouldRetry());

                    if (resultPageId != FreelistNode.NoPageId)
                    {
                        // FreelistNode compares generation and so this means that we have an available
                        // id in the free list which we can acquire from a stable generation. Increment readPos
                        _readPos++;
                        if (_readPos >= _freelistNode.maxEntries())
                        {
                            // The current reader page is exhausted, go to the next free-list page.
                            _readPos = 0;
                            do
                            {
                                _readPageId = FreelistNode.Next(cursor);
                            } while (cursor.ShouldRetry());

                            // Put the exhausted free-list page id itself on the free-list
                            long exhaustedFreelistPageId = cursor.CurrentPageId;
                            ReleaseId(stableGeneration, unstableGeneration, exhaustedFreelistPageId);
                            _monitor.releasedFreelistPageId(exhaustedFreelistPageId);
                        }
                        return(resultPageId);
                    }
                }
            }

            // Fall-back to acquiring at the end of the file
            return(NextLastId());
        }
Beispiel #10
0
        /// <summary>
        /// Expects the first key/value-pair to be read into the buffers already, reads subsequent pairs (if requested). </summary>
//JAVA TO C# CONVERTER TODO TASK: There is no .NET equivalent to the Java 'super' constraint:
//ORIGINAL LINE: private static <Buffer extends BigEndianByteArrayBuffer> void visitKeyValuePairs(int pageSize, org.neo4j.io.pagecache.PageCursor cursor, int offset, EntryVisitor<? super Buffer> visitor, boolean visitHeaders, Buffer key, Buffer value) throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        private static void VisitKeyValuePairs <Buffer, T1>(int pageSize, PageCursor cursor, int offset, EntryVisitor <T1> visitor, bool visitHeaders, Buffer key, Buffer value) where Buffer : BigEndianByteArrayBuffer
        {
            while (Visitable(key, visitHeaders) && visitor.Visit(key, value))
            {
                offset += key.Size() + value.Size();
                if (offset >= pageSize)
                {
                    offset = 0;
                    if (!cursor.Next())
                    {
                        return;
                    }
                }
                // reads the next key/value pair
                ReadKeyValuePair(cursor, offset, key, value);
            }
        }
Beispiel #11
0
        public override void Set(long index, long value)
        {
            long pageId = pageId(index);
            int  offset = offset(index);

            try
            {
                using (PageCursor cursor = PagedFile.io(pageId, PF_SHARED_WRITE_LOCK | PF_NO_GROW))
                {
                    cursor.Next();
                    cursor.PutLong(offset, value);
                    CheckBounds(cursor);
                }
            }
            catch (IOException e)
            {
                throw new UncheckedIOException(e);
            }
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void mustAutomaticallyStartEvictionThread() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void MustAutomaticallyStartEvictionThread()
        {
            using (FileSystemAbstraction fs = new DefaultFileSystemAbstraction(), JobScheduler jobScheduler = new ThreadPoolJobScheduler())
            {
                File file = (new File(TestDirectory.directory(), "a")).CanonicalFile;
                fs.Create(file).close();

                using (PageCache cache = ConfigurableStandalonePageCacheFactory.CreatePageCache(fs, jobScheduler), PagedFile pf = cache.Map(file, 4096), PageCursor cursor = pf.Io(0, Org.Neo4j.Io.pagecache.PagedFile_Fields.PfSharedWriteLock))
                {
                    // The default size is currently 8MBs.
                    // It should be possible to write more than that.
                    // If the eviction thread has not been started, then this test will block forever.
                    for (int i = 0; i < 10_000; i++)
                    {
                        assertTrue(cursor.Next());
                        cursor.PutInt(42);
                    }
                }
            }
        }
Beispiel #13
0
        public override long Get(long index)
        {
            long pageId = pageId(index);
            int  offset = offset(index);

            try
            {
                using (PageCursor cursor = PagedFile.io(pageId, PF_SHARED_READ_LOCK))
                {
                    cursor.Next();
                    long result;
                    do
                    {
                        result = cursor.GetLong(offset);
                    } while (cursor.ShouldRetry());
                    CheckBounds(cursor);
                    return(result);
                }
            }
            catch (IOException e)
            {
                throw new UncheckedIOException(e);
            }
        }