| /** |
| * 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.nfs.nfs3; |
| |
| import java.nio.ByteBuffer; |
| import java.nio.charset.StandardCharsets; |
| import java.security.MessageDigest; |
| import java.security.NoSuchAlgorithmException; |
| import java.util.Arrays; |
| |
| import org.apache.hadoop.oncrpc.XDR; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * This is a file handle use by the NFS clients. |
| * Server returns this handle to the client, which is used by the client |
| * on subsequent operations to reference the file. |
| */ |
| public class FileHandle { |
| private static final Logger LOG = LoggerFactory.getLogger(FileHandle.class); |
| private static final String HEXES = "0123456789abcdef"; |
| private static final int HANDLE_LEN = 32; |
| private byte[] handle; // Opaque handle |
| private long fileId = -1; |
| |
| public FileHandle() { |
| handle = null; |
| } |
| |
| /** |
| * Handle is a 32 bytes number. For HDFS, the last 8 bytes is fileId. |
| * @param v file id |
| */ |
| public FileHandle(long v) { |
| fileId = v; |
| handle = new byte[HANDLE_LEN]; |
| handle[0] = (byte)(v >>> 56); |
| handle[1] = (byte)(v >>> 48); |
| handle[2] = (byte)(v >>> 40); |
| handle[3] = (byte)(v >>> 32); |
| handle[4] = (byte)(v >>> 24); |
| handle[5] = (byte)(v >>> 16); |
| handle[6] = (byte)(v >>> 8); |
| handle[7] = (byte)(v >>> 0); |
| for (int i = 8; i < HANDLE_LEN; i++) { |
| handle[i] = (byte) 0; |
| } |
| } |
| |
| public FileHandle(String s) { |
| MessageDigest digest; |
| try { |
| digest = MessageDigest.getInstance("MD5"); |
| handle = new byte[HANDLE_LEN]; |
| } catch (NoSuchAlgorithmException e) { |
| LOG.warn("MD5 MessageDigest unavailable."); |
| handle = null; |
| return; |
| } |
| |
| byte[] in = s.getBytes(StandardCharsets.UTF_8); |
| digest.update(in); |
| |
| byte[] digestbytes = digest.digest(); |
| for (int i = 0; i < 16; i++) { |
| handle[i] = (byte) 0; |
| } |
| |
| for (int i = 16; i < 32; i++) { |
| handle[i] = digestbytes[i - 16]; |
| } |
| } |
| |
| public boolean serialize(XDR out) { |
| out.writeInt(handle.length); |
| out.writeFixedOpaque(handle); |
| return true; |
| } |
| |
| private long bytesToLong(byte[] data) { |
| ByteBuffer buffer = ByteBuffer.allocate(8); |
| for (int i = 0; i < 8; i++) { |
| buffer.put(data[i]); |
| } |
| buffer.flip();// need flip |
| return buffer.getLong(); |
| } |
| |
| public boolean deserialize(XDR xdr) { |
| if (!XDR.verifyLength(xdr, 32)) { |
| return false; |
| } |
| int size = xdr.readInt(); |
| handle = xdr.readFixedOpaque(size); |
| fileId = bytesToLong(handle); |
| return true; |
| } |
| |
| private static String hex(byte b) { |
| StringBuilder strBuilder = new StringBuilder(); |
| strBuilder.append(HEXES.charAt((b & 0xF0) >> 4)).append( |
| HEXES.charAt((b & 0x0F))); |
| return strBuilder.toString(); |
| } |
| |
| public long getFileId() { |
| return fileId; |
| } |
| |
| public byte[] getContent() { |
| return handle.clone(); |
| } |
| |
| @Override |
| public String toString() { |
| StringBuilder s = new StringBuilder(); |
| for (int i = 0; i < handle.length; i++) { |
| s.append(hex(handle[i])); |
| } |
| return s.toString(); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) { |
| return true; |
| } |
| |
| if (!(o instanceof FileHandle)) { |
| return false; |
| } |
| |
| FileHandle h = (FileHandle) o; |
| return Arrays.equals(handle, h.handle); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Arrays.hashCode(handle); |
| } |
| } |