001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.zookeeper; 019 020import java.util.concurrent.ThreadLocalRandom; 021import org.apache.hadoop.hbase.util.Bytes; 022import org.apache.yetus.audience.InterfaceAudience; 023 024/** 025 * The metadata append to the start of data on zookeeper. 026 */ 027@InterfaceAudience.Private 028public class ZKMetadata { 029 030 private ZKMetadata() { 031 } 032 033 // The metadata attached to each piece of data has the format: 034 // <magic> 1-byte constant 035 // <id length> 4-byte big-endian integer (length of next field) 036 // <id> identifier corresponding uniquely to this process 037 // It is prepended to the data supplied by the user. 038 039 // the magic number is to be backward compatible 040 private static final byte MAGIC = (byte) 0XFF; 041 private static final int MAGIC_SIZE = Bytes.SIZEOF_BYTE; 042 private static final int ID_LENGTH_OFFSET = MAGIC_SIZE; 043 private static final int ID_LENGTH_SIZE = Bytes.SIZEOF_INT; 044 045 public static byte[] appendMetaData(byte[] id, byte[] data) { 046 if (data == null || data.length == 0) { 047 return data; 048 } 049 byte[] salt = Bytes.toBytes(ThreadLocalRandom.current().nextLong()); 050 int idLength = id.length + salt.length; 051 byte[] newData = new byte[MAGIC_SIZE + ID_LENGTH_SIZE + idLength + data.length]; 052 int pos = 0; 053 pos = Bytes.putByte(newData, pos, MAGIC); 054 pos = Bytes.putInt(newData, pos, idLength); 055 pos = Bytes.putBytes(newData, pos, id, 0, id.length); 056 pos = Bytes.putBytes(newData, pos, salt, 0, salt.length); 057 Bytes.putBytes(newData, pos, data, 0, data.length); 058 return newData; 059 } 060 061 public static byte[] removeMetaData(byte[] data) { 062 if (data == null || data.length == 0) { 063 return data; 064 } 065 // check the magic data; to be backward compatible 066 byte magic = data[0]; 067 if (magic != MAGIC) { 068 return data; 069 } 070 071 int idLength = Bytes.toInt(data, ID_LENGTH_OFFSET); 072 int dataLength = data.length - MAGIC_SIZE - ID_LENGTH_SIZE - idLength; 073 int dataOffset = MAGIC_SIZE + ID_LENGTH_SIZE + idLength; 074 075 byte[] newData = new byte[dataLength]; 076 System.arraycopy(data, dataOffset, newData, 0, dataLength); 077 return newData; 078 } 079}