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; 021 022import org.apache.hadoop.hbase.util.Bytes; 023import org.apache.yetus.audience.InterfaceAudience; 024 025/** 026 * The metadata append to the start of data on zookeeper. 027 */ 028@InterfaceAudience.Private 029public class ZKMetadata { 030 031 private ZKMetadata() { 032 } 033 034 // The metadata attached to each piece of data has the format: 035 // <magic> 1-byte constant 036 // <id length> 4-byte big-endian integer (length of next field) 037 // <id> identifier corresponding uniquely to this process 038 // It is prepended to the data supplied by the user. 039 040 // the magic number is to be backward compatible 041 private static final byte MAGIC = (byte) 0XFF; 042 private static final int MAGIC_SIZE = Bytes.SIZEOF_BYTE; 043 private static final int ID_LENGTH_OFFSET = MAGIC_SIZE; 044 private static final int ID_LENGTH_SIZE = Bytes.SIZEOF_INT; 045 046 public static byte[] appendMetaData(byte[] id, byte[] data) { 047 if (data == null || data.length == 0) { 048 return data; 049 } 050 byte[] salt = Bytes.toBytes(ThreadLocalRandom.current().nextLong()); 051 int idLength = id.length + salt.length; 052 byte[] newData = new byte[MAGIC_SIZE + ID_LENGTH_SIZE + idLength + data.length]; 053 int pos = 0; 054 pos = Bytes.putByte(newData, pos, MAGIC); 055 pos = Bytes.putInt(newData, pos, idLength); 056 pos = Bytes.putBytes(newData, pos, id, 0, id.length); 057 pos = Bytes.putBytes(newData, pos, salt, 0, salt.length); 058 pos = Bytes.putBytes(newData, pos, data, 0, data.length); 059 return newData; 060 } 061 062 public static byte[] removeMetaData(byte[] data) { 063 if (data == null || data.length == 0) { 064 return data; 065 } 066 // check the magic data; to be backward compatible 067 byte magic = data[0]; 068 if (magic != MAGIC) { 069 return data; 070 } 071 072 int idLength = Bytes.toInt(data, ID_LENGTH_OFFSET); 073 int dataLength = data.length - MAGIC_SIZE - ID_LENGTH_SIZE - idLength; 074 int dataOffset = MAGIC_SIZE + ID_LENGTH_SIZE + idLength; 075 076 byte[] newData = new byte[dataLength]; 077 System.arraycopy(data, dataOffset, newData, 0, dataLength); 078 return newData; 079 } 080}