package org.yamcs.cli; import java.util.List; import java.util.concurrent.ExecutionException; import org.rocksdb.RocksDB; import org.yamcs.TimeInterval; import org.yamcs.YConfiguration; import org.yamcs.yarch.ColumnDefinition; import org.yamcs.yarch.DataType; import org.yamcs.yarch.TableDefinition; import org.yamcs.yarch.TupleDefinition; import org.yamcs.yarch.YarchDatabase; import org.yamcs.yarch.YarchException; import org.yamcs.yarch.rocksdb.HistogramRebuilder; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; import com.beust.jcommander.Parameters; @Parameters(commandDescription = "Upgrade tables to latest format. It can only be done when the Yamcs server is not running.") public class ArchiveUpgradeCommand extends Command { @Parameter(names="--force", description="force rebuild even if the format version looks ok") private boolean force; @Parameter(names="--instance", description="yamcs instance", required=true) String yamcsInstance; public ArchiveUpgradeCommand(ArchiveCli archiveCli) { super("upgrade", archiveCli); } @Override public void execute() throws Exception { RocksDB.loadLibrary(); if(yamcsInstance!=null) { if(!YarchDatabase.instanceExistsOnDisk(yamcsInstance)) { throw new ParameterException("Archive instance '"+yamcsInstance+"' does not exist"); } upgradeInstance(yamcsInstance); } else { List<String> instances = YConfiguration.getConfiguration("yamcs").getList("instances"); for(String instance:instances) { upgradeInstance(instance); } } } private void upgradeInstance(String instance) throws Exception { upgradeYarchTables(instance); } private void upgradeYarchTables(String instance) throws Exception { YarchDatabase ydb = YarchDatabase.getInstance(instance, true); for(TableDefinition tblDef: ydb.getTableDefinitions()) { if(tblDef.getFormatVersion()==0) { upgrade0_1(ydb, tblDef); upgrade1_2(ydb, tblDef); tblDef.changeFormatDefinition(TableDefinition.CURRENT_FORMAT_VERSION); } else if(tblDef.getFormatVersion()==1){ upgrade1_2(ydb, tblDef); tblDef.changeFormatDefinition(TableDefinition.CURRENT_FORMAT_VERSION); } else { log.debug("Skipping table {}/{} because table format version is {}", ydb.getName(), tblDef.getName(), tblDef.getFormatVersion()); } } } private void upgrade0_1(YarchDatabase ydb, TableDefinition tblDef) throws Exception { log.info("upgrading table {}/{} from version 0 to version 1", ydb.getName(), tblDef.getName()); if("pp".equals(tblDef.getName())) { changePpGroup(ydb, tblDef); } if(tblDef.hasHistogram()) { rebuildHistogram(ydb, tblDef); } } private void upgrade1_2(YarchDatabase ydb, TableDefinition tblDef) { log.info("upgrading table {}/{} from version 1 to version 2", ydb.getName(), tblDef.getName()); if("pp".equals(tblDef.getName())) { changeParaValueType(tblDef); } } static void changeParaValueType(TableDefinition tblDef) { TupleDefinition valueDef = tblDef.getValueDefinition(); List<ColumnDefinition> l= valueDef.getColumnDefinitions(); for(int i=0; i<l.size(); i++) { ColumnDefinition cd = l.get(i); if("org.yamcs.protobuf.Pvalue$ParameterValue".equals(cd.getType().name())) { ColumnDefinition cd1 = new ColumnDefinition(cd.getName(), DataType.PARAMETER_VALUE); l.set(i, cd1); } } } private void changePpGroup(YarchDatabase ydb, TableDefinition tblDef) { if(tblDef.getColumnDefinition("ppgroup") == null) { log.info("Table {}/{} has no ppgroup column", ydb.getName(), tblDef.getName()); return; } log.info("Renaming ppgroup -> group column in table {}/{}", ydb.getName(), tblDef.getName()); tblDef.renameColumn("ppgroup", "group"); } private void rebuildHistogram(YarchDatabase ydb, TableDefinition tblDef) throws InterruptedException, ExecutionException, YarchException { HistogramRebuilder hrb = new HistogramRebuilder(ydb, tblDef.getName()); hrb.rebuild(new TimeInterval()).get(); } }