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