/*
* Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.tsdr.collectors.cmc;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;
import org.datasand.codec.TypeDescriptorsContainer;
import org.datasand.codec.bytearray.ByteArrayEncodeDataContainer;
import org.datasand.codec.bytearray.ByteEncoder;
import org.opendaylight.tsdr.collectors.cmc.mdsal.Counter64Serializer;
import org.opendaylight.tsdr.collectors.cmc.mdsal.DataCategorySerializer;
import org.opendaylight.tsdr.collectors.cmc.mdsal.MDSALClassExtractor;
import org.opendaylight.tsdr.collectors.cmc.mdsal.MDSALMethodFilter;
import org.opendaylight.tsdr.collectors.cmc.mdsal.MDSALObjectTypeRule;
import org.opendaylight.tsdr.collectors.cmc.mdsal.MDSalAugmentationObserver;
import org.opendaylight.tsdr.collectors.cmc.mdsal.MDSalObjectChildRule;
import org.opendaylight.tsdr.collectors.cmc.mdsal.RecordKeysSerializer;
import org.opendaylight.tsdr.collectors.cmc.mdsal.TSDRMetricRecordSerializer;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.DataCategory;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.storetsdrmetricrecord.input.TSDRMetricRecord;
import org.opendaylight.yang.gen.v1.opendaylight.tsdr.rev150219.tsdrrecord.RecordKeys;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Counter64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Sharon Aicler(saichler@gmail.com)
**/
public class CollectorService implements ICollectorService, Runnable{
private static Logger log = LoggerFactory.getLogger(CollectorService.class);
private static CollectorService instance = new CollectorService();
private ICollectorService localCollectorService = null;
private TypeDescriptorsContainer typeDescriptorContainer = new TypeDescriptorsContainer("./src/main/java/resources");
private boolean wasMDSALInitialized = false;
private ServerSocket socket = null;
private boolean running = true;
private CollectorService(){
}
public static CollectorService getInstance(){
return instance;
}
public void setLocalCollectorService(ICollectorService localService){
this.localCollectorService = localService;
}
@Override
public void store(TSDRMetricRecord record) {
if(this.localCollectorService!=null){
this.localCollectorService.store(record);
}else{
if(!wasMDSALInitialized){
initMDSALSerialization();
}
ByteArrayEncodeDataContainer ba = new ByteArrayEncodeDataContainer(new byte[256], typeDescriptorContainer.getTypeDescriptorByClass(TSDRMetricRecord.class));
ba.getEncoder().encodeObject(record, ba);
sendBytes(ba.getData());
}
}
@Override
public void store(List<TSDRMetricRecord> recordList) {
if(this.localCollectorService!=null){
this.localCollectorService.store(recordList);
}else{
if(!wasMDSALInitialized){
initMDSALSerialization();
}
ByteArrayEncodeDataContainer ba = new ByteArrayEncodeDataContainer(new byte[256], typeDescriptorContainer.getTypeDescriptorByClass(TSDRMetricRecord.class));
ba.getEncoder().encodeObject(recordList, ba);
sendBytes(ba.getData());
}
}
private void sendBytes(byte[] metricData){
}
public void initMDSALSerialization(){
typeDescriptorContainer.clearChildAttributeObservers();
typeDescriptorContainer.addChildAttributeObserver(new MDSalObjectChildRule());
typeDescriptorContainer.addTypeAttributeObserver(new MDSALObjectTypeRule());
typeDescriptorContainer.setClassExtractor(new MDSALClassExtractor());
typeDescriptorContainer.addMethodFilterObserver(new MDSALMethodFilter());
typeDescriptorContainer.setAugmentationObserver(new MDSalAugmentationObserver());
ByteEncoder.registerSerializer(TSDRMetricRecord.class, new TSDRMetricRecordSerializer(), 900);
ByteEncoder.registerSerializer(DataCategory.class, new DataCategorySerializer(), 901);
ByteEncoder.registerSerializer(RecordKeys.class, new RecordKeysSerializer(), 902);
ByteEncoder.registerSerializer(Counter64.class, new Counter64Serializer(), 903);
wasMDSALInitialized = true;
}
protected void initAsServer(){
try{
socket = new ServerSocket(18080);
new Thread(this,"TSDR MDSAL Server");
}catch(Exception e){
log.error("Failed to start collector service socket",e);
}
}
public void run(){
while(running){
try{
Socket s = socket.accept();
new Connection(s);
}catch(Exception err){
log.error("Server Socket problem, exiting",err);
break;
}
}
}
private class Connection extends Thread{
private Socket s = null;
private BufferedInputStream in = null;
private BufferedOutputStream out = null;
private ObjectProcessor obp = null;
private Connection(Socket _s){
super("TSDR Service Connection from "+_s.getInetAddress().getHostName()+":"+_s.getPort());
this.s = _s;
try{
in = new BufferedInputStream(new DataInputStream(s.getInputStream()));
out = new BufferedOutputStream(new DataOutputStream(s.getOutputStream()));
obp = new ObjectProcessor(this);
}catch(IOException e){
log.error("Error opening Streams",e);
}
this.start();
}
public void run(){
while(running){
try{
byte dataSize[] = new byte[4];
in.read(dataSize);
int size = ByteEncoder.decodeInt32(dataSize,0);
byte objectData[] = new byte[size];
in.read(objectData);
obp.addObject(objectData);
}catch(Exception err){
log.error("Socket Read Problem",err);
}
}
}
}
private class ObjectProcessor extends Thread {
private List<byte[]> queue = new LinkedList<byte[]>();
public ObjectProcessor(Connection _conn){
super("OP for "+_conn.getName());
this.start();
}
public void addObject(byte[] obj){
synchronized(queue){
queue.add(obj);
queue.notifyAll();
}
}
public void run(){
byte data[] = null;
while(running){
synchronized(queue){
if(queue.isEmpty()){
try{queue.wait(2000);}catch(InterruptedException e){}
}else{
data = queue.remove(0);
}
}
if(data!=null){
if(!wasMDSALInitialized){
initMDSALSerialization();
}
ByteArrayEncodeDataContainer container = new ByteArrayEncodeDataContainer(data, typeDescriptorContainer.getTypeDescriptorByClass(TSDRMetricRecord.class));
Object obj = container.getEncoder().decodeObject(container);
if(obj instanceof TSDRMetricRecord){
store((TSDRMetricRecord)obj);
}else{
store((List)obj);
}
}
data = null;
}
}
}
/**
* A method to be used once to generate the serializers
* Look @ the commeted code in the main method
**
private void generate(){
typeDescriptorContainer.getTypeDescriptorByClass(TSDRMetricRecord.class);
}
public static void main(String args[]){
CollectorService.getInstance().initMDSALSerialization();
CollectorService.getInstance().generate();
}**/
}