Update DataJournal interface
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / io / ChunkedByteArray.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.io;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.annotations.VisibleForTesting;
14 import com.google.common.base.MoreObjects;
15 import com.google.common.collect.ImmutableList;
16 import com.google.common.io.ByteSink;
17 import java.io.DataOutput;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.ObjectInput;
21 import java.util.ArrayList;
22 import java.util.List;
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.opendaylight.yangtools.concepts.Immutable;
25
26 @Beta
27 @NonNullByDefault
28 public final class ChunkedByteArray implements Immutable {
29     private final ImmutableList<byte[]> chunks;
30     private final int size;
31
32     ChunkedByteArray(final int size, final ImmutableList<byte[]> chunks) {
33         this.size = size;
34         this.chunks = requireNonNull(chunks);
35     }
36
37     public static ChunkedByteArray readFrom(final ObjectInput in, final int size, final int chunkSize)
38             throws IOException {
39         final List<byte[]> chunks = new ArrayList<>(requiredChunks(size, chunkSize));
40         int remaining = size;
41         do {
42             final byte[] buffer = new byte[Math.min(remaining, chunkSize)];
43             in.readFully(buffer);
44             chunks.add(buffer);
45             remaining -= buffer.length;
46         } while (remaining != 0);
47
48         return new ChunkedByteArray(size, ImmutableList.copyOf(chunks));
49     }
50
51     public int size() {
52         return size;
53     }
54
55     public InputStream openStream() {
56         return new ChunkedInputStream(size, chunks.iterator());
57     }
58
59     public void copyTo(final DataOutput output) throws IOException {
60         for (byte[] chunk : chunks) {
61             output.write(chunk, 0, chunk.length);
62         }
63     }
64
65     public void copyTo(final ByteSink output) throws IOException {
66         for (byte[] chunk : chunks) {
67             output.write(chunk);
68         }
69     }
70
71     @Override
72     public String toString() {
73         return MoreObjects.toStringHelper(this).add("size", size).add("chunkCount", chunks.size()).toString();
74     }
75
76     @VisibleForTesting
77     ImmutableList<byte[]> getChunks() {
78         return chunks;
79     }
80
81     private static int requiredChunks(final int size, final int chunkSize) {
82         final int div = size / chunkSize;
83         return size % chunkSize == 0 ? div : div + 1;
84     }
85 }