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