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