1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.giraph.writable.kryo; 19 20 import java.io.DataInput; 21 import java.io.DataOutput; 22 import java.io.IOException; 23 24 import org.apache.giraph.utils.WritableUtils; 25 import org.apache.hadoop.io.Writable; 26 27 /** 28 * Generic wrapper object, making any object writable. 29 * 30 * Uses Kryo inside for serialization. 31 * Current configuration is not optimized for performance, 32 * but Writable interface doesn't allow much room for it. 33 * 34 * Note - Java8 lambdas need to implement Serializable to work. 35 * 36 * @param <T> Object type 37 */ 38 public class KryoWritableWrapper<T> implements Writable { 39 /** Wrapped object */ 40 private T object; 41 42 /** 43 * Create wrapper given an object. 44 * @param object Object instance 45 */ 46 public KryoWritableWrapper(T object) { 47 this.object = object; 48 } 49 50 /** 51 * Creates wrapper initialized with null. 52 */ 53 public KryoWritableWrapper() { 54 } 55 56 /** 57 * Unwrap the object value 58 * @return Object value 59 */ 60 public T get() { 61 return object; 62 } 63 64 /** 65 * Set wrapped object value 66 * @param object New object value 67 */ 68 public void set(T object) { 69 this.object = object; 70 } 71 72 @Override 73 public void readFields(DataInput in) throws java.io.IOException { 74 object = HadoopKryo.readClassAndObj(in); 75 } 76 77 @Override 78 public void write(DataOutput out) throws IOException { 79 HadoopKryo.writeClassAndObj(out, object); 80 } 81 82 /** 83 * Returns Writable instance, wrapping given object only 84 * if it is not already writable. 85 * 86 * @param object Object to potentially wrap 87 * @return Writable object holding argument 88 */ 89 public static Writable wrapIfNeeded(Object object) { 90 if (object instanceof Writable) { 91 return (Writable) object; 92 } else { 93 return new KryoWritableWrapper<>(object); 94 } 95 } 96 97 /** 98 * Unwrap Writable object if it was wrapped initially, 99 * inverse of wrapIfNeeded function. 100 * @param value Potentially wrapped value 101 * @return Original unwrapped value 102 * @param <T> Type of returned object. 103 */ 104 public static <T> T unwrapIfNeeded(Writable value) { 105 if (value instanceof KryoWritableWrapper) { 106 return ((KryoWritableWrapper<T>) value).get(); 107 } else { 108 return (T) value; 109 } 110 } 111 112 /** 113 * Wrap object with KryoWritableWrapper, create a writable copy of it, 114 * and then unwrap it, allowing any object to be copied. 115 * 116 * @param object Object to copy 117 * @return copy of the object 118 * @param <T> Type of the object 119 */ 120 public static <T> T wrapAndCopy(T object) { 121 return WritableUtils.createCopy(new KryoWritableWrapper<>(object)).get(); 122 } 123 124 /** 125 * Converting the object to byte array. 126 * @param object Object 127 * @param <T> Type 128 * @return byte array 129 */ 130 public static <T> byte [] convertToByteArray(T object) { 131 KryoWritableWrapper<T> wrapper = 132 new KryoWritableWrapper<>(object); 133 return WritableUtils.toByteArray(wrapper); 134 } 135 136 /** 137 * Converting from byte array 138 * @param arr byte array 139 * @param <T> type 140 * @return original object 141 */ 142 public static <T> T convertFromByteArray(byte [] arr) { 143 KryoWritableWrapper<T> wrapper = 144 new KryoWritableWrapper<>(); 145 WritableUtils.fromByteArray(arr, wrapper); 146 return wrapper.get(); 147 } 148 }