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.regionserver; 019 020import java.io.IOException; 021import java.util.Collection; 022import java.util.List; 023import java.util.Map; 024import java.util.NavigableMap; 025import java.util.TreeMap; 026 027import org.apache.hadoop.hbase.Cell; 028import org.apache.yetus.audience.InterfaceAudience; 029 030/** 031 * class for cell sink that separates the provided cells into multiple files for date tiered 032 * compaction. 033 */ 034@InterfaceAudience.Private 035public class DateTieredMultiFileWriter extends AbstractMultiFileWriter { 036 037 private final NavigableMap<Long, StoreFileWriter> lowerBoundary2Writer = new TreeMap<>(); 038 039 private final boolean needEmptyFile; 040 041 private final Map<Long, String> lowerBoundariesPolicies; 042 043 /** 044 * @param lowerBoundariesPolicies each window to storage policy map. 045 * @param needEmptyFile whether need to create an empty store file if we haven't written out 046 * anything. 047 */ 048 public DateTieredMultiFileWriter(List<Long> lowerBoundaries, 049 Map<Long, String> lowerBoundariesPolicies, boolean needEmptyFile) { 050 for (Long lowerBoundary : lowerBoundaries) { 051 lowerBoundary2Writer.put(lowerBoundary, null); 052 } 053 this.needEmptyFile = needEmptyFile; 054 this.lowerBoundariesPolicies = lowerBoundariesPolicies; 055 } 056 057 @Override 058 public void append(Cell cell) throws IOException { 059 Map.Entry<Long, StoreFileWriter> entry = lowerBoundary2Writer.floorEntry(cell.getTimestamp()); 060 StoreFileWriter writer = entry.getValue(); 061 if (writer == null) { 062 String lowerBoundaryStoragePolicy = lowerBoundariesPolicies.get(entry.getKey()); 063 if (lowerBoundaryStoragePolicy != null) { 064 writer = writerFactory.createWriterWithStoragePolicy(lowerBoundaryStoragePolicy); 065 } else { 066 writer = writerFactory.createWriter(); 067 } 068 lowerBoundary2Writer.put(entry.getKey(), writer); 069 } 070 writer.append(cell); 071 } 072 073 @Override 074 protected Collection<StoreFileWriter> writers() { 075 return lowerBoundary2Writer.values(); 076 } 077 078 @Override 079 protected void preCommitWriters() throws IOException { 080 if (!needEmptyFile) { 081 return; 082 } 083 for (StoreFileWriter writer : lowerBoundary2Writer.values()) { 084 if (writer != null) { 085 return; 086 } 087 } 088 // we haven't written out any data, create an empty file to retain metadata 089 lowerBoundary2Writer.put(lowerBoundary2Writer.firstKey(), writerFactory.createWriter()); 090 } 091}