You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/04/18 05:25:37 UTC
[22/54] [abbrv] ignite git commit: ignite-4982 Properly handle case
when near node becomes backup
ignite-4982 Properly handle case when near node becomes backup
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/22e2d8cf
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/22e2d8cf
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/22e2d8cf
Branch: refs/heads/ignite-1561
Commit: 22e2d8cf3a8e75c9c7c177be72bbfba4e54cb85e
Parents: 49cae05
Author: Konstantin Dudkov <kd...@ya.ru>
Authored: Mon Apr 17 17:21:27 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Mon Apr 17 17:21:27 2017 +0300
----------------------------------------------------------------------
.../GridDhtAtomicAbstractUpdateRequest.java | 14 +
.../GridDhtAtomicSingleUpdateRequest.java | 21 +-
.../dht/atomic/GridDhtAtomicUpdateRequest.java | 52 +-
.../distributed/near/GridNearAtomicCache.java | 16 +-
.../ignite/internal/util/GridIntList.java | 587 +++++++++++++++++++
5 files changed, 674 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/22e2d8cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicAbstractUpdateRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicAbstractUpdateRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicAbstractUpdateRequest.java
index 2826215..4ff8484 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicAbstractUpdateRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicAbstractUpdateRequest.java
@@ -56,6 +56,9 @@ public abstract class GridDhtAtomicAbstractUpdateRequest extends GridCacheMessag
/** */
private static final int DHT_ATOMIC_REPLY_WITHOUT_DELAY = 0x10;
+ /** */
+ protected static final int DHT_ATOMIC_OBSOLETE_NEAR_KEY_FLAG_MASK = 0x20;
+
/** Message index. */
public static final int CACHE_MSG_IDX = nextIndexId();
@@ -343,6 +346,17 @@ public abstract class GridDhtAtomicAbstractUpdateRequest extends GridCacheMessag
public abstract KeyCacheObject key(int idx);
/**
+ * @return Obsolete near cache keys size.
+ */
+ public abstract int obsoleteNearKeysSize();
+
+ /**
+ * @param idx Obsolete near cache key index.
+ * @return Obsolete near cache key.
+ */
+ public abstract KeyCacheObject obsoleteNearKey(int idx);
+
+ /**
* @param updCntr Update counter.
* @return Update counter.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/22e2d8cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicSingleUpdateRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicSingleUpdateRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicSingleUpdateRequest.java
index 852beec..8931c24 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicSingleUpdateRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicSingleUpdateRequest.java
@@ -135,7 +135,7 @@ public class GridDhtAtomicSingleUpdateRequest extends GridDhtAtomicAbstractUpdat
assert conflictVer == null : conflictVer;
assert key.partition() >= 0 : key;
- near(false);
+ assert this.key == null;
this.key = key;
this.val = val;
@@ -162,6 +162,12 @@ public class GridDhtAtomicSingleUpdateRequest extends GridDhtAtomicAbstractUpdat
assert ttl <= 0 : ttl;
assert key.partition() >= 0 : key;
+ if (this.key != null) {
+ setFlag(true, DHT_ATOMIC_OBSOLETE_NEAR_KEY_FLAG_MASK);
+
+ return;
+ }
+
near(true);
this.key = key;
@@ -196,6 +202,18 @@ public class GridDhtAtomicSingleUpdateRequest extends GridDhtAtomicAbstractUpdat
}
/** {@inheritDoc} */
+ @Override public int obsoleteNearKeysSize() {
+ return isFlag(DHT_ATOMIC_OBSOLETE_NEAR_KEY_FLAG_MASK) ? 1 : 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public KeyCacheObject obsoleteNearKey(int idx) {
+ assert obsoleteNearKeysSize() == 1 && idx == 0 : idx;
+
+ return key;
+ }
+
+ /** {@inheritDoc} */
@Override public int partition() {
int p = key.partition();
@@ -304,7 +322,6 @@ public class GridDhtAtomicSingleUpdateRequest extends GridDhtAtomicAbstractUpdat
prepareMarshalObject(val, cctx);
prepareMarshalObject(prevVal, cctx);
-
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/22e2d8cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
index d8e7f24..54b2ae7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
@@ -33,6 +33,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
import org.apache.ignite.internal.processors.cache.KeyCacheObject;
import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.GridIntList;
import org.apache.ignite.internal.util.GridLongList;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
import org.apache.ignite.internal.util.typedef.F;
@@ -92,6 +93,10 @@ public class GridDhtAtomicUpdateRequest extends GridDhtAtomicAbstractUpdateReque
@GridDirectCollection(CacheObject.class)
private List<CacheObject> nearVals;
+ /** Obsolete near values. */
+ @GridToStringInclude
+ private GridIntList obsoleteIndexes;
+
/** Force transform backups flag. */
private boolean forceTransformBackups;
@@ -267,6 +272,15 @@ public class GridDhtAtomicUpdateRequest extends GridDhtAtomicAbstractUpdateReque
long expireTime) {
assert key.partition() >= 0 : key;
+ if (hasKey(key)) {
+ if (obsoleteIndexes == null)
+ obsoleteIndexes = new GridIntList();
+
+ obsoleteIndexes.add(keys.indexOf(key));
+
+ return;
+ }
+
if (nearKeys == null) {
nearKeys = new ArrayList<>();
@@ -334,6 +348,16 @@ public class GridDhtAtomicUpdateRequest extends GridDhtAtomicAbstractUpdateReque
}
/** {@inheritDoc} */
+ @Override public int obsoleteNearKeysSize() {
+ return obsoleteIndexes != null ? obsoleteIndexes.size() : 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public KeyCacheObject obsoleteNearKey(int idx) {
+ return keys.get(obsoleteIndexes.get(idx));
+ }
+
+ /** {@inheritDoc} */
@Override public boolean hasKey(KeyCacheObject key) {
return F.contains(keys, key);
}
@@ -603,24 +627,30 @@ public class GridDhtAtomicUpdateRequest extends GridDhtAtomicAbstractUpdateReque
writer.incrementState();
case 23:
- if (!writer.writeCollection("prevVals", prevVals, MessageCollectionItemType.MSG))
+ if (!writer.writeMessage("obsoleteIndexes", obsoleteIndexes))
return false;
writer.incrementState();
case 24:
- if (!writer.writeMessage("ttls", ttls))
+ if (!writer.writeCollection("prevVals", prevVals, MessageCollectionItemType.MSG))
return false;
writer.incrementState();
case 25:
- if (!writer.writeMessage("updateCntrs", updateCntrs))
+ if (!writer.writeMessage("ttls", ttls))
return false;
writer.incrementState();
case 26:
+ if (!writer.writeMessage("updateCntrs", updateCntrs))
+ return false;
+
+ writer.incrementState();
+
+ case 27:
if (!writer.writeCollection("vals", vals, MessageCollectionItemType.MSG))
return false;
@@ -731,7 +761,7 @@ public class GridDhtAtomicUpdateRequest extends GridDhtAtomicAbstractUpdateReque
reader.incrementState();
case 23:
- prevVals = reader.readCollection("prevVals", MessageCollectionItemType.MSG);
+ obsoleteIndexes = reader.readMessage("obsoleteIndexes");
if (!reader.isLastRead())
return false;
@@ -739,7 +769,7 @@ public class GridDhtAtomicUpdateRequest extends GridDhtAtomicAbstractUpdateReque
reader.incrementState();
case 24:
- ttls = reader.readMessage("ttls");
+ prevVals = reader.readCollection("prevVals", MessageCollectionItemType.MSG);
if (!reader.isLastRead())
return false;
@@ -747,7 +777,7 @@ public class GridDhtAtomicUpdateRequest extends GridDhtAtomicAbstractUpdateReque
reader.incrementState();
case 25:
- updateCntrs = reader.readMessage("updateCntrs");
+ ttls = reader.readMessage("ttls");
if (!reader.isLastRead())
return false;
@@ -755,6 +785,14 @@ public class GridDhtAtomicUpdateRequest extends GridDhtAtomicAbstractUpdateReque
reader.incrementState();
case 26:
+ updateCntrs = reader.readMessage("updateCntrs");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 27:
vals = reader.readCollection("vals", MessageCollectionItemType.MSG);
if (!reader.isLastRead())
@@ -780,7 +818,7 @@ public class GridDhtAtomicUpdateRequest extends GridDhtAtomicAbstractUpdateReque
/** {@inheritDoc} */
@Override public byte fieldsCount() {
- return 27;
+ return 28;
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/22e2d8cf/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
index 0deb9bd..422a3fc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
@@ -328,13 +328,6 @@ public class GridNearAtomicCache<K, V> extends GridNearCacheAdapter<K, V> {
break;
}
- if (req.hasKey(key)) { // Reader became backup.
- if (entry.markObsolete(ver))
- removeEntry(entry);
-
- break;
- }
-
CacheObject val = req.nearValue(i);
EntryProcessor<Object, Object, Object> entryProcessor = req.nearEntryProcessor(i);
@@ -390,6 +383,15 @@ public class GridNearAtomicCache<K, V> extends GridNearCacheAdapter<K, V> {
}
}
+ for (int i = 0; i < req.obsoleteNearKeysSize(); i++) {
+ KeyCacheObject key = req.obsoleteNearKey(i);
+
+ GridCacheEntryEx entry = peekEx(key);
+
+ if (entry != null && entry.markObsolete(ver))
+ removeEntry(entry);
+ }
+
return nearEvicted;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/22e2d8cf/modules/core/src/main/java/org/apache/ignite/internal/util/GridIntList.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/GridIntList.java b/modules/core/src/main/java/org/apache/ignite/internal/util/GridIntList.java
new file mode 100644
index 0000000..1de8106
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/GridIntList.java
@@ -0,0 +1,587 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.util;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.NoSuchElementException;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.SB;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Minimal list API to work with primitive ints. This list exists
+ * to avoid boxing/unboxing when using standard list from Java.
+ */
+public class GridIntList implements Message, Externalizable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** */
+ private int[] arr;
+
+ /** */
+ private int idx;
+
+ /**
+ *
+ */
+ public GridIntList() {
+ // No-op.
+ }
+
+ /**
+ * @param size Size.
+ */
+ public GridIntList(int size) {
+ arr = new int[size];
+ // idx = 0
+ }
+
+ /**
+ * @param arr Array.
+ */
+ public GridIntList(int[] arr) {
+ this.arr = arr;
+
+ idx = arr.length;
+ }
+
+ /**
+ * @param vals Values.
+ * @return List from values.
+ */
+ public static GridIntList asList(int... vals) {
+ if (F.isEmpty(vals))
+ return new GridIntList();
+
+ return new GridIntList(vals);
+ }
+
+ /**
+ * @param arr Array.
+ * @param size Size.
+ */
+ private GridIntList(int[] arr, int size) {
+ this.arr = arr;
+ idx = size;
+ }
+
+ /**
+ * @return Copy of this list.
+ */
+ public GridIntList copy() {
+ if (idx == 0)
+ return new GridIntList();
+
+ return new GridIntList(Arrays.copyOf(arr, idx));
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (!(o instanceof GridIntList))
+ return false;
+
+ GridIntList that = (GridIntList)o;
+
+ if (idx != that.idx)
+ return false;
+
+ if (idx == 0 || arr == that.arr)
+ return true;
+
+ for (int i = 0; i < idx; i++) {
+ if (arr[i] != that.arr[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = 1;
+
+ for (int i = 0; i < idx; i++) {
+ int element = arr[i];
+ int elementHash = (int)(element ^ (element >>> 32));
+ res = 31 * res + elementHash;
+ }
+
+ return res;
+ }
+
+ /**
+ * @param l List to add all elements of.
+ */
+ public void addAll(GridIntList l) {
+ assert l != null;
+
+ if (l.isEmpty())
+ return;
+
+ if (arr == null)
+ arr = new int[4];
+
+ int len = arr.length;
+
+ while (len < idx + l.size())
+ len <<= 1;
+
+ arr = Arrays.copyOf(arr, len);
+
+ System.arraycopy(l.arr, 0, arr, idx, l.size());
+
+ idx += l.size();
+ }
+
+ /**
+ * Add element to this array.
+ * @param x Value.
+ */
+ public void add(int x) {
+ if (arr == null)
+ arr = new int[4];
+ else if (arr.length == idx)
+ arr = Arrays.copyOf(arr, arr.length << 1);
+
+ arr[idx++] = x;
+ }
+
+ /**
+ * Clears the list.
+ */
+ public void clear() {
+ idx = 0;
+ }
+
+ /**
+ * Gets the last element.
+ *
+ * @return The last element.
+ */
+ public int last() {
+ return arr[idx - 1];
+ }
+
+ /**
+ * Removes and returns the last element of the list. Complementary method to {@link #add(int)} for stack like usage.
+ *
+ * @return Removed element.
+ * @throws NoSuchElementException If the list is empty.
+ */
+ public int remove() throws NoSuchElementException {
+ if (idx == 0)
+ throw new NoSuchElementException();
+
+ return arr[--idx];
+ }
+
+ /**
+ * Returns (possibly reordered) copy of this list, excluding all elements of given list.
+ *
+ * @param l List of elements to remove.
+ * @return New list without all elements from {@code l}.
+ */
+ public GridIntList copyWithout(GridIntList l) {
+ assert l != null;
+
+ if (idx == 0)
+ return new GridIntList();
+
+ if (l.idx == 0)
+ return new GridIntList(Arrays.copyOf(arr, idx));
+
+ int[] newArr = Arrays.copyOf(arr, idx);
+ int newIdx = idx;
+
+ for (int i = 0; i < l.size(); i++) {
+ int rmVal = l.get(i);
+
+ for (int j = 0; j < newIdx; j++) {
+ if (newArr[j] == rmVal) {
+
+ while (newIdx > 0 && newArr[newIdx - 1] == rmVal)
+ newIdx--;
+
+ if (newIdx > 0) {
+ newArr[j] = newArr[newIdx - 1];
+ newIdx--;
+ }
+ }
+ }
+ }
+
+ return new GridIntList(newArr, newIdx);
+ }
+
+ /**
+ * @param i Index.
+ * @return Value.
+ */
+ public int get(int i) {
+ assert i < idx;
+
+ return arr[i];
+ }
+
+ /**
+ * @return Size.
+ */
+ public int size() {
+ return idx;
+ }
+
+ /**
+ * @return {@code True} if this list has no elements.
+ */
+ public boolean isEmpty() {
+ return idx == 0;
+ }
+
+ /**
+ * @param l Element to find.
+ * @return {@code True} if found.
+ */
+ public boolean contains(int l) {
+ for (int i = 0; i < idx; i++) {
+ if (arr[i] == l)
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param l List to check.
+ * @return {@code True} if this list contains all the elements of passed in list.
+ */
+ public boolean containsAll(GridIntList l) {
+ for (int i = 0; i < l.size(); i++) {
+ if (!contains(l.get(i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @return {@code True} if there are no duplicates.
+ */
+ public boolean distinct() {
+ for (int i = 0; i < idx; i++) {
+ for (int j = i + 1; j < idx; j++) {
+ if (arr[i] == arr[j])
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @param size New size.
+ * @param last If {@code true} the last elements will be removed, otherwise the first.
+ */
+ public void truncate(int size, boolean last) {
+ assert size >= 0 && size <= idx;
+
+ if (size == idx)
+ return;
+
+ if (!last && idx != 0 && size != 0)
+ System.arraycopy(arr, idx - size, arr, 0, size);
+
+ idx = size;
+ }
+
+ /**
+ * Removes element by given index.
+ *
+ * @param i Index.
+ * @return Removed value.
+ */
+ public int removeIndex(int i) {
+ assert i < idx : i;
+
+ int res = arr[i];
+
+ if (i == idx - 1) { // Last element.
+ idx = i;
+ }
+ else {
+ System.arraycopy(arr, i + 1, arr, i, idx - i - 1);
+ idx--;
+ }
+
+ return res;
+ }
+
+ /**
+ * Removes value from this list.
+ *
+ * @param startIdx Index to begin search with.
+ * @param val Value.
+ * @return Index of removed value if the value was found and removed or {@code -1} otherwise.
+ */
+ public int removeValue(int startIdx, int val) {
+ assert startIdx >= 0;
+
+ for (int i = startIdx; i < idx; i++) {
+ if (arr[i] == val) {
+ removeIndex(i);
+
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * Removes value from this list.
+ *
+ * @param startIdx Index to begin search with.
+ * @param oldVal Old value.
+ * @param newVal New value.
+ * @return Index of replaced value if the value was found and replaced or {@code -1} otherwise.
+ */
+ public int replaceValue(int startIdx, int oldVal, int newVal) {
+ for (int i = startIdx; i < idx; i++) {
+ if (arr[i] == oldVal) {
+ arr[i] = newVal;
+
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ /**
+ * @return Array copy.
+ */
+ public int[] array() {
+ int[] res = new int[idx];
+
+ System.arraycopy(arr, 0, res, 0, idx);
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeInt(idx);
+
+ for (int i = 0; i < idx; i++)
+ out.writeInt(arr[i]);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ idx = in.readInt();
+
+ arr = new int[idx];
+
+ for (int i = 0; i < idx; i++)
+ arr[i] = in.readInt();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ SB b = new SB("[");
+
+ for (int i = 0; i < idx; i++) {
+ if (i != 0)
+ b.a(',');
+
+ b.a(arr[i]);
+ }
+
+ b.a(']');
+
+ return S.toString(GridIntList.class, this, "arr", b);
+ }
+
+ /**
+ * @param in Input to read list from.
+ * @return Grid int list.
+ * @throws IOException If failed.
+ */
+ @Nullable public static GridIntList readFrom(DataInput in) throws IOException {
+ int idx = in.readInt();
+
+ if (idx == -1)
+ return null;
+
+ int[] arr = new int[idx];
+
+ for (int i = 0; i < idx; i++)
+ arr[i] = in.readInt();
+
+ return new GridIntList(arr);
+ }
+
+ /**
+ * @param out Output to write to.
+ * @param list List.
+ * @throws IOException If failed.
+ */
+ public static void writeTo(DataOutput out, @Nullable GridIntList list) throws IOException {
+ out.writeInt(list != null ? list.idx : -1);
+
+ if (list != null) {
+ for (int i = 0; i < list.idx; i++)
+ out.writeInt(list.arr[i]);
+ }
+ }
+
+ /**
+ * @param to To list.
+ * @param from From list.
+ * @return To list (passed in or created).
+ */
+ public static GridIntList addAll(@Nullable GridIntList to, GridIntList from) {
+ if (to == null) {
+ GridIntList res = new GridIntList(from.size());
+
+ res.addAll(from);
+
+ return res;
+ }
+ else {
+ to.addAll(from);
+
+ return to;
+ }
+ }
+
+ /**
+ * Sorts this list.
+ * Use {@code copy().sort()} if you need a defensive copy.
+ *
+ * @return {@code this} For chaining.
+ */
+ public GridIntList sort() {
+ if (idx > 1)
+ Arrays.sort(arr, 0, idx);
+
+ return this;
+ }
+
+ /**
+ * Removes given number of elements from the end. If the given number of elements is higher than
+ * list size, then list will be cleared.
+ *
+ * @param cnt Count to pop from the end.
+ */
+ public void pop(int cnt) {
+ assert cnt >= 0 : cnt;
+
+ if (idx < cnt)
+ idx = 0;
+ else
+ idx -= cnt;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onAckReceived() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeIntArray("arr", arr))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeInt("idx", idx))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ arr = reader.readIntArray("arr");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ idx = reader.readInt("idx");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(GridIntList.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public short directType() {
+ return 85;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 2;
+ }
+}