/*
* Copyright 2015 Edward Capriolo
*
* 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 io.teknek.nibiru.engine;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import io.teknek.nibiru.Store;
import io.teknek.nibiru.Configuration;
import io.teknek.nibiru.Token;
import io.teknek.nibiru.engine.atom.AtomKey;
import io.teknek.nibiru.engine.atom.AtomValue;
import io.teknek.nibiru.io.CountingBufferedOutputStream;
import io.teknek.nibiru.metadata.StoreMetaData;
public class SsTableStreamWriter {
private final Store columnFamily;
private final String id;
private final IndexWriter indexWriter;
private CountingBufferedOutputStream ssOutputStream;
private BloomFilterWriter bloomFilter;
public SsTableStreamWriter(String id, Store columnFamily){
this.id = id;
this.columnFamily = columnFamily;
indexWriter = new IndexWriter(id, columnFamily);
bloomFilter = new BloomFilterWriter(id, columnFamily.getKeyspace().getConfiguration());
}
public static File pathToSsTableDataDirectory(Configuration configuration, StoreMetaData cfmd ){
new File(configuration.getDataDirectory()).mkdir();
File ssTablePath = new File(configuration.getDataDirectory(), cfmd.getName());
ssTablePath.mkdir();
return ssTablePath;
}
public void open() throws FileNotFoundException {
//File sstableFile = new File(columnFamily.getKeyspace().getConfiguration().getDataDirectory(), id + ".ss");
File sstableFile = new File (pathToSsTableDataDirectory(columnFamily.getKeyspace().getConfiguration(),
columnFamily.getStoreMetadata()), id + ".ss");
if (! new File(columnFamily.getKeyspace().getConfiguration().getDataDirectory()).exists()){
boolean create = new File(columnFamily.getKeyspace().getConfiguration().getDataDirectory()).mkdirs();
if (!create){
throw new RuntimeException ("could not create "+ columnFamily.getKeyspace().getConfiguration().getDataDirectory());
}
}
ssOutputStream = new CountingBufferedOutputStream(new FileOutputStream(sstableFile));
indexWriter.open();
}
public static void writeToken(Token token, CountingBufferedOutputStream ssOutputStream) throws IOException {
ssOutputStream.writeAndCount((byte) (token.getToken().getBytes().length >> 8) & 0xFF);
ssOutputStream.writeAndCount((byte) (token.getToken().getBytes().length & 0xFF));
ssOutputStream.writeAndCount(token.getToken().getBytes());
}
public static void writeRowkey(Token token, CountingBufferedOutputStream ssOutputStream) throws IOException {
ssOutputStream.writeAndCount((byte) (token.getRowkey().getBytes().length >> 8) & 0xFF);
ssOutputStream.writeAndCount((byte) (token.getRowkey().getBytes().length & 0xFF));
ssOutputStream.writeAndCount(token.getRowkey().getBytes());
}
public static void writeColumns(Map<AtomKey,AtomValue> columns, CountingBufferedOutputStream ssOutputStream) throws IOException {
ssOutputStream.writeAndCount((byte) (columns.size() >> 8) & 0xFF);
ssOutputStream.writeAndCount((byte) (columns.size() & 0xFF));
for (Entry<AtomKey, AtomValue> j : columns.entrySet()) {
{
byte[] key = j.getKey().externalize();
ssOutputStream.writeAndCount((byte) (key.length >> 8) & 0xFF);
ssOutputStream.writeAndCount((byte) (key.length & 0xFF));
ssOutputStream.writeAndCount(key);
}
{
byte[] value = j.getValue().externalize();
ssOutputStream.writeAndCount((byte) (value.length >> 8) & 0xFF);
ssOutputStream.writeAndCount((byte) (value.length & 0xFF));
ssOutputStream.writeAndCount(value);
}
}
}
public void write(Token t, Map<AtomKey,AtomValue> columns) throws IOException {
long startOfRecord = ssOutputStream.getWrittenOffset();
bloomFilter.put(t);
ssOutputStream.writeAndCount(SsTableReader.START_RECORD);
writeToken(t, ssOutputStream);
writeRowkey(t, ssOutputStream);
indexWriter.handleRow(startOfRecord, t.getToken());
writeColumns(columns, ssOutputStream);
ssOutputStream.writeAndCount(SsTableReader.END_ROW);
}
public void close() throws IOException {
indexWriter.close();
ssOutputStream.close();
bloomFilter.writeAndClose();
}
}