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 }