All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.rocketmq.client.java.message.MessageIdCodec Maven / Gradle / Ivy

There is a newer version: 5.0.7
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.rocketmq.client.java.message;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.rocketmq.client.apis.message.MessageId;
import org.apache.rocketmq.client.java.misc.Utilities;

/**
 * The codec for the message-id.
 *
 * 

Codec here provides the following two functions: * 1. Provide decoding function of message-id of all versions above v0. * 2. Provide a generator of message-id of v1 version. * *

The message-id of versions above V1 consists of 17 bytes in total. The first two bytes represent the version * number. For V1, these two bytes are 0x0001. * *

V1 message id example

* *
 * ┌──┬────────────┬────┬────────┬────────┐
 * │01│56F7E71C361B│21BC│024CCDBE│00000000│
 * └──┴────────────┴────┴────────┴────────┘
 * 
* *

V1 version message id generation rules

* *
 *                     process id(lower 2bytes)
 *                             ▲
 * mac address(lower 6bytes)   │   sequence number(big endian)
 *                    ▲        │          ▲ (4bytes)
 *                    │        │          │
 *              ┌─────┴─────┐ ┌┴┐ ┌───┐ ┌─┴─┐
 *       0x01+  │     6     │ │2│ │ 4 │ │ 4 │
 *              └───────────┘ └─┘ └─┬─┘ └───┘
 *                                  │
 *                                  ▼
 *           seconds since 2021-01-01 00:00:00(UTC+0)
 *                         (lower 4bytes)
 * 
*/ public class MessageIdCodec { public static final int MESSAGE_ID_LENGTH_FOR_V1_OR_LATER = 34; public static final String MESSAGE_ID_VERSION_V0 = "00"; public static final String MESSAGE_ID_VERSION_V1 = "01"; private static final MessageIdCodec INSTANCE = new MessageIdCodec(); private final String processFixedStringV1; private final long secondsSinceCustomEpoch; private final long secondsStartTimestamp; private long seconds; private final AtomicInteger sequence; private MessageIdCodec() { ByteBuffer buffer = ByteBuffer.allocate(8); buffer.order(ByteOrder.BIG_ENDIAN); byte[] prefix0 = Utilities.macAddress(); buffer.put(prefix0, 0, 6); ByteBuffer pidBuffer = ByteBuffer.allocate(4); pidBuffer.order(ByteOrder.BIG_ENDIAN); final int pid = Utilities.processId(); pidBuffer.putInt(pid); // Copy the lower 2 bytes buffer.put(pidBuffer.array(), 2, 2); buffer.flip(); processFixedStringV1 = Utilities.encodeHexString(buffer, false); secondsSinceCustomEpoch = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - customEpochMillis()); secondsStartTimestamp = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime()); seconds = deltaSeconds(); sequence = new AtomicInteger(0); } public static MessageIdCodec getInstance() { return INSTANCE; } private long customEpochMillis() { // 2021-01-01 00:00:00 final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Etc/UTC")); calendar.set(Calendar.YEAR, 2021); calendar.set(Calendar.MONTH, Calendar.JANUARY); calendar.set(Calendar.DAY_OF_MONTH, 1); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); return calendar.getTime().getTime(); } private long deltaSeconds() { return TimeUnit.NANOSECONDS.toSeconds(System.nanoTime()) - secondsStartTimestamp + secondsSinceCustomEpoch; } public MessageId nextMessageId() { ByteBuffer buffer = ByteBuffer.allocate(8); buffer.order(ByteOrder.BIG_ENDIAN); final ByteBuffer deltaSecondsBuffer = ByteBuffer.allocate(8); deltaSecondsBuffer.order(ByteOrder.BIG_ENDIAN); final long deltaSeconds = deltaSeconds(); if (seconds != deltaSeconds) { seconds = deltaSeconds; } deltaSecondsBuffer.putLong(seconds); buffer.put(deltaSecondsBuffer.array(), 4, 4); buffer.putInt(sequence.getAndIncrement()); buffer.flip(); final String suffix = processFixedStringV1 + Utilities.encodeHexString(buffer, false); return new MessageIdImpl(MESSAGE_ID_VERSION_V1, suffix); } public MessageId decode(String messageId) { if (MESSAGE_ID_LENGTH_FOR_V1_OR_LATER != messageId.length()) { return new MessageIdImpl(MESSAGE_ID_VERSION_V0, messageId); } return new MessageIdImpl(messageId.substring(0, 2), messageId.substring(2)); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy