IgniteWalConverterArguments { public static IgniteWalConverterArguments parse(final PrintStream out, String args[]) { AtomicReference<CLIArgumentParser> parserRef = new AtomicReference<>(); CLIArgumentParser parser = new CLIArgumentParser(asList( optionalArg(WAL_DIR.arg(), "Path to dir with wal files.", String.class, () -> { if (parserRef.get().get(Args.WAL_ARCHIVE_DIR.arg()) == null) throw new IllegalArgumentException("One of the arguments --wal-dir or --wal-archive-dir must be specified."); else return null; }), optionalArg(Args.WAL_ARCHIVE_DIR.arg(), "Path to dir with wal files.", String.class), optionalArg(PAGE_SIZE.arg(), "Size of pages, which was selected for file store (1024, 2048, 4096, etc).", Integer.class, () -> 4096), optionalArg(BINARY_METADATA_DIR.arg(), "Path to binary meta.", String.class), optionalArg(MARSHALLER_MAPPING_DIR.arg(), "Path to marshaller dir.", String.class), optionalArg(UNWRAP_BINARY.arg(), "Unwrap binary non-primitive objects.", Boolean.class), optionalArg(RECORD_TYPES.arg(), "Comma-separated WAL record types (TX_RECORD, DATA_RECORD, etc). By default, all types will be printed.", String[].class), optionalArg(WAL_TIME_FROM_MILLIS.arg(), "The start time interval for the record time in milliseconds.", Long.class), optionalArg(WAL_TIME_TO_MILLIS.arg(), "The end time interval for the record time in milliseconds.", Long.class), optionalArg(HAS_TEXT.arg(), "Filter by substring in the WAL record.", String.class), optionalArg(INCLUDE_SENSITIVE.arg(), "Strategy for the processing of sensitive data (SHOW, HIDE, HASH, MD5). Default MD5.", String.class, ProcessSensitiveData.MD5::toString), optionalArg(PRINT_STAT.arg(), "Write summary statistics for WAL.", Boolean.class), optionalArg(SKIP_CRC.arg(), "Skip CRC calculation/check flag", Boolean.class) )); if (args == null || args.length < 1) { out.println("Print WAL log data in human-readable form."); out.println(parser.usage()); out.println("For example:"); out.println(" " + WAL_DIR.arg() + " /work/db/wal"); out.println(" " + WAL_ARCHIVE_DIR.arg() + " /work/db/wal_archive"); out.println(" " + PAGE_SIZE.arg() + " 4096"); out.println(" " + BINARY_METADATA_DIR.arg() + " /work/db/nodeId-consistentId"); out.println(" " + MARSHALLER_MAPPING_DIR.arg() + " /work/db/marshaller"); out.println(" " + UNWRAP_BINARY.arg()); out.println(" " + RECORD_TYPES.arg() + " DataRecord,TxRecord"); out.println(" " + WAL_TIME_FROM_MILLIS.arg() + " 1575158400000"); out.println(" " + WAL_TIME_TO_MILLIS.arg() + " 1577836740999"); out.println(" " + HAS_TEXT.arg() + " search_string"); out.println(" " + INCLUDE_SENSITIVE.arg() + " SHOW"); out.println(" " + SKIP_CRC.arg()); return null; } parserRef.set(parser); parser.parse(asList(args).iterator()); File walDir = file(parser.get(WAL_DIR.arg()), true, false); File walArchiveDir = file(parser.get(Args.WAL_ARCHIVE_DIR.arg()), true, false); int pageSize = parser.get(PAGE_SIZE.arg()); File binaryMetadataDir = file(parser.get(BINARY_METADATA_DIR.arg()), true, true); File marshallerMappingDir = file(parser.get(MARSHALLER_MAPPING_DIR.arg()), true, true); boolean unwrapBinary = parser.get(UNWRAP_BINARY.arg()); final Set<WALRecord.RecordType> recordTypes = checkRecordTypes(parser.get(RECORD_TYPES.arg())); Long fromTime = parser.get(Args.WAL_TIME_FROM_MILLIS.arg()); Long toTime = parser.get(Args.WAL_TIME_TO_MILLIS.arg()); String hasText = parser.get(Args.HAS_TEXT.arg()); boolean printStat = parser.get(Args.PRINT_STAT.arg()); boolean skipCrc = parser.get(Args.SKIP_CRC.arg()); String processSensitiveDataStr = parser.get(Args.INCLUDE_SENSITIVE.arg()); ProcessSensitiveData includeSensitive; try { includeSensitive = ProcessSensitiveData.valueOf(processSensitiveDataStr); } catch (Exception e) { throw new IllegalArgumentException("Unknown --include-sensitive: " + processSensitiveDataStr + ". Supported: " + Arrays.toString(ProcessSensitiveData.values())); } out.println("Program arguments:"); if (walDir != null) out.printf("\t%s = %s\n", WAL_DIR, walDir.getAbsolutePath()); if (walArchiveDir != null) out.printf("\t%s = %s\n", WAL_ARCHIVE_DIR, walArchiveDir.getAbsolutePath()); out.printf("\t%s = %d\n", PAGE_SIZE, pageSize); if (binaryMetadataDir != null) out.printf("\t%s = %s\n", BINARY_METADATA_DIR, binaryMetadataDir); if (marshallerMappingDir != null) out.printf("\t%s = %s\n", MARSHALLER_MAPPING_DIR, marshallerMappingDir); out.printf("\t%s = %s\n", UNWRAP_BINARY, unwrapBinary); if (!F.isEmpty(recordTypes)) out.printf("\t%s = %s\n", RECORD_TYPES, recordTypes); if (fromTime != null) out.printf("\t%s = %s\n", WAL_TIME_FROM_MILLIS, new Date(fromTime)); if (toTime != null) out.printf("\t%s = %s\n", WAL_TIME_TO_MILLIS, new Date(toTime)); if (hasText != null) out.printf("\t%s = %s\n", HAS_TEXT, hasText); out.printf("\t%s = %s\n", INCLUDE_SENSITIVE, includeSensitive); out.printf("\t%s = %b\n", PRINT_STAT, printStat); out.printf("\t%s = %b\n", SKIP_CRC, skipCrc); return new IgniteWalConverterArguments(walDir, walArchiveDir, pageSize, binaryMetadataDir, marshallerMappingDir, unwrapBinary, recordTypes, fromTime, toTime, hasText, includeSensitive, printStat, skipCrc); } IgniteWalConverterArguments(
        File walDir,
        File walArchiveDir,
        int pageSize,
        File binaryMetadataDir,
        File marshallerMappingDir,
        boolean unwrapBinary,
        Set<WALRecord.RecordType> recordTypes,
        Long fromTime,
        Long toTime,
        String hasText,
        ProcessSensitiveData includeSensitive,
        boolean printStat,
        boolean skipCrc
    ); File getWalDir(); File getWalArchiveDir(); int getPageSize(); File getBinaryMetadataDir(); File getMarshallerMappingDir(); boolean isUnwrapBinary(); Set<WALRecord.RecordType> getRecordTypes(); Long getFromTime(); Long getToTime(); String hasText(); ProcessSensitiveData includeSensitive(); boolean isPrintStat(); boolean isSkipCrc(); static @Nullable File file(
        @Nullable String filePath,
        boolean checkExists,
        boolean checkIsDirectory
    ); static IgniteWalConverterArguments parse(final PrintStream out, String args[]);  }
