Improve segmented journal actor metrics
[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         return this == obj || obj instanceof MessageSliceIdentifier other
64             && other.clientIdentifier.equals(clientIdentifier) && other.slicerId == slicerId
65             && other.messageId == messageId;
66     }
67
68     @Override
69     public String toString() {
70         return "MessageSliceIdentifier [clientIdentifier=" + clientIdentifier + ", slicerId=" + slicerId
71                 + ", messageId=" + messageId + "]";
72     }
73
74     private Object writeReplace() {
75         return new Proxy(this);
76     }
77
78     private static class Proxy implements Externalizable {
79         private static final long serialVersionUID = 1L;
80
81         private MessageSliceIdentifier messageSliceId;
82
83         // checkstyle flags the public modifier as redundant which really doesn't make sense since it clearly isn't
84         // redundant. It is explicitly needed for Java serialization to be able to create instances via reflection.
85         @SuppressWarnings("checkstyle:RedundantModifier")
86         public Proxy() {
87         }
88
89         Proxy(final MessageSliceIdentifier messageSliceId) {
90             this.messageSliceId = messageSliceId;
91         }
92
93         @Override
94         public void writeExternal(final ObjectOutput out) throws IOException {
95             out.writeObject(messageSliceId.clientIdentifier);
96             WritableObjects.writeLongs(out, messageSliceId.slicerId, messageSliceId.messageId);
97         }
98
99         @Override
100         public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
101             final Identifier clientIdentifier = (Identifier) in.readObject();
102             final byte header = WritableObjects.readLongHeader(in);
103             final long slicerId =  WritableObjects.readFirstLong(in, header);
104             final long messageId = WritableObjects.readSecondLong(in, header);
105             messageSliceId = new MessageSliceIdentifier(clientIdentifier, slicerId, messageId);
106         }
107
108         private Object readResolve() {
109             return messageSliceId;
110         }
111     }
112 }