blob: 62558ab47dd404de2de28abc99b21a6c57f4c0ac [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.store.cluster.messaging;
tom1d416c52014-09-29 20:55:24 -070017
Madan Jampaniba472232015-03-04 13:00:50 -080018import java.io.IOException;
19import java.nio.ByteBuffer;
20import java.util.Arrays;
21import java.util.Objects;
22
Jonathan Hart584d2f32015-01-27 19:46:14 -080023import org.onlab.util.ByteArraySizeHashPrinter;
24import org.onosproject.cluster.NodeId;
25
Madan Jampaniba472232015-03-04 13:00:50 -080026import com.google.common.base.Charsets;
27import com.google.common.base.MoreObjects;
tom1d416c52014-09-29 20:55:24 -070028
Yuta HIGUCHI971addc2014-10-07 23:23:17 -070029// TODO: Should payload type be ByteBuffer?
tom1d416c52014-09-29 20:55:24 -070030/**
31 * Base message for cluster-wide communications.
32 */
Madan Jampani890bc352014-10-01 22:35:29 -070033public class ClusterMessage {
tom1d416c52014-09-29 20:55:24 -070034
Madan Jampani890bc352014-10-01 22:35:29 -070035 private final NodeId sender;
tom1d416c52014-09-29 20:55:24 -070036 private final MessageSubject subject;
Madan Jampani53e44e62014-10-07 12:39:51 -070037 private final byte[] payload;
tom1d416c52014-09-29 20:55:24 -070038
39 /**
40 * Creates a cluster message.
41 *
Yuta HIGUCHI5c947272014-11-03 21:39:21 -080042 * @param sender message sender
tom1d416c52014-09-29 20:55:24 -070043 * @param subject message subject
Yuta HIGUCHI5c947272014-11-03 21:39:21 -080044 * @param payload message payload
tom1d416c52014-09-29 20:55:24 -070045 */
Madan Jampani53e44e62014-10-07 12:39:51 -070046 public ClusterMessage(NodeId sender, MessageSubject subject, byte[] payload) {
Madan Jampani890bc352014-10-01 22:35:29 -070047 this.sender = sender;
tom1d416c52014-09-29 20:55:24 -070048 this.subject = subject;
Madan Jampani890bc352014-10-01 22:35:29 -070049 this.payload = payload;
tom1d416c52014-09-29 20:55:24 -070050 }
51
52 /**
Madan Jampani890bc352014-10-01 22:35:29 -070053 * Returns the id of the controller sending this message.
54 *
55 * @return message sender id.
56 */
57 public NodeId sender() {
58 return sender;
59 }
60
61 /**
tom1d416c52014-09-29 20:55:24 -070062 * Returns the message subject indicator.
63 *
64 * @return message subject
65 */
66 public MessageSubject subject() {
67 return subject;
68 }
69
Madan Jampani890bc352014-10-01 22:35:29 -070070 /**
71 * Returns the message payload.
72 *
73 * @return message payload.
74 */
Madan Jampani53e44e62014-10-07 12:39:51 -070075 public byte[] payload() {
Madan Jampani890bc352014-10-01 22:35:29 -070076 return payload;
tom1d416c52014-09-29 20:55:24 -070077 }
Madan Jampani8a895092014-10-17 16:55:50 -070078
79 /**
80 * Sends a response to the sender.
81 *
82 * @param data payload response.
Yuta HIGUCHI5c947272014-11-03 21:39:21 -080083 * @throws IOException when I/O exception of some sort has occurred
Madan Jampani8a895092014-10-17 16:55:50 -070084 */
85 public void respond(byte[] data) throws IOException {
Jonathan Hart584d2f32015-01-27 19:46:14 -080086 throw new IllegalStateException("One can only respond to message received from others.");
Madan Jampani8a895092014-10-17 16:55:50 -070087 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080088
89 @Override
90 public String toString() {
91 return MoreObjects.toStringHelper(getClass())
92 .add("sender", sender)
93 .add("subject", subject)
94 .add("payload", ByteArraySizeHashPrinter.of(payload))
95 .toString();
96 }
Jonathan Hart584d2f32015-01-27 19:46:14 -080097
98 @Override
99 public boolean equals(Object o) {
100 if (!(o instanceof ClusterMessage)) {
101 return false;
102 }
103
104 ClusterMessage that = (ClusterMessage) o;
105
106 return Objects.equals(this.sender, that.sender) &&
107 Objects.equals(this.subject, that.subject) &&
108 Arrays.equals(this.payload, that.payload);
109 }
110
Madan Jampaniba472232015-03-04 13:00:50 -0800111 /**
112 * Serializes this instance.
113 * @return bytes
114 */
115 public byte[] getBytes() {
116 byte[] senderBytes = sender.toString().getBytes(Charsets.UTF_8);
117 byte[] subjectBytes = subject.value().getBytes(Charsets.UTF_8);
118 int capacity = 12 + senderBytes.length + subjectBytes.length + payload.length;
119 ByteBuffer buffer = ByteBuffer.allocate(capacity);
120 buffer.putInt(senderBytes.length);
121 buffer.put(senderBytes);
122 buffer.putInt(subjectBytes.length);
123 buffer.put(subjectBytes);
124 buffer.putInt(payload.length);
125 buffer.put(payload);
126 return buffer.array();
127 }
128
129 /**
130 * Decodes a new ClusterMessage from raw bytes.
131 * @param bytes raw bytes
132 * @return cluster message
133 */
134 public static ClusterMessage fromBytes(byte[] bytes) {
135 ByteBuffer buffer = ByteBuffer.wrap(bytes);
136 byte[] senderBytes = new byte[buffer.getInt()];
137 buffer.get(senderBytes);
138 byte[] subjectBytes = new byte[buffer.getInt()];
139 buffer.get(subjectBytes);
140 byte[] payloadBytes = new byte[buffer.getInt()];
141 buffer.get(payloadBytes);
142
143 return new ClusterMessage(new NodeId(new String(senderBytes, Charsets.UTF_8)),
Thomas Vachuskaff965232015-03-17 14:10:52 -0700144 new MessageSubject(new String(subjectBytes, Charsets.UTF_8)),
Madan Jampaniba472232015-03-04 13:00:50 -0800145 payloadBytes);
146 }
147
Jonathan Hart584d2f32015-01-27 19:46:14 -0800148 @Override
149 public int hashCode() {
150 return Objects.hash(sender, subject, payload);
151 }
tom1d416c52014-09-29 20:55:24 -0700152}