Bug 7449: Add message slicing/re-assembly classes
[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 com.google.common.base.Preconditions;
11 import java.io.Externalizable;
12 import java.io.IOException;
13 import java.io.ObjectInput;
14 import java.io.ObjectOutput;
15 import java.util.concurrent.atomic.AtomicLong;
16 import org.opendaylight.yangtools.concepts.Identifier;
17
18 /**
19  * Identifier for a message slice that is composed of a client-supplied Identifier and an internal counter value.
20  *
21  * @author Thomas Pantelis
22  */
23 final class MessageSliceIdentifier implements Identifier {
24     private static final long serialVersionUID = 1L;
25     private static final AtomicLong ID_COUNTER = new AtomicLong(1);
26
27     private final Identifier clientIdentifier;
28     private final long messageId;
29
30     MessageSliceIdentifier(final Identifier clientIdentifier) {
31         this(clientIdentifier, ID_COUNTER.getAndIncrement());
32     }
33
34     private MessageSliceIdentifier(final Identifier clientIdentifier, final long messageId) {
35         this.clientIdentifier = Preconditions.checkNotNull(clientIdentifier);
36         this.messageId = messageId;
37     }
38
39     Identifier getClientIdentifier() {
40         return clientIdentifier;
41     }
42
43     @Override
44     public int hashCode() {
45         final int prime = 31;
46         int result = 1;
47         result = prime * result + clientIdentifier.hashCode();
48         result = prime * result + (int) (messageId ^ messageId >>> 32);
49         return result;
50     }
51
52     @Override
53     public boolean equals(Object obj) {
54         if (this == obj) {
55             return true;
56         }
57
58         if (!(obj instanceof MessageSliceIdentifier)) {
59             return false;
60         }
61
62         MessageSliceIdentifier other = (MessageSliceIdentifier) obj;
63         return other.clientIdentifier.equals(clientIdentifier) && other.messageId == messageId;
64     }
65
66     @Override
67     public String toString() {
68         return "MessageSliceIdentifier [clientIdentifier=" + clientIdentifier + ", messageId=" + messageId + "]";
69     }
70
71     private Object writeReplace() {
72         return new Proxy(this);
73     }
74
75     private static class Proxy implements Externalizable {
76         private static final long serialVersionUID = 1L;
77
78         private MessageSliceIdentifier messageSliceId;
79
80         // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
81         // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
82         @SuppressWarnings("checkstyle:RedundantModifier")
83         public Proxy() {
84         }
85
86         Proxy(MessageSliceIdentifier messageSliceId) {
87             this.messageSliceId = messageSliceId;
88         }
89
90         @Override
91         public void writeExternal(ObjectOutput out) throws IOException {
92             out.writeObject(messageSliceId.clientIdentifier);
93             out.writeLong(messageSliceId.messageId);
94         }
95
96         @Override
97         public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
98             messageSliceId = new MessageSliceIdentifier((Identifier) in.readObject(), in.readLong());
99         }
100
101         private Object readResolve() {
102             return messageSliceId;
103         }
104     }
105 }