001/* 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020package org.apache.hadoop.hbase.client; 021 022import java.util.Collections; 023import java.util.HashMap; 024import java.util.Map; 025import java.util.TreeMap; 026import java.util.stream.Collectors; 027import org.apache.hadoop.hbase.HConstants; 028import org.apache.hadoop.hbase.util.Bytes; 029import org.apache.hadoop.hbase.util.ClassSize; 030import org.apache.yetus.audience.InterfaceAudience; 031 032@InterfaceAudience.Public 033public abstract class OperationWithAttributes extends Operation implements Attributes { 034 // An opaque blob of attributes 035 private Map<String, byte[]> attributes; 036 037 // used for uniquely identifying an operation 038 public static final String ID_ATRIBUTE = "_operation.attributes.id"; 039 private int priority = HConstants.PRIORITY_UNSET; 040 041 /** 042 * empty construction. 043 * We need this empty construction to keep binary compatibility. 044 */ 045 protected OperationWithAttributes() { 046 } 047 048 protected OperationWithAttributes(OperationWithAttributes clone) { 049 this.attributes = clone.getAttributesMap() == null ? null : 050 clone.getAttributesMap().entrySet().stream() 051 .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue(), (k, v) -> { 052 throw new RuntimeException("collisions!!!"); 053 }, () -> new TreeMap<>())); 054 this.priority = clone.getPriority(); 055 } 056 057 @Override 058 public OperationWithAttributes setAttribute(String name, byte[] value) { 059 if (attributes == null && value == null) { 060 return this; 061 } 062 063 if (attributes == null) { 064 attributes = new HashMap<>(); 065 } 066 067 if (value == null) { 068 attributes.remove(name); 069 if (attributes.isEmpty()) { 070 this.attributes = null; 071 } 072 } else { 073 attributes.put(name, value); 074 } 075 return this; 076 } 077 078 @Override 079 public byte[] getAttribute(String name) { 080 if (attributes == null) { 081 return null; 082 } 083 084 return attributes.get(name); 085 } 086 087 @Override 088 public Map<String, byte[]> getAttributesMap() { 089 if (attributes == null) { 090 return Collections.emptyMap(); 091 } 092 return Collections.unmodifiableMap(attributes); 093 } 094 095 protected long getAttributeSize() { 096 long size = 0; 097 if (attributes != null) { 098 size += ClassSize.align(this.attributes.size() * ClassSize.MAP_ENTRY); 099 for(Map.Entry<String, byte[]> entry : this.attributes.entrySet()) { 100 size += ClassSize.align(ClassSize.STRING + entry.getKey().length()); 101 size += ClassSize.align(ClassSize.ARRAY + entry.getValue().length); 102 } 103 } 104 return size; 105 } 106 107 /** 108 * This method allows you to set an identifier on an operation. The original 109 * motivation for this was to allow the identifier to be used in slow query 110 * logging, but this could obviously be useful in other places. One use of 111 * this could be to put a class.method identifier in here to see where the 112 * slow query is coming from. 113 * @param id 114 * id to set for the scan 115 */ 116 public OperationWithAttributes setId(String id) { 117 setAttribute(ID_ATRIBUTE, Bytes.toBytes(id)); 118 return this; 119 } 120 121 /** 122 * This method allows you to retrieve the identifier for the operation if one 123 * was set. 124 * @return the id or null if not set 125 */ 126 public String getId() { 127 byte[] attr = getAttribute(ID_ATRIBUTE); 128 return attr == null? null: Bytes.toString(attr); 129 } 130 131 public OperationWithAttributes setPriority(int priority) { 132 this.priority = priority; 133 return this; 134 } 135 136 public int getPriority() { 137 return priority; 138 } 139 140}