package com.taobao.tddl.optimizer.config.table; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.text.MessageFormat; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.builder.ToStringBuilder; import com.taobao.tddl.common.exception.TddlException; import com.taobao.tddl.common.exception.TddlRuntimeException; import com.taobao.tddl.common.model.lifecycle.AbstractLifecycle; import com.taobao.tddl.common.utils.TddlToStringStyle; import com.taobao.tddl.config.ConfigDataHandler; import com.taobao.tddl.config.ConfigDataHandlerFactory; import com.taobao.tddl.config.ConfigDataListener; import com.taobao.tddl.config.impl.ConfigDataHandlerCity; import com.taobao.tddl.optimizer.config.table.parse.TableMetaParser; import com.taobao.tddl.common.utils.logger.Logger; import com.taobao.tddl.common.utils.logger.LoggerFactory; /** * 有schema文件的schemamanager实现 * * @since 5.0.0 */ public class StaticSchemaManager extends AbstractLifecycle implements SchemaManager { private final static Logger logger = LoggerFactory.getLogger(StaticSchemaManager.class); public final static MessageFormat schemaNullError = new MessageFormat("get schema null, appName is:{0}, unitName is:{1}, filePath is: {2}, dataId is: {3}"); public final static MessageFormat TDDL5_SCHEMA_DATA_ID = new MessageFormat("com.taobao.tddl.v1_{0}_schema"); public final static MessageFormat ANDOR_SCHEMA_DATA_ID = new MessageFormat("com.taobao.and_orV0.{0}_SCHEMA_DATAID"); private ConfigDataHandler schemaCdh; private String schemaFilePath = null; private String appName = null; private String unitName = null; public StaticSchemaManager(String schemaFilePath, String appName, String unitName){ super(); this.schemaFilePath = schemaFilePath; this.appName = appName; this.unitName = unitName; } public StaticSchemaManager(){ } protected Map<String, TableMeta> ss; protected void doInit() throws TddlException { super.doInit(); ss = new ConcurrentHashMap<String, TableMeta>(); if (this.appName == null) { logger.warn("schema appname is not assigned"); } if (this.schemaFilePath == null) { logger.warn("schema file is not assigned"); } if (appName == null && schemaFilePath == null) { return; } ConfigDataHandlerFactory factory = null; String dataId = null; // 优先从文件获取 if (schemaFilePath == null) { dataId = TDDL5_SCHEMA_DATA_ID.format(new Object[] { appName }); factory = ConfigDataHandlerCity.getFactory(appName, unitName); } else { factory = ConfigDataHandlerCity.getFileFactory(appName); dataId = schemaFilePath; } schemaCdh = factory.getConfigDataHandler(dataId, new SchemaConfigDataListener(this)); String data = schemaCdh.getData(ConfigDataHandler.GET_DATA_TIMEOUT, ConfigDataHandler.FIRST_CACHE_THEN_SERVER_STRATEGY); if (data == null) { schemaCdh.destory(); // 尝试找一下andor的版本配置 dataId = ANDOR_SCHEMA_DATA_ID.format(new Object[] { appName }); schemaCdh = factory.getConfigDataHandler(dataId, new SchemaConfigDataListener(this)); data = schemaCdh.getData(ConfigDataHandler.GET_DATA_TIMEOUT, ConfigDataHandler.FIRST_CACHE_THEN_SERVER_STRATEGY); } if (data == null) { logger.warn(schemaNullError.format(new Object[] { appName, unitName, schemaFilePath, dataId })); return; } InputStream sis = null; try { sis = new ByteArrayInputStream(data.getBytes()); List<TableMeta> schemaList = TableMetaParser.parse(sis); this.ss.clear(); for (TableMeta table : schemaList) { this.putTable(table.getTableName(), table); } logger.warn("table fetched:"); logger.warn(this.ss.keySet().toString()); } catch (Exception e) { logger.error("table parser error, schema file is:\n" + data, e); throw new TddlRuntimeException(e); } finally { IOUtils.closeQuietly(sis); } } public static class SchemaConfigDataListener implements ConfigDataListener { private StaticSchemaManager schemaManager; public SchemaConfigDataListener(StaticSchemaManager schemaManager){ this.schemaManager = schemaManager; } @Override public void onDataRecieved(String dataId, String data) { if (data == null || data.isEmpty()) { logger.warn("schema is null, dataId is " + dataId); return; } InputStream sis = null; try { sis = new ByteArrayInputStream(data.getBytes()); List<TableMeta> schemaList = TableMetaParser.parse(sis); schemaManager.ss.clear(); for (TableMeta table : schemaList) { schemaManager.putTable(table.getTableName(), table); } logger.warn("table fetched:"); logger.warn(schemaManager.ss.keySet().toString()); } catch (Exception e) { logger.error("table parser error, schema file is:" + data, e); throw new TddlRuntimeException(e); } finally { IOUtils.closeQuietly(sis); } } } protected void doDestory() throws TddlException { super.doDestory(); ss.clear(); if (schemaCdh != null) { schemaCdh.destory(); } } public TableMeta getTable(String tableName) { return ss.get((tableName)); } public void putTable(String tableName, TableMeta tableMeta) { ss.put(tableName.toUpperCase(), tableMeta); } public Collection<TableMeta> getAllTables() { return ss.values(); } public static StaticSchemaManager parseSchema(String data) throws TddlException { if (data == null || data.isEmpty()) { throw new IllegalArgumentException("schema is null"); } InputStream sis = null; try { sis = new ByteArrayInputStream(data.getBytes()); return parseSchema(sis); } finally { IOUtils.closeQuietly(sis); } } public static StaticSchemaManager parseSchema(InputStream in) throws TddlException { if (in == null) { throw new IllegalArgumentException("in is null"); } try { StaticSchemaManager schemaManager = new StaticSchemaManager(); schemaManager.init(); List<TableMeta> schemaList = TableMetaParser.parse(in); for (TableMeta t : schemaList) { schemaManager.putTable(t.getTableName(), t); } return schemaManager; } finally { IOUtils.closeQuietly(in); } } public String toString() { return ToStringBuilder.reflectionToString(this, TddlToStringStyle.DEFAULT_STYLE); } }