package com.ctriposs.tsdb.storage; import java.io.File; import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicLong; import com.ctriposs.tsdb.InternalKey; import com.ctriposs.tsdb.common.IStorage; public class DBWriter { private IStorage storage; private long timeCount = 0; private long timeIndex = 0; private InternalKey smallest = null; private InternalKey largest = null; private AtomicLong valueOffset = null; private AtomicLong timeOffset = null; private long fileNumber; private Map<Integer,CodeItem> codeMap = new LinkedHashMap<Integer,CodeItem>(); public DBWriter(IStorage storage, long timeCount, long fileNumber) { this.storage = storage; this.timeCount = timeCount; this.valueOffset = new AtomicLong(Head.HEAD_SIZE + TimeItem.TIME_ITEM_SIZE * timeCount); this.timeOffset = new AtomicLong(Head.HEAD_SIZE); this.fileNumber = fileNumber; } public void add(InternalKey key, byte[] value)throws IOException { ++timeIndex; if(timeIndex == 1) { smallest = key; } if(timeIndex > timeCount){ throw new IOException("add item over timecount"); } largest = key; // write time item long tOffset = timeOffset.getAndAdd(TimeItem.TIME_ITEM_SIZE); long vOffset = valueOffset.getAndAdd(value.length); storage.put(tOffset, key.toTimeItemByte(value.length, vOffset)); // write value item storage.put(vOffset, value); //record start time offset when code change CodeItem codeItem = codeMap.get(key.getCode()); if (codeItem == null) { codeItem = new CodeItem(key.getCode(), tOffset, key.getTime(), key.getTime()); codeMap.put(key.getCode(), codeItem); } codeItem.addTimeItem(key.getTime()); } private void writeCodeArea()throws IOException { for(Entry<Integer,CodeItem> entry: codeMap.entrySet()){ long cOffset = valueOffset.getAndAdd(CodeItem.CODE_ITEM_SIZE); storage.put(cOffset, entry.getValue().toByte()); } } private void writeHead(long codeOffset,int codeCount,long timeCount,InternalKey smallest,InternalKey largest)throws IOException { Head head = new Head(codeOffset, codeCount, timeCount, smallest, largest); storage.put(0, head.toByte()); } public FileMeta close()throws IOException { long cOffset = valueOffset.get(); writeCodeArea(); writeHead(cOffset,codeMap.size(), timeIndex, smallest, largest); storage.close(); return new FileMeta(fileNumber, new File(storage.getName()), smallest, largest); } }