All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ebay.jetstream.event.channel.file.InboundFileChannelHelper Maven / Gradle / Ivy

/*******************************************************************************
 *  Copyright © 2012-2015 eBay Software Foundation
 *  This program is dual licensed under the MIT and Apache 2.0 licenses.
 *  Please see LICENSE for more information.
 *******************************************************************************/
package com.ebay.jetstream.event.channel.file;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ebay.jetstream.config.ConfigUtils;
import com.ebay.jetstream.event.EventException;


/**
 * This class was and should be part of FileChannelAddress or a base class of InbounfFileChannel
 * if we follow "expert" pattern. However,
 * to make the "address" simple, we move some implementation 
 * details from the "address" class into this "helper" class.
 *  
 * This class will not do any sanity checking which is performed 
 * by the "address" class already.
 * 
 * @author gjin
 */

public class InboundFileChannelHelper {
	private FileChannelAddress m_address;

	private BufferedReader m_br;   /*inbound only:  the reader associated with the local file */
	
	private boolean m_eof = false; /*inbound only */
	
	private FileOutputStream m_fos = null; /* for outbound */
	private AtomicLong m_totalWrites = new AtomicLong();
	private AtomicBoolean m_reportFull = new AtomicBoolean();
	
	private static final Logger LOGGER = LoggerFactory.getLogger("com.ebay.jetstream.event.channel.file");
	private AtomicLong m_errorLoggingRate = new AtomicLong(5000); /* log every 5000 errors initially*/
	private AtomicLong m_numberOfErrors = new AtomicLong();

	
	/***
	 * 
	 */
	public InboundFileChannelHelper(FileChannelAddress address) {
		m_address = address;
		if (m_address == null) {
			throw new IllegalArgumentException("the channel address must be no null");
			
		}
	
	}
	
	public FileChannelAddress getAddress() {
		return m_address;
	}
	
	/* open the file */
	public void openForRead() throws EventException {
		if (m_br != null) {
			LOGGER.info( "try to open an event file " + m_address.getPathname() + " which was open", "OpenFileTwice");
			return;  /* open already */
		}
		File f = new File(ConfigUtils.getInitialPropertyExpanded(m_address.getPathname()));
		
		if (!f.isFile() || !f.canRead()) {
			throw new EventException("Filename=" + m_address.getPathname() + " is not a file or not readable");
		}
		try {
			m_br = new BufferedReader(new InputStreamReader(new FileInputStream(m_address.getPathname())));
		} catch (FileNotFoundException e) {
			throw new EventException("open file: " + m_address.getPathname(), e);
		}
		m_eof= false;
	}
	
	/**inbound only */
	public void closeForRead() throws EventException {
		if (m_br == null) {
			LOGGER.info( "try to close an event file " + m_address.getPathname() + " which was not open", "CloseUnOpenFile");
			return;  /* close already or never open*/
		}
		try {
			m_br.close();
		} catch (IOException e) {
			throw new EventException("close file: " + m_address.getPathname(), e);
		}
		m_br = null;
	}
	
	

	
	
	/***
	 * inbound
	 * @return null when file is not open, or running into IO exception, EOF, bad records
	 */
	public Map getNextEventMap() {
		/***TODO: what is event type, ID?
		 * 
		 */
		HashMap event = new HashMap();
		if (m_br == null) {
			if (m_numberOfErrors.getAndIncrement() % m_errorLoggingRate.get() ==0) {
				LOGGER.error( "the event file is not open");
			}
			return null;
		}
		if (m_eof) {
			if (m_numberOfErrors.getAndIncrement() % m_errorLoggingRate.get() ==0) {
				LOGGER.error( "the event file has reached the end");
			}
			return null;
		}
		String line;
		try {
			line = m_br.readLine();
		} catch (IOException e) {
			/* report ERROR */
			LOGGER.error( e.getLocalizedMessage(), e);
			return null;
		}
		if (line== null) {
			/* report eof--- not an error */
			LOGGER.warn( "file reaches the end");
			m_eof = true;
			return null;
		}
		if (parseEvent(event, line)) {
			return event;
		} else {
			return null;
		}
		
		
	}
	
	private boolean parseEvent(Map event, String s) {
		Long longObj = 0L;
		Integer intObj = 0;
		Float  floatObj = 0.0f;
		String[] columns = s.split(m_address.getColumnDelimiter(), -1);
		
		if (columns.length != m_address.getColumnNameArray().length) {
			/* the data has either more or less columns */ 
			LOGGER.error( "the number of columns in a record!=the number of cloumns:" +
					   " data has "	+ columns.length + ", expected " + m_address.getColumnNameArray().length);
			return false;
		}
		
		/* build map  i.e.
		 * {, ...} for a data record 
		 */
		for (int i=0; i< columns.length; i++) {
			String key = m_address.getColumnNameArray()[i];
			Class xlass = (Class) (m_address.getColumnNameToTypeMap().get(key));
			
			//Object xlass = Class.forName((String) (m_address.getColumnNameToTypeMap().get(key)));
			
			
			/****TODO ****/
			if (xlass.isInstance(longObj)) {
				
				long value; 
				try {
					value = Long.parseLong(columns[i]);
				} catch (NumberFormatException e) {
					LOGGER.info( "incorrect long value=" + columns[i]);
				    return false;
				}
				event.put(m_address.getColumnNameArray()[i], value);
			} else if (xlass.isInstance(intObj)) {
				int value;
				try {
					value = Integer.parseInt(columns[i]);
				} catch (NumberFormatException e) {
					LOGGER.info( "incorrect int value=" + columns[i]);
				    return false;
				}
				
				event.put(m_address.getColumnNameArray()[i], value);
			}else if (xlass.isInstance(floatObj)) {
				float value;
				try {
					value = Float.parseFloat(columns[i]);
				}catch (NumberFormatException e) {
					LOGGER.info( "incorrect float value=" + columns[i]);
				    return false;
				}
				event.put(m_address.getColumnNameArray()[i], value);
			} else { 
				event.put(m_address.getColumnNameArray()[i], columns[i]);
			}
		}
		return true;
	}
	
	public boolean isEOF() {
		return m_eof;
	}
	
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy