Bump upstream versions
[controller.git] / opendaylight / md-sal / sal-clustering-commons / src / main / java / org / opendaylight / controller / cluster / messaging / MessageSliceIdentifier.java
1 /*
2  * Copyright (c) 2017 Inocybe Technologies 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.messaging;
9
10 import static java.util.Objects.requireNonNull;
11
12 import java.io.Externalizable;
13 import java.io.IOException;
14 import java.io.ObjectInput;
15 import java.io.ObjectOutput;
16 import java.util.concurrent.atomic.AtomicLong;
17 import org.opendaylight.yangtools.concepts.Identifier;
18 import org.opendaylight.yangtools.concepts.WritableObjects;
19
20 /**
21  * Identifier for a message slice that is composed of a client-supplied Identifier and an internal counter value.
22  *
23  * @author Thomas Pantelis
24  */
25 final class MessageSliceIdentifier implements Identifier {
26     private static final long serialVersionUID = 1L;
27     private static final AtomicLong ID_COUNTER = new AtomicLong(1);
28
29     private final Identifier clientIdentifier;
30     private final long slicerId;
31     private final long messageId;
32
33     MessageSliceIdentifier(final Identifier clientIdentifier, final long slicerId) {
34         this(clientIdentifier, slicerId, ID_COUNTER.getAndIncrement());
35     }
36
37     private MessageSliceIdentifier(final Identifier clientIdentifier, final long slicerId, final long messageId) {
38         this.clientIdentifier = requireNonNull(clientIdentifier);
39         this.messageId = messageId;
40         this.slicerId = slicerId;
41     }
42
43     Identifier getClientIdentifier() {
44         return clientIdentifier;
45     }
46
47     long getSlicerId() {
48         return slicerId;
49     }
50
51     @Override
52     public int hashCode() {
53         final int prime = 31;
54         int result = 1;
55         result = prime * result + clientIdentifier.hashCode();
56         result = prime * result + (int) (messageId ^ messageId >>> 32);
57         result = prime * result + (int) (slicerId ^ slicerId >>> 32);
58         return result;
59     }
60
61     @Override
62     public boolean equals(final Object obj) {
63         if (this == obj) {
64             return true;
65         }
66
67         if (!(obj instanceof MessageSliceIdentifier)) {
68             return false;
69         }
70
71         MessageSliceIdentifier other = (MessageSliceIdentifier) obj;
72         return other.clientIdentifier.equals(clientIdentifier) && other.slicerId == slicerId
73                 && other.messageId == messageId;
74     }
75
76     @Override
77     public String toString() {
78         return "MessageSliceIdentifier [clientIdentifier=" + clientIdentifier + ", slicerId=" + slicerId
79                 + ", messageId=" + messageId + "]";
80     }
81
82     private Object writeReplace() {
83         return new Proxy(this);
84     }
85
86     private static class Proxy implements Externalizable {
87         private static final long serialVersionUID = 1L;
88
89         private MessageSliceIdentifier messageSliceId;
90
91         // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
92         // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
93         @SuppressWarnings("checkstyle:RedundantModifier")
94         public Proxy() {
95         }
96
97         Proxy(final MessageSliceIdentifier messageSliceId) {
98             this.messageSliceId = messageSliceId;
99         }
100
101         @Override
102         public void writeExternal(final ObjectOutput out) throws IOException {
103             out.writeObject(messageSliceId.clientIdentifier);
104             WritableObjects.writeLongs(out, messageSliceId.slicerId, messageSliceId.messageId);
105         }
106
107         @Override
108         public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
109             final Identifier clientIdentifier = (Identifier) in.readObject();
110             final byte header = WritableObjects.readLongHeader(in);
111             final long slicerId =  WritableObjects.readFirstLong(in, header);
112             final long messageId = WritableObjects.readSecondLong(in, header);
113             messageSliceId = new MessageSliceIdentifier(clientIdentifier, slicerId, messageId);
114         }
115
116         private Object readResolve() {
117             return messageSliceId;
118         }
119     }
120 }