@Test public void testViewHelp() throws Exception { final ByteArrayOutputStream out = new ByteArrayOutputStream(); final IgniteWalConverterArguments parseArgs = IgniteWalConverterArguments.parse(new PrintStream(out), null); Assert.assertNull(parseArgs); final String help = out.toString(); Assert.assertTrue(help.startsWith("Print WAL log data in human-readable form.")); for (final Field field : IgniteWalConverterArguments.class.getDeclaredFields()) { if (Modifier.isStatic(field.getModifiers()) && Modifier.isStatic(field.getModifiers()) && field.getType() == String.class) { field.setAccessible(true); final String arg = (String)field.get(null); Assert.assertTrue(help.contains(" " + arg + " ")); } } }
@Test public void testIncorrectWalTimeToMillis() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("Can't parse number 'not_long', expected type: java.lang.Long"); final File wal = File.createTempFile("wal", ""); wal.deleteOnExit(); final String[] args = { "--wal-dir", wal.getAbsolutePath(), "--wal-time-to-millis", "not_long" }; IgniteWalConverterArguments.parse(System.out, args); }
@Test public void testIncorrectProcessSensitiveData() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("Unknown --include-sensitive: unknown. Supported:"); final File wal = File.createTempFile("wal", ""); wal.deleteOnExit(); final String[] args = { "--wal-dir", wal.getAbsolutePath(), "--include-sensitive", "unknown" }; IgniteWalConverterArguments.parse(System.out, args); }
@Test public void testParse() throws IOException { final File wal = File.createTempFile("wal", ""); wal.deleteOnExit(); final File walArchive = File.createTempFile("wal_archive", ""); walArchive.deleteOnExit(); final File binaryMetadataDir = new File(System.getProperty("java.io.tmpdir")); final File marshallerDir = binaryMetadataDir; final String[] args = { "--wal-dir", wal.getAbsolutePath(), "--wal-archive-dir", walArchive.getAbsolutePath(), "--page-size", "2048", "--binary-metadata-dir", binaryMetadataDir.getAbsolutePath(), "--marshaller-mapping-dir", marshallerDir.getAbsolutePath(), "--unwrap-binary", "--record-types", "DATA_RECORD,TX_RECORD", "--wal-time-from-millis", "1575158400000", "--wal-time-to-millis", "1577836740999", "--has-text", "search string", "--include-sensitive", "HASH", "--print-stat", "--skip-crc"}; final IgniteWalConverterArguments parseArgs = IgniteWalConverterArguments.parse(System.out, args); Assert.assertEquals(wal, parseArgs.getWalDir()); Assert.assertEquals(walArchive, parseArgs.getWalArchiveDir()); Assert.assertEquals(2048, parseArgs.getPageSize()); Assert.assertEquals(binaryMetadataDir, parseArgs.getBinaryMetadataDir()); Assert.assertEquals(marshallerDir, parseArgs.getMarshallerMappingDir()); Assert.assertTrue(parseArgs.isUnwrapBinary()); Assert.assertTrue(parseArgs.getRecordTypes().contains(WALRecord.RecordType.DATA_RECORD)); Assert.assertTrue(parseArgs.getRecordTypes().contains(WALRecord.RecordType.TX_RECORD)); Assert.assertEquals(1575158400000L, (long)parseArgs.getFromTime()); Assert.assertEquals(1577836740999L, (long)parseArgs.getToTime()); Assert.assertEquals("search string", parseArgs.hasText()); Assert.assertEquals(ProcessSensitiveData.HASH, parseArgs.includeSensitive()); Assert.assertTrue(parseArgs.isPrintStat()); Assert.assertTrue(parseArgs.isSkipCrc()); }
@Test public void testRequiredWalDir() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("One of the arguments --wal-dir or --wal-archive-dir must be specified."); IgniteWalConverterArguments.parse(System.out, new String[] {"--page-size", "4096"}); }
@Test public void testIncorrectWalDir() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("File/directory 'non_existing_path' does not exist."); IgniteWalConverterArguments.parse(System.out, new String[] {"--wal-dir", "non_existing_path"}); }
@Test public void testIncorrectWalArchiveDir() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("File/directory 'non_existing_path' does not exist."); IgniteWalConverterArguments.parse(System.out, new String[] {"--wal-archive-dir", "non_existing_path"}); }
@Test public void testIncorrectPageSize() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("Can't parse number 'not_integer', expected type: java.lang.Integer"); final File wal = File.createTempFile("wal", ""); wal.deleteOnExit(); final String[] args = { "--wal-dir", wal.getAbsolutePath(), "--page-size", "not_integer" }; IgniteWalConverterArguments.parse(System.out, args); }
@Test public void testIncorrectBinaryMetadataFileStoreDir() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("File/directory 'non_existing_path' does not exist."); final File wal = File.createTempFile("wal", ""); wal.deleteOnExit(); final String[] args = { "--wal-dir", wal.getAbsolutePath(), "--binary-metadata-dir", "non_existing_path" }; IgniteWalConverterArguments.parse(System.out, args); }
@Test public void testIncorrectMarshallerMappingDir() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("File/directory 'non_existing_path' does not exist."); final File wal = File.createTempFile("wal", ""); wal.deleteOnExit(); final String[] args = { "--wal-dir", wal.getAbsolutePath(), "--marshaller-mapping-dir", "non_existing_path" }; IgniteWalConverterArguments.parse(System.out, args); }
@Test public void testIncorrectRecordTypes() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("Unknown record types: [not_exist]."); final File wal = File.createTempFile("wal", ""); wal.deleteOnExit(); final String[] args = { "--wal-dir", wal.getAbsolutePath(), "--record-types", "not_exist" }; IgniteWalConverterArguments.parse(System.out, args); }
@Test public void testIncorrectSeveralRecordTypes() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("Unknown record types: [not_exist1, not_exist2]."); final File wal = File.createTempFile("wal", ""); wal.deleteOnExit(); final String[] args = { "--wal-dir", wal.getAbsolutePath(), "--record-types", "not_exist1,not_exist2" }; IgniteWalConverterArguments.parse(System.out, args); }
@Test public void testIncorrectWalTimeFromMillis() throws Exception { expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("Can't parse number 'not_long', expected type: java.lang.Long"); final File wal = File.createTempFile("wal", ""); wal.deleteOnExit(); final String[] args = { "--wal-dir", wal.getAbsolutePath(), "--wal-time-from-millis", "not_long" }; IgniteWalConverterArguments.parse(System.out, args); }