/** * 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.hadoop.yarn.server.applicationhistoryservice.timeline; import java.io.IOException; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectReader; import org.codehaus.jackson.map.ObjectWriter; /** * A utility class providing methods for serializing and deserializing * objects. The {@link #write(Object)} and {@link #read(byte[])} methods are * used by the {@link LeveldbTimelineStore} to store and retrieve arbitrary * JSON, while the {@link #writeReverseOrderedLong} and {@link * #readReverseOrderedLong} methods are used to sort entities in descending * start time order. */ @InterfaceAudience.Private @InterfaceStability.Unstable public class GenericObjectMapper { private static final byte[] EMPTY_BYTES = new byte[0]; public static final ObjectReader OBJECT_READER; public static final ObjectWriter OBJECT_WRITER; static { ObjectMapper mapper = new ObjectMapper(); OBJECT_READER = mapper.reader(Object.class); OBJECT_WRITER = mapper.writer(); } /** * Serializes an Object into a byte array. Along with {@link #read(byte[])}, * can be used to serialize an Object and deserialize it into an Object of * the same type without needing to specify the Object's type, * as long as it is one of the JSON-compatible objects understood by * ObjectMapper. * * @param o An Object * @return A byte array representation of the Object * @throws IOException if there is a write error */ public static byte[] write(Object o) throws IOException { if (o == null) { return EMPTY_BYTES; } return OBJECT_WRITER.writeValueAsBytes(o); } /** * Deserializes an Object from a byte array created with * {@link #write(Object)}. * * @param b A byte array * @return An Object * @throws IOException if there is a read error */ public static Object read(byte[] b) throws IOException { return read(b, 0); } /** * Deserializes an Object from a byte array at a specified offset, assuming * the bytes were created with {@link #write(Object)}. * * @param b A byte array * @param offset Offset into the array * @return An Object * @throws IOException if there is a read error */ public static Object read(byte[] b, int offset) throws IOException { if (b == null || b.length == 0) { return null; } return OBJECT_READER.readValue(b, offset, b.length - offset); } /** * Converts a long to a 8-byte array so that lexicographic ordering of the * produced byte arrays sort the longs in descending order. * * @param l A long * @return A byte array */ public static byte[] writeReverseOrderedLong(long l) { byte[] b = new byte[8]; return writeReverseOrderedLong(l, b, 0); } public static byte[] writeReverseOrderedLong(long l, byte[] b, int offset) { b[offset] = (byte)(0x7f ^ ((l >> 56) & 0xff)); for (int i = offset+1; i < offset+7; i++) { b[i] = (byte)(0xff ^ ((l >> 8*(7-i)) & 0xff)); } b[offset+7] = (byte)(0xff ^ (l & 0xff)); return b; } /** * Reads 8 bytes from an array starting at the specified offset and * converts them to a long. The bytes are assumed to have been created * with {@link #writeReverseOrderedLong}. * * @param b A byte array * @param offset An offset into the byte array * @return A long */ public static long readReverseOrderedLong(byte[] b, int offset) { long l = b[offset] & 0xff; for (int i = 1; i < 8; i++) { l = l << 8; l = l | (b[offset+i]&0xff); } return l ^ 0x7fffffffffffffffl; } }