/* * Copyright Terracotta, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.ehcache.clustered.common.internal.messages; import org.ehcache.clustered.common.ServerSideConfiguration; import org.ehcache.clustered.common.internal.ServerStoreConfiguration; import org.terracotta.runnel.Struct; import org.terracotta.runnel.StructBuilder; import org.terracotta.runnel.decoding.StructDecoder; import org.terracotta.runnel.encoding.StructEncoder; import java.nio.ByteBuffer; import java.util.UUID; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.EHCACHE_MESSAGE_TYPES_ENUM_MAPPING; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_INDEX; import static org.ehcache.clustered.common.internal.messages.EhcacheMessageType.MESSAGE_TYPE_FIELD_NAME; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.LSB_UUID_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.MSB_UUID_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.MSG_ID_FIELD; import static org.ehcache.clustered.common.internal.messages.MessageCodecUtils.SERVER_STORE_NAME_FIELD; import static org.terracotta.runnel.StructBuilder.newStructBuilder; public class LifeCycleMessageCodec { private static final String CONFIG_PRESENT_FIELD = "configPresent"; private final StructBuilder VALIDATE_MESSAGE_STRUCT_BUILDER_PREFIX = newStructBuilder() .enm(MESSAGE_TYPE_FIELD_NAME, MESSAGE_TYPE_FIELD_INDEX, EHCACHE_MESSAGE_TYPES_ENUM_MAPPING) .int64(MSG_ID_FIELD, 15) .int64(MSB_UUID_FIELD, 20) .int64(LSB_UUID_FIELD, 21) .bool(CONFIG_PRESENT_FIELD, 30); private static final int CONFIGURE_MESSAGE_NEXT_INDEX = 40; private final StructBuilder VALIDATE_STORE_MESSAGE_STRUCT_BUILDER_PREFIX = newStructBuilder() .enm(MESSAGE_TYPE_FIELD_NAME, MESSAGE_TYPE_FIELD_INDEX, EHCACHE_MESSAGE_TYPES_ENUM_MAPPING) .int64(MSG_ID_FIELD, 15) .int64(MSB_UUID_FIELD, 20) .int64(LSB_UUID_FIELD, 21) .string(SERVER_STORE_NAME_FIELD, 30); private static final int VALIDATE_STORE_NEXT_INDEX = 40; private final Struct PREPARE_FOR_DESTROY_STRUCT = newStructBuilder() .enm(MESSAGE_TYPE_FIELD_NAME, MESSAGE_TYPE_FIELD_INDEX, EHCACHE_MESSAGE_TYPES_ENUM_MAPPING) .build(); private final Struct validateMessageStruct; private final Struct validateStoreMessageStruct; private final MessageCodecUtils messageCodecUtils; private final ConfigCodec configCodec; public LifeCycleMessageCodec(ConfigCodec configCodec) { this.messageCodecUtils = new MessageCodecUtils(); this.configCodec = configCodec; validateMessageStruct = this.configCodec.injectServerSideConfiguration( VALIDATE_MESSAGE_STRUCT_BUILDER_PREFIX, CONFIGURE_MESSAGE_NEXT_INDEX).getUpdatedBuilder().build(); validateStoreMessageStruct = this.configCodec.injectServerStoreConfiguration( VALIDATE_STORE_MESSAGE_STRUCT_BUILDER_PREFIX, VALIDATE_STORE_NEXT_INDEX).getUpdatedBuilder().build(); } public byte[] encode(LifecycleMessage message) { switch (message.getMessageType()) { case VALIDATE: return encodeTierManagerValidateMessage((LifecycleMessage.ValidateStoreManager) message); case VALIDATE_SERVER_STORE: return encodeValidateStoreMessage((LifecycleMessage.ValidateServerStore) message); case PREPARE_FOR_DESTROY: return encodePrepareForDestroyMessage(message); default: throw new IllegalArgumentException("Unknown lifecycle message: " + message.getClass()); } } private byte[] encodePrepareForDestroyMessage(LifecycleMessage message) { return PREPARE_FOR_DESTROY_STRUCT.encoder() .enm(MESSAGE_TYPE_FIELD_NAME, message.getMessageType()) .encode().array(); } private byte[] encodeValidateStoreMessage(LifecycleMessage.ValidateServerStore message) { StructEncoder<Void> encoder = validateStoreMessageStruct.encoder(); messageCodecUtils.encodeMandatoryFields(encoder, message); encoder.string(SERVER_STORE_NAME_FIELD, message.getName()); configCodec.encodeServerStoreConfiguration(encoder, message.getStoreConfiguration()); return encoder.encode().array(); } private byte[] encodeTierManagerValidateMessage(LifecycleMessage.ValidateStoreManager message) { StructEncoder<Void> encoder = validateMessageStruct.encoder(); ServerSideConfiguration config = message.getConfiguration(); messageCodecUtils.encodeMandatoryFields(encoder, message); if (config == null) { encoder.bool(CONFIG_PRESENT_FIELD, false); } else { encoder.bool(CONFIG_PRESENT_FIELD, true); configCodec.encodeServerSideConfiguration(encoder, config); } return encoder.encode().array(); } public EhcacheEntityMessage decode(EhcacheMessageType messageType, ByteBuffer messageBuffer) { switch (messageType) { case VALIDATE: return decodeValidateMessage(messageBuffer); case VALIDATE_SERVER_STORE: return decodeValidateServerStoreMessage(messageBuffer); case PREPARE_FOR_DESTROY: return decodePrepareForDestroyMessage(); } throw new IllegalArgumentException("LifeCycleMessage operation not defined for : " + messageType); } private LifecycleMessage.PrepareForDestroy decodePrepareForDestroyMessage() { return new LifecycleMessage.PrepareForDestroy(); } private LifecycleMessage.ValidateServerStore decodeValidateServerStoreMessage(ByteBuffer messageBuffer) { StructDecoder<Void> decoder = validateStoreMessageStruct.decoder(messageBuffer); Long msgId = decoder.int64(MSG_ID_FIELD); UUID cliendId = messageCodecUtils.decodeUUID(decoder); String storeName = decoder.string(SERVER_STORE_NAME_FIELD); ServerStoreConfiguration config = configCodec.decodeServerStoreConfiguration(decoder); LifecycleMessage.ValidateServerStore message = new LifecycleMessage.ValidateServerStore(storeName, config, cliendId); message.setId(msgId); return message; } private LifecycleMessage.ValidateStoreManager decodeValidateMessage(ByteBuffer messageBuffer) { StructDecoder<Void> decoder = validateMessageStruct.decoder(messageBuffer); Long msgId = decoder.int64(MSG_ID_FIELD); UUID cliendId = messageCodecUtils.decodeUUID(decoder); boolean configPresent = decoder.bool(CONFIG_PRESENT_FIELD); ServerSideConfiguration config = null; if (configPresent) { config = configCodec.decodeServerSideConfiguration(decoder); } LifecycleMessage.ValidateStoreManager message = new LifecycleMessage.ValidateStoreManager(config, cliendId); if (msgId != null) { message.setId(msgId); } return message; } }