Package com.dp.nebula.wormhole.plugins.writer.greenplumwriter

Source Code of com.dp.nebula.wormhole.plugins.writer.greenplumwriter.GreenplumWriter

package com.dp.nebula.wormhole.plugins.writer.greenplumwriter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.dbcp.DelegatingConnection;
import org.apache.log4j.Logger;
import org.postgresql.PGConnection;
import org.postgresql.copy.PGCopyOutputStream;
import org.postgresql.util.PSQLException;

import com.dp.nebula.wormhole.common.AbstractPlugin;
import com.dp.nebula.wormhole.common.JobStatus;
import com.dp.nebula.wormhole.common.WormholeException;
import com.dp.nebula.wormhole.common.interfaces.ILine;
import com.dp.nebula.wormhole.common.interfaces.ILineReceiver;
import com.dp.nebula.wormhole.common.interfaces.IWriter;
import com.dp.nebula.wormhole.plugins.common.DBSource;
import com.dp.nebula.wormhole.plugins.common.ErrorCodeUtils;

public class GreenplumWriter  extends AbstractPlugin implements IWriter {
  static final int PLUGIN_NO = 2;
  private int errorCodeAdd;
  private static Map<String, String> encodingMaps = null;
  static {
    encodingMaps = new HashMap<String, String>();
    encodingMaps.put("utf-8", "UTF8");
  }
 
  private Connection conn;

  private String ip = "";
 
  private String dbname = null;

  private String sql;
 
  private String table;
 
  private String columns;

  private String encoding = "UTF8";

  //private double limit = 0;

  //private int lineCounter = 0;
    //0x0 is invalid in greenplum
//    private static char[] replaceChars = {0,' '};

  private int sucLineCounter = 0;
 
  private int failedLineCounter = 0;
 
  private String logErrorTable;
 
  private int failedLinesThreshold;

    /* 列分隔符 */
    private static final char SEP = '\t';
    /* 行分隔符 */
    // In windows this may be '\r\n'
    private static final char BREAK = '\n';
   
    private ILine line = null;
    /* 从line中获取一行数据暂存数组*/
    private byte buffer[] = null;
   
//    private int length = 1024 * 1024 * 8;
       
  private String writerID;
   
    //private StringBuilder lineBuilder = new StringBuilder(len);
   
  private Logger logger = Logger.getLogger(GreenplumWriter.class);
 
  private static final String SQL_PATTERN = "COPY %s %s FROM STDIN WITH DELIMITER E'%c' ";
 
  private static final String SQL_ERROR_LOG_PATTERN = "%s LOG ERRORS INTO %s";
 
  private static final String SQL_REJECT_LIMIT_PATTERN = "%s SEGMENT REJECT LIMIT %d ROWS";
 
//  private final String zeroDateTimeRound = "0001-01-01 00:00:00.0";
 
  private String[] addFields = null;
 
  @Override
  public void init() {
    this.ip = getParam().getValue(ParamKey.ip,"");
    this.dbname = getParam().getValue(ParamKey.dbname,"");
    this.table = getParam().getValue(ParamKey.table,"");
    this.columns = getParam().getValue(ParamKey.columns,"");
    this.encoding = getParam().getValue(ParamKey.encoding, "UTF8").toLowerCase();
    this.logErrorTable = getParam().getValue(ParamKey.logErrorTable, "");
    this.failedLinesThreshold = getParam().getIntValue(ParamKey.failedLinesThreshold, 0);
    this.writerID   = getParam().getValue(AbstractPlugin.PLUGINID, "");
    analyzeColumns();
    if (encodingMaps.containsKey(this.encoding)) {
      this.encoding = encodingMaps.get(this.encoding);
    }
    if(!columns.isEmpty()) {
      columns = "(" + columns + ")";
    }
    sql = String.format(SQL_PATTERN, table, columns,SEP);
    if(!logErrorTable.isEmpty()) {
      sql = String.format(SQL_ERROR_LOG_PATTERN,sql,logErrorTable);
    }
    if(failedLinesThreshold > 1) {
      sql = String.format(SQL_REJECT_LIMIT_PATTERN,sql,failedLinesThreshold);
    }
    int priority = getParam().getIntValue(ParamKey.priority, 0);
    errorCodeAdd = PLUGIN_NO*JobStatus.PLUGIN_BASE + priority*JobStatus.WRITER_BASE;
  }

  @Override
  public void connection() {
    try {
      conn = DBSource.getConnection(GreenplumWriter.class, ip, writerID, dbname);
    } catch (Exception e) {
      throw new WormholeException(e, JobStatus.WRITE_CONNECTION_FAILED.getStatus() + errorCodeAdd);
    }
  }
 
  @Override
  public void write(ILineReceiver receiver) {
    logger.info(writerID + ": insert SQL - " + sql);
    PGCopyOutputStream outputStream = null;
    try {
      outputStream = new PGCopyOutputStream((PGConnection) ((DelegatingConnection) conn).getInnermostDelegate(), sql);
      while(true){
        if(fetchLine(receiver, outputStream) == -1){
          break;
        }
      }
      outputStream.flushCopy();
      getMonitor().increaseSuccessLine(sucLineCounter);
      getMonitor().increaseFailedLines(failedLineCounter);
    } catch (Exception e) {
      logger.error(writerID + ": write to greenplum failed.");
      throw throwException(e)
    }
    finally{
      if(outputStream != null) {
        try {
          outputStream.close();
        } catch (IOException e) {
          throw throwException(e)
        }
      }
      this.logger.info(writerID + ": write to greenplum ends .");
      try {
        if(conn != null) {
          conn.close();
        }
      } catch (Exception e) {
        logger.error(writerID + ": close connection failed.",e);
      }
    }
  }
 
