|
19 | 19 | import org.elasticsearch.core.Releasable;
|
20 | 20 | import org.elasticsearch.index.stats.IndexingPressureStats;
|
21 | 21 |
|
| 22 | +import java.util.Optional; |
22 | 23 | import java.util.concurrent.atomic.AtomicBoolean;
|
23 | 24 | import java.util.concurrent.atomic.AtomicLong;
|
24 | 25 |
|
@@ -138,48 +139,167 @@ private static Releasable wrapReleasable(Releasable releasable) {
|
138 | 139 | };
|
139 | 140 | }
|
140 | 141 |
|
141 |
| - public Releasable markCoordinatingOperationStarted(int operations, long bytes, boolean forceExecution) { |
142 |
| - long combinedBytes = this.currentCombinedCoordinatingAndPrimaryBytes.addAndGet(bytes); |
143 |
| - long replicaWriteBytes = this.currentReplicaBytes.get(); |
144 |
| - long totalBytes = combinedBytes + replicaWriteBytes; |
145 |
| - if (forceExecution == false && totalBytes > coordinatingLimit) { |
146 |
| - long bytesWithoutOperation = combinedBytes - bytes; |
147 |
| - long totalBytesWithoutOperation = totalBytes - bytes; |
148 |
| - this.currentCombinedCoordinatingAndPrimaryBytes.getAndAdd(-bytes); |
149 |
| - this.coordinatingRejections.getAndIncrement(); |
150 |
| - throw new EsRejectedExecutionException( |
151 |
| - "rejected execution of coordinating operation [" |
152 |
| - + "coordinating_and_primary_bytes=" |
153 |
| - + bytesWithoutOperation |
154 |
| - + ", " |
155 |
| - + "replica_bytes=" |
156 |
| - + replicaWriteBytes |
157 |
| - + ", " |
158 |
| - + "all_bytes=" |
159 |
| - + totalBytesWithoutOperation |
160 |
| - + ", " |
161 |
| - + "coordinating_operation_bytes=" |
162 |
| - + bytes |
163 |
| - + ", " |
164 |
| - + "max_coordinating_bytes=" |
165 |
| - + coordinatingLimit |
166 |
| - + "]", |
167 |
| - false |
168 |
| - ); |
| 142 | + public Incremental startIncrementalCoordinating(int operations, long bytes, boolean forceExecution) { |
| 143 | + Incremental coordinating = new Incremental(forceExecution); |
| 144 | + coordinating.coordinating.increment(operations, bytes); |
| 145 | + return coordinating; |
| 146 | + } |
| 147 | + |
| 148 | + public Coordinating markCoordinatingOperationStarted(int operations, long bytes, boolean forceExecution) { |
| 149 | + Coordinating coordinating = new Coordinating(forceExecution); |
| 150 | + coordinating.increment(operations, bytes); |
| 151 | + return coordinating; |
| 152 | + } |
| 153 | + |
| 154 | + public class Incremental implements Releasable { |
| 155 | + |
| 156 | + private final AtomicBoolean closed = new AtomicBoolean(); |
| 157 | + private final boolean forceExecution; |
| 158 | + private long currentUnparsedSize = 0; |
| 159 | + private long totalParsedBytes = 0; |
| 160 | + private Coordinating coordinating; |
| 161 | + |
| 162 | + public Incremental(boolean forceExecution) { |
| 163 | + this.forceExecution = forceExecution; |
| 164 | + this.coordinating = new Coordinating(forceExecution); |
| 165 | + } |
| 166 | + |
| 167 | + public long totalParsedBytes() { |
| 168 | + return totalParsedBytes; |
| 169 | + } |
| 170 | + |
| 171 | + public void incrementUnparsedBytes(long bytes) { |
| 172 | + assert closed.get() == false; |
| 173 | + // TODO: Implement integration with IndexingPressure for unparsed bytes |
| 174 | + currentUnparsedSize += bytes; |
| 175 | + } |
| 176 | + |
| 177 | + public void transferUnparsedBytesToParsed(long bytes) { |
| 178 | + assert closed.get() == false; |
| 179 | + assert currentUnparsedSize >= bytes; |
| 180 | + currentUnparsedSize -= bytes; |
| 181 | + totalParsedBytes += bytes; |
| 182 | + } |
| 183 | + |
| 184 | + public void increment(int operations, long bytes) { |
| 185 | + // TODO: Eventually most of the memory will already be accounted for in unparsed. |
| 186 | + coordinating.increment(operations, bytes); |
| 187 | + } |
| 188 | + |
| 189 | + public long currentOperationsSize() { |
| 190 | + return coordinating.currentOperationsSize; |
| 191 | + } |
| 192 | + |
| 193 | + public Optional<Releasable> maybeSplit() { |
| 194 | + long currentUsage = (currentCombinedCoordinatingAndPrimaryBytes.get() + currentReplicaBytes.get()); |
| 195 | + long currentOperationsSize = coordinating.currentOperationsSize; |
| 196 | + if (currentUsage >= highWatermark && currentOperationsSize >= highWatermarkSize) { |
| 197 | + highWaterMarkSplits.getAndIncrement(); |
| 198 | + logger.trace( |
| 199 | + () -> Strings.format( |
| 200 | + "Split bulk due to high watermark: current bytes [%d] and size [%d]", |
| 201 | + currentUsage, |
| 202 | + currentOperationsSize |
| 203 | + ) |
| 204 | + ); |
| 205 | + return Optional.of(split()); |
| 206 | + } |
| 207 | + if (currentUsage >= lowWatermark && currentOperationsSize >= lowWatermarkSize) { |
| 208 | + lowWaterMarkSplits.getAndIncrement(); |
| 209 | + logger.trace( |
| 210 | + () -> Strings.format( |
| 211 | + "Split bulk due to low watermark: current bytes [%d] and size [%d]", |
| 212 | + currentUsage, |
| 213 | + currentOperationsSize |
| 214 | + ) |
| 215 | + ); |
| 216 | + return Optional.of(split()); |
| 217 | + } |
| 218 | + return Optional.empty(); |
| 219 | + } |
| 220 | + |
| 221 | + public Releasable split() { |
| 222 | + Coordinating toReturn = coordinating; |
| 223 | + coordinating = new Coordinating(forceExecution); |
| 224 | + return toReturn; |
| 225 | + } |
| 226 | + |
| 227 | + @Override |
| 228 | + public void close() { |
| 229 | + coordinating.close(); |
| 230 | + } |
| 231 | + } |
| 232 | + |
| 233 | + // TODO: Maybe this should be re-named and used for primary operations too. Eventually we will need to account for: ingest pipeline |
| 234 | + // expansions, reading updates, etc. This could just be a generic OP that could be expanded as appropriate |
| 235 | + public class Coordinating implements Releasable { |
| 236 | + |
| 237 | + private final AtomicBoolean closed = new AtomicBoolean(); |
| 238 | + private final boolean forceExecution; |
| 239 | + private int currentOperations = 0; |
| 240 | + private long currentOperationsSize = 0; |
| 241 | + |
| 242 | + public Coordinating(boolean forceExecution) { |
| 243 | + this.forceExecution = forceExecution; |
| 244 | + } |
| 245 | + |
| 246 | + private void increment(int operations, long bytes) { |
| 247 | + assert closed.get() == false; |
| 248 | + long combinedBytes = currentCombinedCoordinatingAndPrimaryBytes.addAndGet(bytes); |
| 249 | + long replicaWriteBytes = currentReplicaBytes.get(); |
| 250 | + long totalBytes = combinedBytes + replicaWriteBytes; |
| 251 | + if (forceExecution == false && totalBytes > coordinatingLimit) { |
| 252 | + long bytesWithoutOperation = combinedBytes - bytes; |
| 253 | + long totalBytesWithoutOperation = totalBytes - bytes; |
| 254 | + currentCombinedCoordinatingAndPrimaryBytes.getAndAdd(-bytes); |
| 255 | + coordinatingRejections.getAndIncrement(); |
| 256 | + throw new EsRejectedExecutionException( |
| 257 | + "rejected execution of coordinating operation [" |
| 258 | + + "coordinating_and_primary_bytes=" |
| 259 | + + bytesWithoutOperation |
| 260 | + + ", " |
| 261 | + + "replica_bytes=" |
| 262 | + + replicaWriteBytes |
| 263 | + + ", " |
| 264 | + + "all_bytes=" |
| 265 | + + totalBytesWithoutOperation |
| 266 | + + ", " |
| 267 | + + "coordinating_operation_bytes=" |
| 268 | + + bytes |
| 269 | + + ", " |
| 270 | + + "max_coordinating_bytes=" |
| 271 | + + coordinatingLimit |
| 272 | + + "]", |
| 273 | + false |
| 274 | + ); |
| 275 | + } |
| 276 | + currentOperations += operations; |
| 277 | + currentOperationsSize += bytes; |
| 278 | + logger.trace(() -> Strings.format("adding [%d] coordinating operations and [%d] bytes", operations, bytes)); |
| 279 | + currentCoordinatingBytes.getAndAdd(bytes); |
| 280 | + currentCoordinatingOps.getAndAdd(operations); |
| 281 | + totalCombinedCoordinatingAndPrimaryBytes.getAndAdd(bytes); |
| 282 | + totalCoordinatingBytes.getAndAdd(bytes); |
| 283 | + totalCoordinatingOps.getAndAdd(operations); |
| 284 | + totalCoordinatingRequests.getAndIncrement(); |
| 285 | + } |
| 286 | + |
| 287 | + @Override |
| 288 | + public void close() { |
| 289 | + if (closed.compareAndSet(false, true)) { |
| 290 | + logger.trace( |
| 291 | + () -> Strings.format("removing [%d] coordinating operations and [%d] bytes", currentOperations, currentOperationsSize) |
| 292 | + ); |
| 293 | + currentCombinedCoordinatingAndPrimaryBytes.getAndAdd(-currentOperationsSize); |
| 294 | + currentCoordinatingBytes.getAndAdd(-currentOperationsSize); |
| 295 | + currentCoordinatingOps.getAndAdd(-currentOperations); |
| 296 | + currentOperationsSize = 0; |
| 297 | + currentOperations = 0; |
| 298 | + } else { |
| 299 | + logger.error("IndexingPressure memory is adjusted twice", new IllegalStateException("Releasable is called twice")); |
| 300 | + assert false : "IndexingPressure is adjusted twice"; |
| 301 | + } |
169 | 302 | }
|
170 |
| - logger.trace(() -> Strings.format("adding [%d] coordinating operations and [%d] bytes", operations, bytes)); |
171 |
| - currentCoordinatingBytes.getAndAdd(bytes); |
172 |
| - currentCoordinatingOps.getAndAdd(operations); |
173 |
| - totalCombinedCoordinatingAndPrimaryBytes.getAndAdd(bytes); |
174 |
| - totalCoordinatingBytes.getAndAdd(bytes); |
175 |
| - totalCoordinatingOps.getAndAdd(operations); |
176 |
| - totalCoordinatingRequests.getAndIncrement(); |
177 |
| - return wrapReleasable(() -> { |
178 |
| - logger.trace(() -> Strings.format("removing [%d] coordinating operations and [%d] bytes", operations, bytes)); |
179 |
| - this.currentCombinedCoordinatingAndPrimaryBytes.getAndAdd(-bytes); |
180 |
| - this.currentCoordinatingBytes.getAndAdd(-bytes); |
181 |
| - this.currentCoordinatingOps.getAndAdd(-operations); |
182 |
| - }); |
183 | 303 | }
|
184 | 304 |
|
185 | 305 | public Releasable markPrimaryOperationLocalToCoordinatingNodeStarted(int operations, long bytes) {
|
@@ -266,21 +386,6 @@ public Releasable markReplicaOperationStarted(int operations, long bytes, boolea
|
266 | 386 | });
|
267 | 387 | }
|
268 | 388 |
|
269 |
| - public boolean shouldSplitBulk(long size) { |
270 |
| - long currentUsage = (currentCombinedCoordinatingAndPrimaryBytes.get() + currentReplicaBytes.get()); |
271 |
| - if (currentUsage >= highWatermark && size >= highWatermarkSize) { |
272 |
| - highWaterMarkSplits.getAndIncrement(); |
273 |
| - logger.trace(() -> Strings.format("Split bulk due to high watermark: current bytes [%d] and size [%d]", currentUsage, size)); |
274 |
| - return (true); |
275 |
| - } |
276 |
| - if (currentUsage >= lowWatermark && size >= lowWatermarkSize) { |
277 |
| - lowWaterMarkSplits.getAndIncrement(); |
278 |
| - logger.trace(() -> Strings.format("Split bulk due to low watermark: current bytes [%d] and size [%d]", currentUsage, size)); |
279 |
| - return (true); |
280 |
| - } |
281 |
| - return (false); |
282 |
| - } |
283 |
| - |
284 | 389 | public IndexingPressureStats stats() {
|
285 | 390 | return new IndexingPressureStats(
|
286 | 391 | totalCombinedCoordinatingAndPrimaryBytes.get(),
|
|
0 commit comments