-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
PagedFile.java
162 lines (154 loc) · 6.8 KB
/
PagedFile.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.io.pagecache;
import java.io.IOException;
/**
* The representation of a file that has been mapped into the associated page cache.
*/
public interface PagedFile extends AutoCloseable
{
/**
* Pin the pages with a shared lock.
* <p>
* This implies {@link org.neo4j.io.pagecache.PagedFile#PF_NO_GROW}, since
* pages under read locks cannot be safely written to anyway, so there's
* no point in trying to go beyond the end of the file.
* <p>
* This cannot be combined with {@link #PF_SHARED_WRITE_LOCK}.
*/
int PF_SHARED_READ_LOCK = 1;
/**
* Pin the pages with a shared write lock.
* <p>
* This will mark the pages as dirty, and caused them to be flushed, if they are evicted.
* <p>
* Note that write locks are <em>not</em> exclusive. You must use other means to coordinate access to the data on
* the pages. The write lock only means that the page will not be concurrently evicted.
* <p>
* This cannot be combined with {@link #PF_SHARED_READ_LOCK}.
*/
int PF_SHARED_WRITE_LOCK = 1 << 1;
/**
* Disallow pinning and navigating to pages outside the range of the
* underlying file.
*/
int PF_NO_GROW = 1 << 2;
/**
* Read-ahead hint for sequential forward scanning.
*/
int PF_READ_AHEAD = 1 << 3; // TBD
/**
* Do not load in the page if it is not loaded already. Only useful with
* exclusive locking when you want to overwrite the whole page anyway.
*/
int PF_NO_FAULT = 1 << 4; // TBD
/**
* Do not update page access statistics.
*/
int PF_TRANSIENT = 1 << 5; // TBD
/**
* Initiate an IO interaction with the contents of the paged file.
* <p>
* The basic structure of an interaction looks like this:
* <pre><code>
* try ( PageCursor cursor = pagedFile.io( startingPageId, intentFlags ) )
* {
* if ( cursor.next() )
* {
* do
* {
* // perform read or write operations on the page
* }
* while ( cursor.shouldRetry() );
* }
* }
* </code></pre>
* {@link org.neo4j.io.pagecache.PageCursor PageCursors} are {@link AutoCloseable}, so interacting with them
* using <em>try-with-resources</em> is recommended.
* <p>
* The returned PageCursor is initially not bound, so {@link PageCursor#next() next} must be called on it before it
* can be used.
* <p>
* The first {@code next} call will advance the cursor to the initial page, as given by the {@code pageId}
* parameter. Until then, the cursor won't be bound to any page, the {@link PageCursor#getCurrentPageId()} method
* will return the {@link org.neo4j.io.pagecache.PageCursor#UNBOUND_PAGE_ID} constant, and attempts at reading from
* or writing to the cursor will throw a {@link NullPointerException}.
* <p>
* After the {@code next} call, if it returns {@code true}, the cursor will be bound to a page, and the get and put
* methods will access that page.
* <p>
* After a call to {@link PageCursor#rewind()}, the cursor will return to its initial state.
* <p>
* The {@code pf_flags} argument expresses the intent of the IO operation. It is a bitmap that combines various
* {@code PF_*} constants. You must always specify your desired locking behaviour, with either
* {@link org.neo4j.io.pagecache.PagedFile#PF_SHARED_WRITE_LOCK} or
* {@link org.neo4j.io.pagecache.PagedFile#PF_SHARED_READ_LOCK}.
* <p>
* The two locking modes cannot be combined, but other intents can be combined with them. For instance, if you want
* to write to a page, but also make sure that you don't write beyond the end of the file, then you can express your
* intent with {@code PF_SHARED_WRITE_LOCK | PF_NO_GROW} – note how the flags are combined with a bitwise-OR operator.
* Arithmetic addition can also be used, but might not make it as clear that we are dealing with a bit-set.
*
* @param pageId The initial file-page-id, that the cursor will be bound to
* after the first call to <code>next</code>.
* @param pf_flags A bitmap of <code>PF_*</code> constants composed with
* the bitwise-OR operator, that expresses the desired
* locking behaviour, and other hints.
* @return A PageCursor in its initial unbound state.
* Never <code>null</code>.
* @throws IOException if there was an error accessing the underlying file.
*/
PageCursor io( long pageId, int pf_flags ) throws IOException;
/**
* Get the size of the file-pages, in bytes.
*/
int pageSize();
/**
* Flush all dirty pages into the file channel, and force the file channel to disk.
*/
void flushAndForce() throws IOException;
/**
* Flush all dirty pages into the file channel, and force the file channel to disk, but limit the rate of IO as
* advised by the given IOPSLimiter.
* @param limiter The {@link IOLimiter} that determines if pauses or sleeps should be injected into the flushing
* process to keep the IO rate down.
*/
void flushAndForce( IOLimiter limiter ) throws IOException;
/**
* Get the file-page-id of the last page in the file.
* <p>
* This will return <em>a negative number</em> (not necessarily -1) if the file is completely empty.
*
* @throws IllegalStateException if this file has been unmapped
*/
long getLastPageId() throws IOException;
/**
* Release a handle to a paged file.
* <p>
* If this is the last handle to the file, it will be flushed and closed.
* <p>
* Note that this operation assumes that there are no write page cursors open on the paged file. If there are, then
* their writes may be lost, as they might miss the last flush that can happen on their data.
*
* @throws IOException instead of the Exception superclass as defined in AutoCloseable, if .
* @see AutoCloseable#close()
*/
void close() throws IOException;
}