/*
* Copyright 2016 Naver Corp.
*
* Licensed 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 com.navercorp.pinpoint.common.server.bo.serializer.stat;
import com.navercorp.pinpoint.common.server.bo.serializer.HbaseSerializer;
import com.navercorp.pinpoint.common.server.bo.stat.AgentStatDataPoint;
import com.navercorp.pinpoint.common.server.bo.stat.AgentStatType;
import com.sematext.hbase.wd.AbstractRowKeyDistributor;
import org.apache.commons.collections.CollectionUtils;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Scan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import static com.navercorp.pinpoint.common.hbase.HBaseTables.AGENT_STAT_TIMESPAN_MS;
/**
* @author HyunGil Jeong
*/
@Component
public class AgentStatHbaseOperationFactory {
private final AgentStatRowKeyEncoder rowKeyEncoder;
private final AgentStatRowKeyDecoder rowKeyDecoder;
private final AbstractRowKeyDistributor rowKeyDistributor;
@Autowired
public AgentStatHbaseOperationFactory(
AgentStatRowKeyEncoder rowKeyEncoder,
AgentStatRowKeyDecoder rowKeyDecoder,
@Qualifier("agentStatV2RowKeyDistributor") AbstractRowKeyDistributor rowKeyDistributor) {
Assert.notNull(rowKeyEncoder, "rowKeyEncoder must not be null");
Assert.notNull(rowKeyDecoder, "rowKeyDecoder must not be null");
Assert.notNull(rowKeyDistributor, "rowKeyDistributor must not be null");
this.rowKeyEncoder = rowKeyEncoder;
this.rowKeyDecoder = rowKeyDecoder;
this.rowKeyDistributor = rowKeyDistributor;
}
public <T extends AgentStatDataPoint> List<Put> createPuts(String agentId, AgentStatType agentStatType, List<T> agentStatDataPoints, HbaseSerializer<List<T>, Put> agentStatSerializer) {
if (CollectionUtils.isEmpty(agentStatDataPoints)) {
return Collections.emptyList();
}
Map<Long, List<T>> timeslots = slotAgentStatDataPoints(agentStatDataPoints);
List<Put> puts = new ArrayList<Put>();
for (Map.Entry<Long, List<T>> timeslot : timeslots.entrySet()) {
long baseTimestamp = timeslot.getKey();
List<T> slottedAgentStatDataPoints = timeslot.getValue();
final AgentStatRowKeyComponent rowKeyComponent = new AgentStatRowKeyComponent(agentId, agentStatType, baseTimestamp);
byte[] rowKey = this.rowKeyEncoder.encodeRowKey(rowKeyComponent);
byte[] distributedRowKey = this.rowKeyDistributor.getDistributedKey(rowKey);
Put put = new Put(distributedRowKey);
agentStatSerializer.serialize(slottedAgentStatDataPoints, put, null);
puts.add(put);
}
return puts;
}
public Scan createScan(String agentId, AgentStatType agentStatType, long startTimestamp, long endTimestamp) {
final AgentStatRowKeyComponent startRowKeyComponent = new AgentStatRowKeyComponent(agentId, agentStatType, AgentStatUtils.getBaseTimestamp(endTimestamp));
final AgentStatRowKeyComponent endRowKeyComponenet = new AgentStatRowKeyComponent(agentId, agentStatType, AgentStatUtils.getBaseTimestamp(startTimestamp) - AGENT_STAT_TIMESPAN_MS);
byte[] startRowKey = this.rowKeyEncoder.encodeRowKey(startRowKeyComponent);
byte[] endRowKey = this.rowKeyEncoder.encodeRowKey(endRowKeyComponenet);
return new Scan(startRowKey, endRowKey);
}
public AbstractRowKeyDistributor getRowKeyDistributor() {
return this.rowKeyDistributor;
}
public String getAgentId(byte[] distributedRowKey) {
byte[] originalRowKey = this.rowKeyDistributor.getOriginalKey(distributedRowKey);
return this.rowKeyDecoder.decodeRowKey(originalRowKey).getAgentId();
}
public AgentStatType getAgentStatType(byte[] distributedRowKey) {
byte[] originalRowKey = this.rowKeyDistributor.getOriginalKey(distributedRowKey);
return this.rowKeyDecoder.decodeRowKey(originalRowKey).getAgentStatType();
}
public long getBaseTimestamp(byte[] distributedRowKey) {
byte[] originalRowKey = this.rowKeyDistributor.getOriginalKey(distributedRowKey);
return this.rowKeyDecoder.decodeRowKey(originalRowKey).getBaseTimestamp();
}
private <T extends AgentStatDataPoint> Map<Long, List<T>> slotAgentStatDataPoints(List<T> agentStatDataPoints) {
Map<Long, List<T>> timeslots = new TreeMap<Long, List<T>>();
for (T agentStatDataPoint : agentStatDataPoints) {
long timestamp = agentStatDataPoint.getTimestamp();
long timeslot = AgentStatUtils.getBaseTimestamp(timestamp);
List<T> slottedDataPoints = timeslots.get(timeslot);
if (slottedDataPoints == null) {
slottedDataPoints = new ArrayList<T>();
timeslots.put(timeslot, slottedDataPoints);
}
slottedDataPoints.add(agentStatDataPoint);
}
return timeslots;
}
}