  private WormholeException throwException(Exception e) {
    WormholeException ex = new WormholeException(e,JobStatus.WRITE_FAILED.getStatus(),writerID);
    if(e instanceof WormholeException) {
      ex = (WormholeException) e;
    }
    else if(e instanceof PSQLException) {
      ErrorCodeUtils.psqlWriterWrapper((PSQLException)e,ex);
    }
    else if(e instanceof IOException && e.getCause() != null
        && e.getCause() instanceof PSQLException) {
      ErrorCodeUtils.psqlWriterWrapper((PSQLException)(e.getCause()),ex);
    }
    ex.setStatusCode(ex.getStatusCode() + errorCodeAdd);
    return ex;
  }

  public String getEncoding() {
    return encoding;
  }

  @Override
  public void commit() {
  }
 
  private void analyzeColumns(){
    if(columns.isEmpty()) {
      return;
    }
    String tmpColumns = columns;
    String [] tmpColumnsArr = tmpColumns.split(",");
    addFields = new String[tmpColumnsArr.length];
    columns = "";
    int i = 0;
    for(String field:tmpColumnsArr){
      int index = field.indexOf("=");
      if(index != -1) {
        if(index + 1 != field.length()) {
          String columnValue = field.substring(index+1);
          addFields[i] = columnValue;
        }
        else {
          addFields[i] = "";
        }
        field = field.substring(0,index).trim();
      }
      if (columns.isEmpty()) {
        columns = field;
      }
      else {
        columns = columns + "," + field;
      }
      i++; 
    }
  }
 
  private String buildString(ILine line) {
    StringBuilder lineBuilder = new StringBuilder();
    String field;
      int num = line.getFieldNum();
      int len = 0;
      if(addFields == null ) {
        len = num;
      } else {
        len = addFields.length;
      }
      for (int i = 0,j = 0;i < len; i++) {
        if(addFields!=null && addFields[i] != null) {
          field = addFields[i];
        }
        else if(j < num){
          field = line.getField(j);
          j++;
        }
        else {
          logger.error(writerID + ": field number is less than column number.");
          throw new WormholeException("GreenplumWriter: Fields number is less than column number ",JobStatus.WRITE_FAILED.getStatus(),writerID);
        }
          if (null != field) {
            StringBuilder sb = new StringBuilder();
            char[] characters = field.toCharArray();
            for(int k = 0; k < characters.length; k++){
              if(characters[k] == '\\'){
                sb.append("\\\\");
              }
              else if(characters[k] == '\r'){
                sb.append("\\r");
              }
              else if(characters[k] == '\n'){
                sb.append("\\n");
              }
              else if(characters[k] == SEP){
                sb.append("\\t");
              }
              else if(characters[k] == 0) {
                sb.append(" ");
              }
              else{
                sb.append(characters[k]);
              }
            }
              lineBuilder.append(sb.toString());
          } else {
              lineBuilder.append("\\N");
          }
          if (i < len - 1) {
            lineBuilder.append(SEP);
          } else {
              lineBuilder.append(BREAK);
          }
      }
      return lineBuilder.toString();
  }
     
  private int fetchLine(ILineReceiver receiver, PGCopyOutputStream outputStream) throws UnsupportedEncodingException {
        boolean isSuccess = true;
    int ret = 0;
        //int currLen;
       
        /* 本次读数据的逻辑 */
        int lineLen;
        line = receiver.receive();
        /* line为空,表明数据已全部读完 */
        if (line == null) {
            return -1;
        }
        //this.buildString(line);
        this.buffer = buildString(line).getBytes(this.encoding);
        lineLen = this.buffer.length;
      
        try {
           outputStream.write(buffer);
//           if(lineLen > length) {
//               logger.error(writerID + ": line is too long");
//               isSuccess = false;
//             }
//           else {
//             outputStream.writeToCopy(buffer, 0, lineLen);
//           }
    } catch (Exception e) {
      logger.warn(writerID + ": Copy data failed for one Line.");
      if(!outputStream.isActive()) {
        logger.error(writerID + ": Copy data failed:" + line.toString('\t'),e);
        throw new WormholeException(e,JobStatus.WRITE_FAILED.getStatus(),writerID);
      }
           isSuccess = false;
    }
    if(isSuccess) {
      this.sucLineCounter ++ ;
    } else {
      this.failedLineCounter ++ ;
    }
    ret += lineLen;
        return (ret);
  }

//  private String replaceChars(String old, char[] rchars) {
//    if (null == rchars) {
//      return old;
//    }
//   
//    int oldLen = old.length();
//    int rLen = rchars.length;
//   
//    StringBuilder sb = new StringBuilder(oldLen);
//    char[] oldArrays = old.toCharArray();
//    boolean found;
//    char c1;
//   
//    for (int i = 0; i < oldLen; i++) {
//      found = false;
//      c1 = oldArrays[i];
//      for (int j = 0; j < rLen; j += 2) {
//        if (c1 == rchars[j]) {
//          if (rchars[j + 1] != 0) {
//            sb.append(rchars[j + 1]);
//          }
//          found = true;
//        }
//      }
//      if (!found) {
//        sb.append(c1);
//      }
//    } 
//    return sb.toString();
//  }
}
TOP

Related Classes of com.dp.nebula.wormhole.plugins.writer.greenplumwriter.GreenplumWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.