Return-Path: X-Original-To: apmail-accumulo-commits-archive@www.apache.org Delivered-To: apmail-accumulo-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 59E8418BF6 for ; Wed, 13 Jan 2016 22:58:59 +0000 (UTC) Received: (qmail 83261 invoked by uid 500); 13 Jan 2016 22:58:59 -0000 Delivered-To: apmail-accumulo-commits-archive@accumulo.apache.org Received: (qmail 83223 invoked by uid 500); 13 Jan 2016 22:58:59 -0000 Mailing-List: contact commits-help@accumulo.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@accumulo.apache.org Delivered-To: mailing list commits@accumulo.apache.org Received: (qmail 83212 invoked by uid 99); 13 Jan 2016 22:58:59 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 13 Jan 2016 22:58:59 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 03110E0007; Wed, 13 Jan 2016 22:58:59 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: elserj@apache.org To: commits@accumulo.apache.org Message-Id: <63638f0d20bd47b6af5a3ff158ba4ce9@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: accumulo git commit: ACCUMULO-2493: Deprecated BinaryFormatter in favor of DefaultFormatter with FormatterConfig. [Forced Update!] Date: Wed, 13 Jan 2016 22:58:59 +0000 (UTC) Repository: accumulo Updated Branches: refs/heads/master 83f346b28 -> f7b9fd40a (forced update) ACCUMULO-2493: Deprecated BinaryFormatter in favor of DefaultFormatter with FormatterConfig. * New class FormatterConfig handles configuration of Formatter objects * FormatterConfig is taken by Formatter.initialize, which broke the interface for many classes throughout the non-public API * Added DateFormatSupplier to let Formatters use DateFormat in a Thread-safe way * Removed code from ScanCommand and Shell tied to BinaryFormatter to use properly configured DefaultFormatter instead * Fixed bug where `scan -f [num] -fm [class]` would ignore Formatter class used in `-fm` and be overridden with BinaryFormatter Closes apache/accumulo#61 Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/f7b9fd40 Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/f7b9fd40 Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/f7b9fd40 Branch: refs/heads/master Commit: f7b9fd40a5ee73d137643580832084b505fffae9 Parents: bd515fc Author: Matt Dailey Authored: Fri Dec 4 21:50:58 2015 -0500 Committer: Josh Elser Committed: Wed Jan 13 17:58:37 2016 -0500 ---------------------------------------------------------------------- .../core/util/format/BinaryFormatter.java | 41 ++----- .../core/util/format/DateFormatSupplier.java | 95 +++++++++++++++ .../core/util/format/DateStringFormatter.java | 57 ++++----- .../core/util/format/DefaultFormatter.java | 99 +++++++++------- .../accumulo/core/util/format/Formatter.java | 2 +- .../core/util/format/FormatterConfig.java | 115 +++++++++++++++++++ .../core/util/format/FormatterFactory.java | 8 +- .../accumulo/core/util/format/HexFormatter.java | 8 +- .../util/format/DateFormatSupplierTest.java | 74 ++++++++++++ .../util/format/DateStringFormatterTest.java | 29 ++++- .../core/util/format/DefaultFormatterTest.java | 62 +++++++++- .../core/util/format/FormatterConfigTest.java | 81 +++++++++++++ .../core/util/format/FormatterFactoryTest.java | 5 +- .../core/util/format/HexFormatterTest.java | 6 +- .../ShardedTableDistributionFormatterTest.java | 4 +- .../format/StatisticsDisplayFormatterTest.java | 4 +- .../server/replication/StatusFormatter.java | 18 +-- .../apache/accumulo/tracer/TraceFormatter.java | 22 ++-- .../java/org/apache/accumulo/shell/Shell.java | 19 +-- .../shell/commands/DeleteManyCommand.java | 5 +- .../shell/commands/GetSplitsCommand.java | 6 +- .../accumulo/shell/commands/GrepCommand.java | 6 +- .../accumulo/shell/commands/ScanCommand.java | 31 ++--- .../accumulo/shell/format/DeleterFormatter.java | 11 +- .../org/apache/accumulo/shell/ShellTest.java | 96 +++++++++++++++- .../shell/format/DeleterFormatterTest.java | 20 ++-- .../org/apache/accumulo/test/ShellServerIT.java | 9 +- 27 files changed, 719 insertions(+), 214 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java index a5f6a8d..f5cbe39 100644 --- a/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java +++ b/core/src/main/java/org/apache/accumulo/core/util/format/BinaryFormatter.java @@ -17,67 +17,50 @@ package org.apache.accumulo.core.util.format; import java.util.Map.Entry; - import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.security.ColumnVisibility; -import org.apache.hadoop.io.Text; +/** + * @deprecated Use {@link DefaultFormatter} providing showLength and printTimestamps via {@link FormatterConfig}. + */ +@Deprecated public class BinaryFormatter extends DefaultFormatter { - private static int showLength; - + // this class can probably be replaced by DefaultFormatter since DefaultFormatter has the max length stuff @Override public String next() { checkState(true); - return formatEntry(getScannerIterator().next(), isDoTimestamps()); + return formatEntry(getScannerIterator().next(), config.willPrintTimestamps(), config.getShownLength()); } - // this should be replaced with something like Record.toString(); - // it would be great if we were able to combine code with DefaultFormatter.formatEntry, but that currently does not respect the showLength option. - public static String formatEntry(Entry entry, boolean showTimestamps) { + public static String formatEntry(Entry entry, boolean printTimestamps, int shownLength) { StringBuilder sb = new StringBuilder(); Key key = entry.getKey(); // append row - appendText(sb, key.getRow()).append(" "); + appendText(sb, key.getRow(), shownLength).append(" "); // append column family - appendText(sb, key.getColumnFamily()).append(":"); + appendText(sb, key.getColumnFamily(), shownLength).append(":"); // append column qualifier - appendText(sb, key.getColumnQualifier()).append(" "); + appendText(sb, key.getColumnQualifier(), shownLength).append(" "); // append visibility expression sb.append(new ColumnVisibility(key.getColumnVisibility())); // append timestamp - if (showTimestamps) + if (printTimestamps) sb.append(" ").append(entry.getKey().getTimestamp()); // append value Value value = entry.getValue(); if (value != null && value.getSize() > 0) { sb.append("\t"); - appendValue(sb, value); + appendValue(sb, value, shownLength); } return sb.toString(); } - public static StringBuilder appendText(StringBuilder sb, Text t) { - return appendBytes(sb, t.getBytes(), 0, t.getLength()); - } - - static StringBuilder appendValue(StringBuilder sb, Value value) { - return appendBytes(sb, value.get(), 0, value.get().length); - } - - static StringBuilder appendBytes(StringBuilder sb, byte ba[], int offset, int len) { - int length = Math.min(len, showLength); - return DefaultFormatter.appendBytes(sb, ba, offset, length); - } - - public static void getlength(int length) { - showLength = length; - } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/main/java/org/apache/accumulo/core/util/format/DateFormatSupplier.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/DateFormatSupplier.java b/core/src/main/java/org/apache/accumulo/core/util/format/DateFormatSupplier.java new file mode 100644 index 0000000..9cf50e0 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/util/format/DateFormatSupplier.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.accumulo.core.util.format; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.TimeZone; + +import com.google.common.base.Supplier; + +/** + * DateFormatSupplier is a {@code ThreadLocal} that will set the correct TimeZone when the object is retrieved by {@link #get()}. + * + * This exists as a way to get around thread safety issues in {@link DateFormat}. This class also contains helper methods that create some useful + * DateFormatSuppliers. + * + * Instances of DateFormatSuppliers can be shared, but note that a DateFormat generated from it will be shared by all classes within a Thread. + * + * In general, the state of a retrieved DateFormat should not be changed, unless it makes sense to only perform a state change within that Thread. + */ +public abstract class DateFormatSupplier extends ThreadLocal implements Supplier { + private TimeZone timeZone; + + public DateFormatSupplier() { + timeZone = TimeZone.getDefault(); + } + + public DateFormatSupplier(TimeZone timeZone) { + this.timeZone = timeZone; + } + + public TimeZone getTimeZone() { + return timeZone; + } + + public void setTimeZone(TimeZone timeZone) { + this.timeZone = timeZone; + } + + /** Always sets the TimeZone, which is a fast operation */ + @Override + public DateFormat get() { + final DateFormat df = super.get(); + df.setTimeZone(timeZone); + return df; + } + + public static final String HUMAN_READABLE_FORMAT = "yyyy/MM/dd HH:mm:ss.SSS"; + + /** + * Create a Supplier for {@link FormatterConfig.DefaultDateFormat}s + */ + public static DateFormatSupplier createDefaultFormatSupplier() { + return new DateFormatSupplier() { + @Override + protected DateFormat initialValue() { + return new FormatterConfig.DefaultDateFormat(); + } + }; + } + + /** Create a generator for SimpleDateFormats accepting a dateFormat */ + public static DateFormatSupplier createSimpleFormatSupplier(final String dateFormat) { + return new DateFormatSupplier() { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat(dateFormat); + } + }; + } + + /** Create a generator for SimpleDateFormats accepting a dateFormat */ + public static DateFormatSupplier createSimpleFormatSupplier(final String dateFormat, final TimeZone timeZone) { + return new DateFormatSupplier(timeZone) { + @Override + protected SimpleDateFormat initialValue() { + return new SimpleDateFormat(dateFormat); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/main/java/org/apache/accumulo/core/util/format/DateStringFormatter.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/DateStringFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/DateStringFormatter.java index 5bcd4a3..63bd536 100644 --- a/core/src/main/java/org/apache/accumulo/core/util/format/DateStringFormatter.java +++ b/core/src/main/java/org/apache/accumulo/core/util/format/DateStringFormatter.java @@ -16,31 +16,45 @@ */ package org.apache.accumulo.core.util.format; -import java.text.DateFormat; -import java.text.SimpleDateFormat; import java.util.Map.Entry; import java.util.TimeZone; - import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; +/** + * This class is not recommended because {@link #initialize(Iterable, FormatterConfig)} replaces parameters in {@link FormatterConfig}, which + * could surprise users. + * + * This class can be replaced by {@link DefaultFormatter} where FormatterConfig is initialized with a DateFormat set to {@link #DATE_FORMAT}. See + * {@link DateFormatSupplier#createSimpleFormatSupplier(String, java.util.TimeZone)}. + * + *
+ * final DateFormatSupplier dfSupplier = DateFormatSupplier.createSimpleFormatSupplier(DateFormatSupplier.HUMAN_READABLE_FORMAT, TimeZone.getTimeZone("UTC"));
+ * final FormatterConfig config = new FormatterConfig().setPrintTimestamps(true).setDateFormatSupplier(dfSupplier);
+ * 
+ */ +@Deprecated public class DateStringFormatter implements Formatter { - private boolean printTimestamps = false; - private DefaultFormatter defaultFormatter = new DefaultFormatter(); - public static final String DATE_FORMAT = "yyyy/MM/dd HH:mm:ss.SSS"; - // SimpleDataFormat is not thread safe - private static final ThreadLocal formatter = new ThreadLocal() { - @Override - protected SimpleDateFormat initialValue() { - return new SimpleDateFormat(DATE_FORMAT); - } - }; + private DefaultFormatter defaultFormatter; + private TimeZone timeZone; + + public static final String DATE_FORMAT = DateFormatSupplier.HUMAN_READABLE_FORMAT; + + public DateStringFormatter() { + this(TimeZone.getDefault()); + } + + public DateStringFormatter(TimeZone timeZone) { + this.defaultFormatter = new DefaultFormatter(); + this.timeZone = timeZone; + } @Override - public void initialize(Iterable> scanner, boolean printTimestamps) { - this.printTimestamps = printTimestamps; - defaultFormatter.initialize(scanner, printTimestamps); + public void initialize(Iterable> scanner, FormatterConfig config) { + FormatterConfig newConfig = new FormatterConfig(config); + newConfig.setDateFormatSupplier(DateFormatSupplier.createSimpleFormatSupplier(DATE_FORMAT, timeZone)); + defaultFormatter.initialize(scanner, newConfig); } @Override @@ -50,13 +64,7 @@ public class DateStringFormatter implements Formatter { @Override public String next() { - DateFormat timestampformat = null; - - if (printTimestamps) { - timestampformat = formatter.get(); - } - - return defaultFormatter.next(timestampformat); + return defaultFormatter.next(); } @Override @@ -64,7 +72,4 @@ public class DateStringFormatter implements Formatter { defaultFormatter.remove(); } - public void setTimeZone(TimeZone zone) { - formatter.get().setTimeZone(zone); - } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java index 5a2f43f..5517b78 100644 --- a/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java +++ b/core/src/main/java/org/apache/accumulo/core/util/format/DefaultFormatter.java @@ -17,12 +17,9 @@ package org.apache.accumulo.core.util.format; import java.text.DateFormat; -import java.text.FieldPosition; -import java.text.ParsePosition; import java.util.Date; import java.util.Iterator; import java.util.Map.Entry; - import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.security.ColumnVisibility; @@ -30,35 +27,16 @@ import org.apache.hadoop.io.Text; public class DefaultFormatter implements Formatter { private Iterator> si; - private boolean doTimestamps; - - public static class DefaultDateFormat extends DateFormat { - private static final long serialVersionUID = 1L; - - @Override - public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { - toAppendTo.append(Long.toString(date.getTime())); - return toAppendTo; - } - - @Override - public Date parse(String source, ParsePosition pos) { - return new Date(Long.parseLong(source)); - } - } + protected FormatterConfig config; - private static final ThreadLocal formatter = new ThreadLocal() { - @Override - protected DateFormat initialValue() { - return new DefaultDateFormat(); - } - }; + /** Used as default DateFormat for some static methods */ + private static final ThreadLocal formatter = DateFormatSupplier.createDefaultFormatSupplier(); @Override - public void initialize(Iterable> scanner, boolean printTimestamps) { + public void initialize(Iterable> scanner, FormatterConfig config) { checkState(false); si = scanner.iterator(); - doTimestamps = printTimestamps; + this.config = new FormatterConfig(config); } @Override @@ -69,18 +47,8 @@ public class DefaultFormatter implements Formatter { @Override public String next() { - DateFormat timestampFormat = null; - - if (doTimestamps) { - timestampFormat = formatter.get(); - } - - return next(timestampFormat); - } - - protected String next(DateFormat timestampFormat) { checkState(true); - return formatEntry(si.next(), timestampFormat); + return formatEntry(si.next()); } @Override @@ -96,7 +64,10 @@ public class DefaultFormatter implements Formatter { throw new IllegalStateException("Already initialized"); } - // this should be replaced with something like Record.toString(); + /** + * if showTimestamps, will use {@link org.apache.accumulo.core.util.format.FormatterConfig.DefaultDateFormat}. Preferably, use + * {@link #formatEntry(Entry, FormatterConfig)} + */ public static String formatEntry(Entry entry, boolean showTimestamps) { DateFormat timestampFormat = null; @@ -115,6 +86,7 @@ public class DefaultFormatter implements Formatter { } }; + /** Does not show timestamps if timestampFormat is null */ public static String formatEntry(Entry entry, DateFormat timestampFormat) { StringBuilder sb = new StringBuilder(); Key key = entry.getKey(); @@ -149,14 +121,55 @@ public class DefaultFormatter implements Formatter { return sb.toString(); } + public String formatEntry(Entry entry) { + return formatEntry(entry, this.config); + } + + public static String formatEntry(Entry entry, FormatterConfig config) { + // originally from BinaryFormatter + StringBuilder sb = new StringBuilder(); + Key key = entry.getKey(); + Text buffer = new Text(); + + final int shownLength = config.getShownLength(); + + appendText(sb, key.getRow(buffer), shownLength).append(" "); + appendText(sb, key.getColumnFamily(buffer), shownLength).append(":"); + appendText(sb, key.getColumnQualifier(buffer), shownLength).append(" "); + sb.append(new ColumnVisibility(key.getColumnVisibility(buffer))); + + // append timestamp + if (config.willPrintTimestamps() && config.getDateFormatSupplier() != null) { + tmpDate.get().setTime(entry.getKey().getTimestamp()); + sb.append(" ").append(config.getDateFormatSupplier().get().format(tmpDate.get())); + } + + // append value + Value value = entry.getValue(); + if (value != null && value.getSize() > 0) { + sb.append("\t"); + appendValue(sb, value, shownLength); + } + return sb.toString(); + + } + static StringBuilder appendText(StringBuilder sb, Text t) { return appendBytes(sb, t.getBytes(), 0, t.getLength()); } + public static StringBuilder appendText(StringBuilder sb, Text t, int shownLength) { + return appendBytes(sb, t.getBytes(), 0, t.getLength(), shownLength); + } + static StringBuilder appendValue(StringBuilder sb, Value value) { return appendBytes(sb, value.get(), 0, value.get().length); } + static StringBuilder appendValue(StringBuilder sb, Value value, int shownLength) { + return appendBytes(sb, value.get(), 0, value.get().length, shownLength); + } + static StringBuilder appendBytes(StringBuilder sb, byte ba[], int offset, int len) { for (int i = 0; i < len; i++) { int c = 0xff & ba[offset + i]; @@ -170,11 +183,17 @@ public class DefaultFormatter implements Formatter { return sb; } + static StringBuilder appendBytes(StringBuilder sb, byte ba[], int offset, int len, int shownLength) { + int length = Math.min(len, shownLength); + return DefaultFormatter.appendBytes(sb, ba, offset, length); + } + public Iterator> getScannerIterator() { return si; } protected boolean isDoTimestamps() { - return doTimestamps; + return config.willPrintTimestamps(); } + } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/main/java/org/apache/accumulo/core/util/format/Formatter.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/Formatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/Formatter.java index 497cc74..136b252 100644 --- a/core/src/main/java/org/apache/accumulo/core/util/format/Formatter.java +++ b/core/src/main/java/org/apache/accumulo/core/util/format/Formatter.java @@ -23,5 +23,5 @@ import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; public interface Formatter extends Iterator { - void initialize(Iterable> scanner, boolean printTimestamps); + void initialize(Iterable> scanner, FormatterConfig config); } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/main/java/org/apache/accumulo/core/util/format/FormatterConfig.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/FormatterConfig.java b/core/src/main/java/org/apache/accumulo/core/util/format/FormatterConfig.java new file mode 100644 index 0000000..c70b1e4 --- /dev/null +++ b/core/src/main/java/org/apache/accumulo/core/util/format/FormatterConfig.java @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.accumulo.core.util.format; + +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.google.common.base.Preconditions; +import com.google.common.base.Supplier; + +/** + * Holds configuration settings for a {@link Formatter} + */ +public class FormatterConfig { + + private boolean printTimestamps; + private int shownLength; + private Supplier dateFormatSupplier; + + /** Formats with milliseconds since epoch */ + public static class DefaultDateFormat extends SimpleDateFormat { + private static final long serialVersionUID = 1L; + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { + toAppendTo.append(Long.toString(date.getTime())); + return toAppendTo; + } + + @Override + public Date parse(String source, ParsePosition pos) { + return new Date(Long.parseLong(source)); + } + } + + public FormatterConfig() { + this.setPrintTimestamps(false); + this.doNotLimitShowLength(); + this.dateFormatSupplier = DateFormatSupplier.createDefaultFormatSupplier(); + } + + /** + * Copies most fields, but still points to other.dateFormatSupplier. + */ + public FormatterConfig(FormatterConfig other) { + this.printTimestamps = other.printTimestamps; + this.shownLength = other.shownLength; + this.dateFormatSupplier = other.dateFormatSupplier; + } + + public boolean willPrintTimestamps() { + return printTimestamps; + } + + public FormatterConfig setPrintTimestamps(boolean printTimestamps) { + this.printTimestamps = printTimestamps; + return this; + } + + public int getShownLength() { + return shownLength; + } + + public boolean willLimitShowLength() { + return this.shownLength != Integer.MAX_VALUE; + } + + /** + * If given a negative number, throws an {@link IllegalArgumentException} + * + * @param shownLength + * maximum length of formatted output + * @return {@code this} to allow chaining of set methods + */ + public FormatterConfig setShownLength(int shownLength) { + Preconditions.checkArgument(shownLength >= 0, "Shown length cannot be negative"); + this.shownLength = shownLength; + return this; + } + + public FormatterConfig doNotLimitShowLength() { + this.shownLength = Integer.MAX_VALUE; + return this; + } + + public Supplier getDateFormatSupplier() { + return dateFormatSupplier; + } + + /** + * this.dateFormatSupplier points to dateFormatSupplier, so it is recommended that you create a new {@code Supplier} when calling this function if your + * {@code Supplier} maintains some kind of state (see {@link DateFormatSupplier}. + */ + public FormatterConfig setDateFormatSupplier(Supplier dateFormatSupplier) { + this.dateFormatSupplier = dateFormatSupplier; + return this; + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java b/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java index 7eb542f..9ae1a6c 100644 --- a/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java +++ b/core/src/main/java/org/apache/accumulo/core/util/format/FormatterFactory.java @@ -26,7 +26,7 @@ import org.slf4j.LoggerFactory; public class FormatterFactory { private static final Logger log = LoggerFactory.getLogger(FormatterFactory.class); - public static Formatter getFormatter(Class formatterClass, Iterable> scanner, boolean printTimestamps) { + public static Formatter getFormatter(Class formatterClass, Iterable> scanner, FormatterConfig config) { Formatter formatter = null; try { formatter = formatterClass.newInstance(); @@ -34,12 +34,12 @@ public class FormatterFactory { log.warn("Unable to instantiate formatter. Using default formatter.", e); formatter = new DefaultFormatter(); } - formatter.initialize(scanner, printTimestamps); + formatter.initialize(scanner, config); return formatter; } - public static Formatter getDefaultFormatter(Iterable> scanner, boolean printTimestamps) { - return getFormatter(DefaultFormatter.class, scanner, printTimestamps); + public static Formatter getDefaultFormatter(Iterable> scanner, FormatterConfig config) { + return getFormatter(DefaultFormatter.class, scanner, config); } private FormatterFactory() { http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java b/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java index 65e52d3..54e2598 100644 --- a/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java +++ b/core/src/main/java/org/apache/accumulo/core/util/format/HexFormatter.java @@ -31,7 +31,7 @@ public class HexFormatter implements Formatter, ScanInterpreter { private char chars[] = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; private Iterator> iter; - private boolean printTimestamps; + private FormatterConfig config; private void toHex(StringBuilder sb, byte[] bin) { @@ -88,7 +88,7 @@ public class HexFormatter implements Formatter, ScanInterpreter { sb.append(" ["); sb.append(entry.getKey().getColumnVisibilityData().toString()); sb.append("] "); - if (printTimestamps) { + if (config.willPrintTimestamps()) { sb.append(Long.toString(entry.getKey().getTimestamp())); sb.append(" "); } @@ -103,9 +103,9 @@ public class HexFormatter implements Formatter, ScanInterpreter { } @Override - public void initialize(Iterable> scanner, boolean printTimestamps) { + public void initialize(Iterable> scanner, FormatterConfig config) { this.iter = scanner.iterator(); - this.printTimestamps = printTimestamps; + this.config = new FormatterConfig(config); } @Override http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/test/java/org/apache/accumulo/core/util/format/DateFormatSupplierTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/DateFormatSupplierTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/DateFormatSupplierTest.java new file mode 100644 index 0000000..b095b04 --- /dev/null +++ b/core/src/test/java/org/apache/accumulo/core/util/format/DateFormatSupplierTest.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.accumulo.core.util.format; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.text.DateFormat; +import java.util.Date; +import java.util.TimeZone; +import org.junit.Test; + +public class DateFormatSupplierTest { + + /** Asserts two supplier instance create independent objects */ + private void assertSuppliersIndependent(ThreadLocal supplierA, ThreadLocal supplierB) { + DateFormat getA1 = supplierA.get(); + DateFormat getA2 = supplierA.get(); + assertSame(getA1, getA2); + + DateFormat getB1 = supplierB.get(); + DateFormat getB2 = supplierB.get(); + + assertSame(getB1, getB2); + assertNotSame(getA1, getB1); + } + + @Test + public void testCreateDefaultFormatSupplier() throws Exception { + ThreadLocal supplierA = DateFormatSupplier.createDefaultFormatSupplier(); + ThreadLocal supplierB = DateFormatSupplier.createDefaultFormatSupplier(); + assertSuppliersIndependent(supplierA, supplierB); + } + + @Test + public void testCreateSimpleFormatSupplier() throws Exception { + final String format = DateFormatSupplier.HUMAN_READABLE_FORMAT; + DateFormatSupplier supplierA = DateFormatSupplier.createSimpleFormatSupplier(format); + DateFormatSupplier supplierB = DateFormatSupplier.createSimpleFormatSupplier(format); + assertSuppliersIndependent(supplierA, supplierB); + + // since dfA and dfB come from different suppliers, altering the TimeZone on one does not affect the other + supplierA.setTimeZone(TimeZone.getTimeZone("UTC")); + final DateFormat dfA = supplierA.get(); + + supplierB.setTimeZone(TimeZone.getTimeZone("EST")); + final DateFormat dfB = supplierB.get(); + + final String resultA = dfA.format(new Date(0)); + assertEquals("1970/01/01 00:00:00.000", resultA); + + final String resultB = dfB.format(new Date(0)); + assertEquals("1969/12/31 19:00:00.000", resultB); + + assertTrue(!resultA.equals(resultB)); + + } +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java index 1b121f3..505c198 100644 --- a/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java +++ b/core/src/test/java/org/apache/accumulo/core/util/format/DateStringFormatterTest.java @@ -22,12 +22,12 @@ import static org.junit.Assert.assertTrue; import java.util.Map; import java.util.TimeZone; import java.util.TreeMap; - import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; import org.junit.Before; import org.junit.Test; +@SuppressWarnings("deprecation") public class DateStringFormatterTest { DateStringFormatter formatter; @@ -40,13 +40,30 @@ public class DateStringFormatterTest { data.put(new Key("", "", "", 0), new Value()); } + private void testFormatterIgnoresConfig(FormatterConfig config, DateStringFormatter formatter) { + // ignores config's DateFormatSupplier and substitutes its own + formatter.initialize(data.entrySet(), config); + + assertTrue(formatter.hasNext()); + final String next = formatter.next(); + assertTrue(next, next.endsWith("1970/01/01 00:00:00.000")); + } + @Test public void testTimestamps() { - formatter.initialize(data.entrySet(), true); - formatter.setTimeZone(TimeZone.getTimeZone("UTC")); + final TimeZone utc = TimeZone.getTimeZone("UTC"); + final TimeZone est = TimeZone.getTimeZone("EST"); + final FormatterConfig config = new FormatterConfig().setPrintTimestamps(true); + DateStringFormatter formatter; - assertTrue(formatter.hasNext()); - assertTrue(formatter.next().endsWith("1970/01/01 00:00:00.000")); + formatter = new DateStringFormatter(utc); + testFormatterIgnoresConfig(config, formatter); + + // even though config says to use EST and only print year, the Formatter will override these + formatter = new DateStringFormatter(utc); + DateFormatSupplier dfSupplier = DateFormatSupplier.createSimpleFormatSupplier("YYYY", est); + config.setDateFormatSupplier(dfSupplier); + testFormatterIgnoresConfig(config, formatter); } @Test @@ -55,7 +72,7 @@ public class DateStringFormatterTest { assertEquals(2, data.size()); - formatter.initialize(data.entrySet(), false); + formatter.initialize(data.entrySet(), new FormatterConfig()); assertEquals(formatter.next(), formatter.next()); } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java index 7b654d0..eed455c 100644 --- a/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java +++ b/core/src/test/java/org/apache/accumulo/core/util/format/DefaultFormatterTest.java @@ -19,8 +19,10 @@ package org.apache.accumulo.core.util.format; import static org.junit.Assert.assertEquals; import java.util.Collections; +import java.util.Map; import java.util.Map.Entry; - +import java.util.TimeZone; +import java.util.TreeMap; import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; import org.apache.hadoop.io.Text; @@ -29,6 +31,8 @@ import org.junit.Test; public class DefaultFormatterTest { + public static final TimeZone UTC = TimeZone.getTimeZone("UTC"); + public static final TimeZone EST = TimeZone.getTimeZone("EST"); DefaultFormatter df; Iterable> empty = Collections. emptyMap().entrySet(); @@ -39,8 +43,9 @@ public class DefaultFormatterTest { @Test(expected = IllegalStateException.class) public void testDoubleInitialize() { - df.initialize(empty, true); - df.initialize(empty, true); + final FormatterConfig timestampConfig = new FormatterConfig().setPrintTimestamps(true); + df.initialize(empty, timestampConfig); + df.initialize(empty, timestampConfig); } @Test(expected = IllegalStateException.class) @@ -59,4 +64,55 @@ public class DefaultFormatterTest { DefaultFormatter.appendText(sb, new Text(data)); assertEquals("\\x00\\\\x\\xFF", sb.toString()); } + + @Test + public void testFormatEntry() { + final long timestamp = 0; + Map map = new TreeMap(); + map.put(new Key("a", "ab", "abc", timestamp), new Value("abcd".getBytes())); + + FormatterConfig config; + String answer; + + // no timestamp, no max + config = new FormatterConfig(); + df = new DefaultFormatter(); + df.initialize(map.entrySet(), config); + answer = df.next(); + assertEquals("a ab:abc []\tabcd", answer); + + // yes timestamp, no max + config.setPrintTimestamps(true); + df = new DefaultFormatter(); + df.initialize(map.entrySet(), config); + answer = df.next(); + assertEquals("a ab:abc [] " + timestamp + "\tabcd", answer); + + // yes timestamp, max of 1 + config.setPrintTimestamps(true).setShownLength(1); + df = new DefaultFormatter(); + df.initialize(map.entrySet(), config); + answer = df.next(); + assertEquals("a a:a [] " + timestamp + "\ta", answer); + + // yes timestamp, no max, new DateFormat + config.setPrintTimestamps(true).doNotLimitShowLength().setDateFormatSupplier(DateFormatSupplier.createSimpleFormatSupplier("YYYY")); + df = new DefaultFormatter(); + df.initialize(map.entrySet(), config); + answer = df.next(); + assertEquals("a ab:abc [] 1970\tabcd", answer); + + // yes timestamp, no max, new DateFormat, different TimeZone + config.setPrintTimestamps(true).doNotLimitShowLength().setDateFormatSupplier(DateFormatSupplier.createSimpleFormatSupplier("HH", UTC)); + df = new DefaultFormatter(); + df.initialize(map.entrySet(), config); + answer = df.next(); + assertEquals("a ab:abc [] 00\tabcd", answer); + + config.setPrintTimestamps(true).doNotLimitShowLength().setDateFormatSupplier(DateFormatSupplier.createSimpleFormatSupplier("HH", EST)); + df = new DefaultFormatter(); + df.initialize(map.entrySet(), config); + answer = df.next(); + assertEquals("a ab:abc [] 19\tabcd", answer); + } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/test/java/org/apache/accumulo/core/util/format/FormatterConfigTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/FormatterConfigTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/FormatterConfigTest.java new file mode 100644 index 0000000..aa88e03 --- /dev/null +++ b/core/src/test/java/org/apache/accumulo/core/util/format/FormatterConfigTest.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.accumulo.core.util.format; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.fail; + +import java.text.DateFormat; +import org.junit.Test; + +public class FormatterConfigTest { + + @Test + public void testConstructor() { + FormatterConfig config = new FormatterConfig(); + assertEquals(false, config.willLimitShowLength()); + assertEquals(false, config.willPrintTimestamps()); + } + + @Test + public void testSetShownLength() throws Exception { + FormatterConfig config = new FormatterConfig(); + try { + config.setShownLength(-1); + fail("Should throw on negative length."); + } catch (IllegalArgumentException e) {} + + config.setShownLength(0); + assertEquals(0, config.getShownLength()); + assertEquals(true, config.willLimitShowLength()); + + config.setShownLength(1); + assertEquals(1, config.getShownLength()); + assertEquals(true, config.willLimitShowLength()); + } + + @Test + public void testDoNotLimitShowLength() { + FormatterConfig config = new FormatterConfig(); + assertEquals(false, config.willLimitShowLength()); + + config.setShownLength(1); + assertEquals(true, config.willLimitShowLength()); + + config.doNotLimitShowLength(); + assertEquals(false, config.willLimitShowLength()); + } + + @Test + public void testGetDateFormat() { + FormatterConfig config1 = new FormatterConfig(); + DateFormat df1 = config1.getDateFormatSupplier().get(); + + FormatterConfig config2 = new FormatterConfig(); + assertNotSame(df1, config2.getDateFormatSupplier().get()); + + config2.setDateFormatSupplier(config1.getDateFormatSupplier()); + assertSame(df1, config2.getDateFormatSupplier().get()); + + // even though copying, it can't copy the Generator, so will pull out the same DateFormat + FormatterConfig configCopy = new FormatterConfig(config1); + assertSame(df1, configCopy.getDateFormatSupplier().get()); + } + +} http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java index d379dee..b6b91d3 100644 --- a/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java +++ b/core/src/test/java/org/apache/accumulo/core/util/format/FormatterFactoryTest.java @@ -37,8 +37,9 @@ public class FormatterFactoryTest { @Test public void testGetDefaultFormatter() { - Formatter defaultFormatter = FormatterFactory.getDefaultFormatter(scanner, true); - Formatter bogusFormatter = FormatterFactory.getFormatter(Formatter.class, scanner, true); + final FormatterConfig timestampConfig = new FormatterConfig().setPrintTimestamps(true); + Formatter defaultFormatter = FormatterFactory.getDefaultFormatter(scanner, timestampConfig); + Formatter bogusFormatter = FormatterFactory.getFormatter(Formatter.class, scanner, timestampConfig); assertEquals(defaultFormatter.getClass(), bogusFormatter.getClass()); } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java index 4745ad3..7f20dfc 100644 --- a/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java +++ b/core/src/test/java/org/apache/accumulo/core/util/format/HexFormatterTest.java @@ -42,7 +42,7 @@ public class HexFormatterTest { @Test public void testInitialize() { data.put(new Key(), new Value()); - formatter.initialize(data.entrySet(), false); + formatter.initialize(data.entrySet(), new FormatterConfig()); assertTrue(formatter.hasNext()); assertEquals(" " + " " + " [" + "] ", formatter.next()); @@ -59,7 +59,7 @@ public class HexFormatterTest { Text bytes = new Text(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}); data.put(new Key(bytes), new Value()); - formatter.initialize(data.entrySet(), false); + formatter.initialize(data.entrySet(), new FormatterConfig()); String row = formatter.next().split(" ")[0]; assertEquals("0001-0203-0405-0607-0809-0a0b-0c0d-0e0f", row); @@ -80,7 +80,7 @@ public class HexFormatterTest { public void testTimestamps() { long now = System.currentTimeMillis(); data.put(new Key("", "", "", now), new Value()); - formatter.initialize(data.entrySet(), true); + formatter.initialize(data.entrySet(), new FormatterConfig().setPrintTimestamps(true)); String entry = formatter.next().split("\\s+")[2]; assertEquals(now, Long.parseLong(entry)); } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java index e8879a5..d6afe99 100644 --- a/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java +++ b/core/src/test/java/org/apache/accumulo/core/util/format/ShardedTableDistributionFormatterTest.java @@ -47,7 +47,7 @@ public class ShardedTableDistributionFormatterTest { public void testInitialize() { data.put(new Key(), new Value()); data.put(new Key("r", "~tab"), new Value()); - formatter.initialize(data.entrySet(), false); + formatter.initialize(data.entrySet(), new FormatterConfig()); assertTrue(formatter.hasNext()); formatter.next(); @@ -60,7 +60,7 @@ public class ShardedTableDistributionFormatterTest { data.put(new Key("t;19700101", "~tab", "loc", 0), new Value("srv1".getBytes(UTF_8))); data.put(new Key("t;19700101", "~tab", "loc", 1), new Value("srv2".getBytes(UTF_8))); - formatter.initialize(data.entrySet(), false); + formatter.initialize(data.entrySet(), new FormatterConfig()); String[] resultLines = formatter.next().split("\n"); List results = Arrays.asList(resultLines).subList(2, 4); http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java b/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java index 93c948c..69342d7 100644 --- a/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java +++ b/core/src/test/java/org/apache/accumulo/core/util/format/StatisticsDisplayFormatterTest.java @@ -42,7 +42,7 @@ public class StatisticsDisplayFormatterTest { @Test public void testInitialize() { data.put(new Key(), new Value()); - formatter.initialize(data.entrySet(), false); + formatter.initialize(data.entrySet(), new FormatterConfig()); assertTrue(formatter.hasNext()); } @@ -51,7 +51,7 @@ public class StatisticsDisplayFormatterTest { public void testAggregate() { data.put(new Key("", "", "", 1), new Value()); data.put(new Key("", "", "", 2), new Value()); - formatter.initialize(data.entrySet(), false); + formatter.initialize(data.entrySet(), new FormatterConfig()); String[] output = formatter.next().split("\n"); assertTrue(output[2].endsWith(": 1")); http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/server/base/src/main/java/org/apache/accumulo/server/replication/StatusFormatter.java ---------------------------------------------------------------------- diff --git a/server/base/src/main/java/org/apache/accumulo/server/replication/StatusFormatter.java b/server/base/src/main/java/org/apache/accumulo/server/replication/StatusFormatter.java index a674802..6a2d66a 100644 --- a/server/base/src/main/java/org/apache/accumulo/server/replication/StatusFormatter.java +++ b/server/base/src/main/java/org/apache/accumulo/server/replication/StatusFormatter.java @@ -22,7 +22,6 @@ import java.util.Date; import java.util.Iterator; import java.util.Map.Entry; import java.util.Set; - import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.metadata.schema.MetadataSchema.ReplicationSection; @@ -32,8 +31,8 @@ import org.apache.accumulo.core.replication.ReplicationSchema.StatusSection; import org.apache.accumulo.core.replication.ReplicationSchema.WorkSection; import org.apache.accumulo.core.security.ColumnVisibility; import org.apache.accumulo.core.util.format.DefaultFormatter; -import org.apache.accumulo.core.util.format.DefaultFormatter.DefaultDateFormat; import org.apache.accumulo.core.util.format.Formatter; +import org.apache.accumulo.core.util.format.FormatterConfig; import org.apache.accumulo.server.replication.proto.Replication.Status; import org.apache.hadoop.io.Text; import org.slf4j.Logger; @@ -52,7 +51,7 @@ public class StatusFormatter implements Formatter { WorkSection.NAME, OrderSection.NAME)); private Iterator> iterator; - private boolean printTimestamps; + private FormatterConfig config; /* so a new date object doesn't get created for every record in the scan result */ private static ThreadLocal tmpDate = new ThreadLocal() { @@ -62,13 +61,6 @@ public class StatusFormatter implements Formatter { } }; - private static final ThreadLocal formatter = new ThreadLocal() { - @Override - protected DateFormat initialValue() { - return new DefaultDateFormat(); - } - }; - @Override public boolean hasNext() { return iterator.hasNext(); @@ -77,7 +69,7 @@ public class StatusFormatter implements Formatter { @Override public String next() { Entry entry = iterator.next(); - DateFormat timestampFormat = printTimestamps ? formatter.get() : null; + DateFormat timestampFormat = config.willPrintTimestamps() ? config.getDateFormatSupplier().get() : null; // If we expected this to be a protobuf, try to parse it, adding a message when it fails to parse if (REPLICATION_COLFAMS.contains(entry.getKey().getColumnFamily())) { @@ -157,9 +149,9 @@ public class StatusFormatter implements Formatter { } @Override - public void initialize(Iterable> scanner, boolean printTimestamps) { + public void initialize(Iterable> scanner, FormatterConfig config) { this.iterator = scanner.iterator(); - this.printTimestamps = printTimestamps; + this.config = new FormatterConfig(config); } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/server/tracer/src/main/java/org/apache/accumulo/tracer/TraceFormatter.java ---------------------------------------------------------------------- diff --git a/server/tracer/src/main/java/org/apache/accumulo/tracer/TraceFormatter.java b/server/tracer/src/main/java/org/apache/accumulo/tracer/TraceFormatter.java index 48ec8cf..775e6aa 100644 --- a/server/tracer/src/main/java/org/apache/accumulo/tracer/TraceFormatter.java +++ b/server/tracer/src/main/java/org/apache/accumulo/tracer/TraceFormatter.java @@ -20,11 +20,12 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Iterator; import java.util.Map.Entry; - import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Value; +import org.apache.accumulo.core.util.format.DateFormatSupplier; import org.apache.accumulo.core.util.format.DefaultFormatter; import org.apache.accumulo.core.util.format.Formatter; +import org.apache.accumulo.core.util.format.FormatterConfig; import org.apache.accumulo.tracer.thrift.Annotation; import org.apache.accumulo.tracer.thrift.RemoteSpan; import org.apache.commons.lang.NotImplementedException; @@ -38,14 +39,9 @@ import org.apache.thrift.transport.TMemoryInputTransport; * */ public class TraceFormatter implements Formatter { - public static final String DATE_FORMAT = "yyyy/MM/dd HH:mm:ss.SSS"; + public static final String DATE_FORMAT = DateFormatSupplier.HUMAN_READABLE_FORMAT; // ugh... SimpleDataFormat is not thread safe - private static final ThreadLocal formatter = new ThreadLocal() { - @Override - protected SimpleDateFormat initialValue() { - return new SimpleDateFormat(DATE_FORMAT); - } - }; + private static final DateFormatSupplier formatter = DateFormatSupplier.createSimpleFormatSupplier(DATE_FORMAT); public static String formatDate(final Date date) { return formatter.get().format(date); @@ -54,7 +50,7 @@ public class TraceFormatter implements Formatter { private final static Text SPAN_CF = new Text("span"); private Iterator> scanner; - private boolean printTimeStamps; + private FormatterConfig config; public static RemoteSpan getRemoteSpan(Entry entry) { TMemoryInputTransport transport = new TMemoryInputTransport(entry.getValue().get()); @@ -99,12 +95,12 @@ public class TraceFormatter implements Formatter { } } - if (printTimeStamps) { + if (config.willPrintTimestamps()) { result.append(String.format(" %-12s:%d%n", "timestamp", next.getKey().getTimestamp())); } return result.toString(); } - return DefaultFormatter.formatEntry(next, printTimeStamps); + return DefaultFormatter.formatEntry(next, config.willPrintTimestamps()); } @Override @@ -113,8 +109,8 @@ public class TraceFormatter implements Formatter { } @Override - public void initialize(Iterable> scanner, boolean printTimestamps) { + public void initialize(Iterable> scanner, FormatterConfig config) { this.scanner = scanner.iterator(); - this.printTimeStamps = printTimestamps; + this.config = new FormatterConfig(config); } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/shell/src/main/java/org/apache/accumulo/shell/Shell.java ---------------------------------------------------------------------- diff --git a/shell/src/main/java/org/apache/accumulo/shell/Shell.java b/shell/src/main/java/org/apache/accumulo/shell/Shell.java index 2373437..5c95129 100644 --- a/shell/src/main/java/org/apache/accumulo/shell/Shell.java +++ b/shell/src/main/java/org/apache/accumulo/shell/Shell.java @@ -67,9 +67,9 @@ import org.apache.accumulo.core.tabletserver.thrift.ConstraintViolationException import org.apache.accumulo.core.trace.DistributedTrace; import org.apache.accumulo.core.util.BadArgumentException; import org.apache.accumulo.core.util.DeprecationUtil; -import org.apache.accumulo.core.util.format.BinaryFormatter; import org.apache.accumulo.core.util.format.DefaultFormatter; import org.apache.accumulo.core.util.format.Formatter; +import org.apache.accumulo.core.util.format.FormatterConfig; import org.apache.accumulo.core.util.format.FormatterFactory; import org.apache.accumulo.core.volume.VolumeConfiguration; import org.apache.accumulo.core.zookeeper.ZooUtil; @@ -206,7 +206,6 @@ public class Shell extends ShellOptions implements KeywordExecutable { protected ConsoleReader reader; private AuthenticationToken token; private final Class defaultFormatterClass = DefaultFormatter.class; - private final Class binaryFormatterClass = BinaryFormatter.class; public Map> scanIteratorOptions = new HashMap>(); public Map> iteratorProfiles = new HashMap>(); @@ -1102,22 +1101,14 @@ public class Shell extends ShellOptions implements KeywordExecutable { } } - public final void printRecords(Iterable> scanner, boolean printTimestamps, boolean paginate, Class formatterClass, + public final void printRecords(Iterable> scanner, FormatterConfig config, boolean paginate, Class formatterClass, PrintLine outFile) throws IOException { - printLines(FormatterFactory.getFormatter(formatterClass, scanner, printTimestamps), paginate, outFile); + printLines(FormatterFactory.getFormatter(formatterClass, scanner, config), paginate, outFile); } - public final void printRecords(Iterable> scanner, boolean printTimestamps, boolean paginate, Class formatterClass) + public final void printRecords(Iterable> scanner, FormatterConfig config, boolean paginate, Class formatterClass) throws IOException { - printLines(FormatterFactory.getFormatter(formatterClass, scanner, printTimestamps), paginate); - } - - public final void printBinaryRecords(Iterable> scanner, boolean printTimestamps, boolean paginate, PrintLine outFile) throws IOException { - printLines(FormatterFactory.getFormatter(binaryFormatterClass, scanner, printTimestamps), paginate, outFile); - } - - public final void printBinaryRecords(Iterable> scanner, boolean printTimestamps, boolean paginate) throws IOException { - printLines(FormatterFactory.getFormatter(binaryFormatterClass, scanner, printTimestamps), paginate); + printLines(FormatterFactory.getFormatter(formatterClass, scanner, config), paginate); } public static String repeat(String s, int c) { http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/shell/src/main/java/org/apache/accumulo/shell/commands/DeleteManyCommand.java ---------------------------------------------------------------------- diff --git a/shell/src/main/java/org/apache/accumulo/shell/commands/DeleteManyCommand.java b/shell/src/main/java/org/apache/accumulo/shell/commands/DeleteManyCommand.java index 3400680..b8782f0 100644 --- a/shell/src/main/java/org/apache/accumulo/shell/commands/DeleteManyCommand.java +++ b/shell/src/main/java/org/apache/accumulo/shell/commands/DeleteManyCommand.java @@ -24,6 +24,7 @@ import org.apache.accumulo.core.client.IteratorSetting; import org.apache.accumulo.core.client.Scanner; import org.apache.accumulo.core.iterators.SortedKeyIterator; import org.apache.accumulo.core.security.Authorizations; +import org.apache.accumulo.core.util.format.FormatterConfig; import org.apache.accumulo.core.util.interpret.ScanInterpreter; import org.apache.accumulo.shell.Shell; import org.apache.accumulo.shell.format.DeleterFormatter; @@ -61,7 +62,9 @@ public class DeleteManyCommand extends ScanCommand { // output / delete the records final BatchWriter writer = shellState.getConnector() .createBatchWriter(tableName, new BatchWriterConfig().setTimeout(getTimeout(cl), TimeUnit.MILLISECONDS)); - shellState.printLines(new DeleterFormatter(writer, scanner, cl.hasOption(timestampOpt.getOpt()), shellState, cl.hasOption(forceOpt.getOpt())), false); + FormatterConfig config = new FormatterConfig(); + config.setPrintTimestamps(cl.hasOption(timestampOpt.getOpt())); + shellState.printLines(new DeleterFormatter(writer, scanner, config, shellState, cl.hasOption(forceOpt.getOpt())), false); return 0; } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/shell/src/main/java/org/apache/accumulo/shell/commands/GetSplitsCommand.java ---------------------------------------------------------------------- diff --git a/shell/src/main/java/org/apache/accumulo/shell/commands/GetSplitsCommand.java b/shell/src/main/java/org/apache/accumulo/shell/commands/GetSplitsCommand.java index 9d82269..17b7db4 100644 --- a/shell/src/main/java/org/apache/accumulo/shell/commands/GetSplitsCommand.java +++ b/shell/src/main/java/org/apache/accumulo/shell/commands/GetSplitsCommand.java @@ -36,7 +36,7 @@ import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection; import org.apache.accumulo.core.security.Authorizations; import org.apache.accumulo.core.util.Base64; import org.apache.accumulo.core.util.TextUtil; -import org.apache.accumulo.core.util.format.BinaryFormatter; +import org.apache.accumulo.core.util.format.DefaultFormatter; import org.apache.accumulo.shell.Shell; import org.apache.accumulo.shell.Shell.Command; import org.apache.accumulo.shell.Shell.PrintFile; @@ -102,8 +102,8 @@ public class GetSplitsCommand extends Command { if (text == null) { return null; } - BinaryFormatter.getlength(text.getLength()); - return encode ? Base64.encodeBase64String(TextUtil.getBytes(text)) : BinaryFormatter.appendText(new StringBuilder(), text).toString(); + final int length = text.getLength(); + return encode ? Base64.encodeBase64String(TextUtil.getBytes(text)) : DefaultFormatter.appendText(new StringBuilder(), text, length).toString(); } private static String obscuredTabletName(final KeyExtent extent) { http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/shell/src/main/java/org/apache/accumulo/shell/commands/GrepCommand.java ---------------------------------------------------------------------- diff --git a/shell/src/main/java/org/apache/accumulo/shell/commands/GrepCommand.java b/shell/src/main/java/org/apache/accumulo/shell/commands/GrepCommand.java index 44ee93c..70c5db2 100644 --- a/shell/src/main/java/org/apache/accumulo/shell/commands/GrepCommand.java +++ b/shell/src/main/java/org/apache/accumulo/shell/commands/GrepCommand.java @@ -19,12 +19,12 @@ package org.apache.accumulo.shell.commands; import java.io.IOException; import java.util.Collections; import java.util.concurrent.TimeUnit; - import org.apache.accumulo.core.client.BatchScanner; import org.apache.accumulo.core.client.IteratorSetting; import org.apache.accumulo.core.iterators.user.GrepIterator; import org.apache.accumulo.core.security.Authorizations; import org.apache.accumulo.core.util.format.Formatter; +import org.apache.accumulo.core.util.format.FormatterConfig; import org.apache.accumulo.core.util.interpret.ScanInterpreter; import org.apache.accumulo.shell.Shell; import org.apache.accumulo.shell.Shell.PrintFile; @@ -71,7 +71,9 @@ public class GrepCommand extends ScanCommand { fetchColumns(cl, scanner, interpeter); // output the records - printRecords(cl, shellState, scanner, formatter, printFile); + final FormatterConfig config = new FormatterConfig(); + config.setPrintTimestamps(cl.hasOption(timestampOpt.getOpt())); + printRecords(cl, shellState, config, scanner, formatter, printFile); } finally { scanner.close(); } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/shell/src/main/java/org/apache/accumulo/shell/commands/ScanCommand.java ---------------------------------------------------------------------- diff --git a/shell/src/main/java/org/apache/accumulo/shell/commands/ScanCommand.java b/shell/src/main/java/org/apache/accumulo/shell/commands/ScanCommand.java index c7ab1ff..85cd8e7 100644 --- a/shell/src/main/java/org/apache/accumulo/shell/commands/ScanCommand.java +++ b/shell/src/main/java/org/apache/accumulo/shell/commands/ScanCommand.java @@ -22,7 +22,6 @@ import java.io.UnsupportedEncodingException; import java.util.List; import java.util.Map.Entry; import java.util.concurrent.TimeUnit; - import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.AccumuloSecurityException; import org.apache.accumulo.core.client.IteratorSetting; @@ -37,8 +36,8 @@ import org.apache.accumulo.core.data.Range; import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.iterators.SortedKeyValueIterator; import org.apache.accumulo.core.security.Authorizations; -import org.apache.accumulo.core.util.format.BinaryFormatter; import org.apache.accumulo.core.util.format.Formatter; +import org.apache.accumulo.core.util.format.FormatterConfig; import org.apache.accumulo.core.util.interpret.DefaultScanInterpreter; import org.apache.accumulo.core.util.interpret.ScanInterpreter; import org.apache.accumulo.shell.Shell; @@ -111,24 +110,21 @@ public class ScanCommand extends Command { setupSampling(tableName, cl, shellState, scanner); // output the records + + final FormatterConfig config = new FormatterConfig(); + config.setPrintTimestamps(cl.hasOption(timestampOpt.getOpt())); if (cl.hasOption(showFewOpt.getOpt())) { final String showLength = cl.getOptionValue(showFewOpt.getOpt()); try { final int length = Integer.parseInt(showLength); - if (length < 1) { - throw new IllegalArgumentException(); - } - BinaryFormatter.getlength(length); - printBinaryRecords(cl, shellState, scanner, printFile); + config.setShownLength(length); } catch (NumberFormatException nfe) { shellState.getReader().println("Arg must be an integer."); } catch (IllegalArgumentException iae) { shellState.getReader().println("Arg must be greater than one."); } - - } else { - printRecords(cl, shellState, scanner, formatter, printFile); } + printRecords(cl, shellState, config, scanner, formatter, printFile); if (printFile != null) { printFile.close(); } @@ -190,21 +186,12 @@ public class ScanCommand extends Command { } } - protected void printRecords(final CommandLine cl, final Shell shellState, final Iterable> scanner, + protected void printRecords(final CommandLine cl, final Shell shellState, FormatterConfig config, final Iterable> scanner, final Class formatter, PrintFile outFile) throws IOException { if (outFile == null) { - shellState.printRecords(scanner, cl.hasOption(timestampOpt.getOpt()), !cl.hasOption(disablePaginationOpt.getOpt()), formatter); - } else { - shellState.printRecords(scanner, cl.hasOption(timestampOpt.getOpt()), !cl.hasOption(disablePaginationOpt.getOpt()), formatter, outFile); - } - } - - protected void printBinaryRecords(final CommandLine cl, final Shell shellState, final Iterable> scanner, PrintFile outFile) - throws IOException { - if (outFile == null) { - shellState.printBinaryRecords(scanner, cl.hasOption(timestampOpt.getOpt()), !cl.hasOption(disablePaginationOpt.getOpt())); + shellState.printRecords(scanner, config, !cl.hasOption(disablePaginationOpt.getOpt()), formatter); } else { - shellState.printBinaryRecords(scanner, cl.hasOption(timestampOpt.getOpt()), !cl.hasOption(disablePaginationOpt.getOpt()), outFile); + shellState.printRecords(scanner, config, !cl.hasOption(disablePaginationOpt.getOpt()), formatter, outFile); } } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/shell/src/main/java/org/apache/accumulo/shell/format/DeleterFormatter.java ---------------------------------------------------------------------- diff --git a/shell/src/main/java/org/apache/accumulo/shell/format/DeleterFormatter.java b/shell/src/main/java/org/apache/accumulo/shell/format/DeleterFormatter.java index 1dd2234..275592e 100644 --- a/shell/src/main/java/org/apache/accumulo/shell/format/DeleterFormatter.java +++ b/shell/src/main/java/org/apache/accumulo/shell/format/DeleterFormatter.java @@ -18,7 +18,6 @@ package org.apache.accumulo.shell.format; import java.io.IOException; import java.util.Map.Entry; - import org.apache.accumulo.core.client.BatchWriter; import org.apache.accumulo.core.client.MutationsRejectedException; import org.apache.accumulo.core.data.ConstraintViolationSummary; @@ -27,7 +26,9 @@ import org.apache.accumulo.core.data.Mutation; import org.apache.accumulo.core.data.Value; import org.apache.accumulo.core.security.ColumnVisibility; import org.apache.accumulo.core.util.format.DefaultFormatter; +import org.apache.accumulo.core.util.format.FormatterConfig; import org.apache.accumulo.shell.Shell; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,15 +37,13 @@ public class DeleterFormatter extends DefaultFormatter { private static final Logger log = LoggerFactory.getLogger(DeleterFormatter.class); private BatchWriter writer; private Shell shellState; - private boolean printTimestamps; private boolean force; private boolean more; - public DeleterFormatter(BatchWriter writer, Iterable> scanner, boolean printTimestamps, Shell shellState, boolean force) { - super.initialize(scanner, printTimestamps); + public DeleterFormatter(BatchWriter writer, Iterable> scanner, FormatterConfig config, Shell shellState, boolean force) { + super.initialize(scanner, config); this.writer = writer; this.shellState = shellState; - this.printTimestamps = printTimestamps; this.force = force; this.more = true; } @@ -73,7 +72,7 @@ public class DeleterFormatter extends DefaultFormatter { Entry next = getScannerIterator().next(); Key key = next.getKey(); Mutation m = new Mutation(key.getRow()); - String entryStr = formatEntry(next, printTimestamps); + String entryStr = formatEntry(next, isDoTimestamps()); boolean delete = force; try { if (!force) { http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/shell/src/test/java/org/apache/accumulo/shell/ShellTest.java ---------------------------------------------------------------------- diff --git a/shell/src/test/java/org/apache/accumulo/shell/ShellTest.java b/shell/src/test/java/org/apache/accumulo/shell/ShellTest.java index 95fdc5a..dc902ce 100644 --- a/shell/src/test/java/org/apache/accumulo/shell/ShellTest.java +++ b/shell/src/test/java/org/apache/accumulo/shell/ShellTest.java @@ -31,9 +31,6 @@ import java.util.Date; import java.util.List; import java.util.TimeZone; -import jline.console.ConsoleReader; - -import org.apache.accumulo.core.util.format.DateStringFormatter; import org.apache.log4j.Level; import org.junit.After; import org.junit.Before; @@ -41,6 +38,8 @@ import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import jline.console.ConsoleReader; + public class ShellTest { private static final Logger log = LoggerFactory.getLogger(ShellTest.class); @@ -174,6 +173,8 @@ public class ShellTest { exec("createtable test", true); exec("addsplits 1 \\x80", true); exec("getsplits", true, "1\n\\x80"); + exec("getsplits -m 1", true, "1"); + exec("getsplits -b64", true, "MQ==\ngA=="); exec("deletetable test -f", true, "Table: [test] has been deleted"); } @@ -203,6 +204,36 @@ public class ShellTest { } @Test + public void deleteManyTest() throws IOException { + exec("deletemany", false, "java.lang.IllegalStateException: Not in a table context"); + exec("createtable test", true); + exec("deletemany", true, "\n"); + + exec("insert 0 0 0 0 -ts 0"); + exec("insert 0 0 0 0 -l 0 -ts 0"); + exec("insert 1 1 1 1 -ts 1"); + exec("insert 2 2 2 2 -ts 2"); + + // prompts for delete, and rejects by default + exec("deletemany", true, "[SKIPPED] 0 0:0 []"); + exec("deletemany -r 0", true, "[SKIPPED] 0 0:0 []"); + exec("deletemany -r 0 -f", true, "[DELETED] 0 0:0 []"); + + // with auths, can delete the other record + exec("setauths -s 0"); + exec("deletemany -r 0 -f", true, "[DELETED] 0 0:0 [0]"); + + // delete will show the timestamp + exec("deletemany -r 1 -f -st", true, "[DELETED] 1 1:1 [] 1"); + + // DeleteManyCommand has its own Formatter (DeleterFormatter), so it does not honor the -fm flag + exec("deletemany -r 2 -f -st -fm org.apache.accumulo.core.util.format.DateStringFormatter", true, "[DELETED] 2 2:2 [] 2"); + + exec("setauths -c ", true); + exec("deletetable test -f", true, "Table: [test] has been deleted"); + } + + @Test public void authsTest() throws Exception { Shell.log.debug("Starting auths test --------------------------"); exec("setauths x,y,z", false, "Missing required option"); @@ -251,13 +282,70 @@ public class ShellTest { } @Test + public void scanTimestampTest() throws IOException { + Shell.log.debug("Starting scanTimestamp test ------------------------"); + exec("createtable test", true); + exec("insert r f q v -ts 0", true); + exec("scan -st", true, "r f:q [] 0 v"); + exec("scan -st -f 0", true, " : [] 0 "); + exec("deletemany -f", true); + exec("deletetable test -f", true, "Table: [test] has been deleted"); + } + + @Test + public void scanFewTest() throws IOException { + Shell.log.debug("Starting scanFew test ------------------------"); + exec("createtable test", true); + // historically, showing few did not pertain to ColVis or Timestamp + exec("insert 1 123 123456 -l '12345678' -ts 123456789 1234567890", true); + exec("setauths -s 12345678", true); + String expected = "1 123:123456 [12345678] 123456789 1234567890"; + String expectedFew = "1 123:12345 [12345678] 123456789 12345"; + exec("scan -st", true, expected); + exec("scan -st -f 5", true, expectedFew); + // also prove that BinaryFormatter behaves same as the default + exec("scan -st -fm org.apache.accumulo.core.util.format.BinaryFormatter", true, expected); + exec("scan -st -f 5 -fm org.apache.accumulo.core.util.format.BinaryFormatter", true, expectedFew); + exec("setauths -c", true); + exec("deletetable test -f", true, "Table: [test] has been deleted"); + } + + @Test public void scanDateStringFormatterTest() throws IOException { Shell.log.debug("Starting scan dateStringFormatter test --------------------------"); exec("createtable t", true); exec("insert r f q v -ts 0", true); - DateFormat dateFormat = new SimpleDateFormat(DateStringFormatter.DATE_FORMAT); + @SuppressWarnings("deprecation") + DateFormat dateFormat = new SimpleDateFormat(org.apache.accumulo.core.util.format.DateStringFormatter.DATE_FORMAT); String expected = String.format("r f:q [] %s v", dateFormat.format(new Date(0))); + // historically, showing few did not pertain to ColVis or Timestamp + String expectedFew = expected; + String expectedNoTimestamp = String.format("r f:q [] v"); exec("scan -fm org.apache.accumulo.core.util.format.DateStringFormatter -st", true, expected); + exec("scan -fm org.apache.accumulo.core.util.format.DateStringFormatter -st -f 1000", true, expected); + exec("scan -fm org.apache.accumulo.core.util.format.DateStringFormatter -st -f 5", true, expectedFew); + exec("scan -fm org.apache.accumulo.core.util.format.DateStringFormatter", true, expectedNoTimestamp); + exec("deletetable t -f", true, "Table: [t] has been deleted"); + } + + @Test + public void grepTest() throws IOException { + Shell.log.debug("Starting grep test --------------------------"); + exec("grep", false, "java.lang.IllegalStateException: Not in a table context"); + exec("createtable t", true); + exec("setauths -s vis", true); + exec("insert r f q v -ts 0 -l vis", true); + + String expected = "r f:q [vis] v"; + String expectedTimestamp = "r f:q [vis] 0 v"; + exec("grep", false, "No terms specified"); + exec("grep non_matching_string", true, ""); + // historically, showing few did not pertain to ColVis or Timestamp + exec("grep r", true, expected); + exec("grep r -f 1", true, expected); + exec("grep r -st", true, expectedTimestamp); + exec("grep r -st -f 1", true, expectedTimestamp); + exec("setauths -c", true); exec("deletetable t -f", true, "Table: [t] has been deleted"); } http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/shell/src/test/java/org/apache/accumulo/shell/format/DeleterFormatterTest.java ---------------------------------------------------------------------- diff --git a/shell/src/test/java/org/apache/accumulo/shell/format/DeleterFormatterTest.java b/shell/src/test/java/org/apache/accumulo/shell/format/DeleterFormatterTest.java index d99c0f2..0698beb 100644 --- a/shell/src/test/java/org/apache/accumulo/shell/format/DeleterFormatterTest.java +++ b/shell/src/test/java/org/apache/accumulo/shell/format/DeleterFormatterTest.java @@ -34,16 +34,16 @@ import java.io.InputStream; import java.util.Collections; import java.util.Map; import java.util.TreeMap; - -import jline.UnsupportedTerminal; -import jline.console.ConsoleReader; - import org.apache.accumulo.core.client.BatchWriter; import org.apache.accumulo.core.client.MutationsRejectedException; import org.apache.accumulo.core.data.Key; import org.apache.accumulo.core.data.Mutation; import org.apache.accumulo.core.data.Value; +import org.apache.accumulo.core.util.format.FormatterConfig; import org.apache.accumulo.shell.Shell; + +import jline.UnsupportedTerminal; +import jline.console.ConsoleReader; import org.junit.Before; import org.junit.Test; @@ -99,13 +99,13 @@ public class DeleterFormatterTest { @Test public void testEmpty() { - formatter = new DeleterFormatter(writer, Collections. emptyMap().entrySet(), true, shellState, true); + formatter = new DeleterFormatter(writer, Collections. emptyMap().entrySet(), new FormatterConfig().setPrintTimestamps(true), shellState, true); assertFalse(formatter.hasNext()); } @Test public void testSingle() throws IOException { - formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, true); + formatter = new DeleterFormatter(writer, data.entrySet(), new FormatterConfig().setPrintTimestamps(true), shellState, true); assertTrue(formatter.hasNext()); assertNull(formatter.next()); @@ -117,7 +117,7 @@ public class DeleterFormatterTest { public void testNo() throws IOException { input.set("no\n"); data.put(new Key("z"), new Value("v2".getBytes(UTF_8))); - formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, false); + formatter = new DeleterFormatter(writer, data.entrySet(), new FormatterConfig().setPrintTimestamps(true), shellState, false); assertTrue(formatter.hasNext()); assertNull(formatter.next()); @@ -131,7 +131,7 @@ public class DeleterFormatterTest { public void testNoConfirmation() throws IOException { input.set(""); data.put(new Key("z"), new Value("v2".getBytes(UTF_8))); - formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, false); + formatter = new DeleterFormatter(writer, data.entrySet(), new FormatterConfig().setPrintTimestamps(true), shellState, false); assertTrue(formatter.hasNext()); assertNull(formatter.next()); @@ -145,7 +145,7 @@ public class DeleterFormatterTest { public void testYes() throws IOException { input.set("y\nyes\n"); data.put(new Key("z"), new Value("v2".getBytes(UTF_8))); - formatter = new DeleterFormatter(writer, data.entrySet(), true, shellState, false); + formatter = new DeleterFormatter(writer, data.entrySet(), new FormatterConfig().setPrintTimestamps(true), shellState, false); assertTrue(formatter.hasNext()); assertNull(formatter.next()); @@ -158,7 +158,7 @@ public class DeleterFormatterTest { @Test public void testMutationException() { - formatter = new DeleterFormatter(exceptionWriter, data.entrySet(), true, shellState, true); + formatter = new DeleterFormatter(exceptionWriter, data.entrySet(), new FormatterConfig().setPrintTimestamps(true), shellState, true); assertTrue(formatter.hasNext()); assertNull(formatter.next()); http://git-wip-us.apache.org/repos/asf/accumulo/blob/f7b9fd40/test/src/main/java/org/apache/accumulo/test/ShellServerIT.java ---------------------------------------------------------------------- diff --git a/test/src/main/java/org/apache/accumulo/test/ShellServerIT.java b/test/src/main/java/org/apache/accumulo/test/ShellServerIT.java index f2dcd4b..28112ac 100644 --- a/test/src/main/java/org/apache/accumulo/test/ShellServerIT.java +++ b/test/src/main/java/org/apache/accumulo/test/ShellServerIT.java @@ -62,6 +62,7 @@ import org.apache.accumulo.core.file.FileSKVWriter; import org.apache.accumulo.core.metadata.MetadataTable; import org.apache.accumulo.core.security.Authorizations; import org.apache.accumulo.core.util.format.Formatter; +import org.apache.accumulo.core.util.format.FormatterConfig; import org.apache.accumulo.harness.SharedMiniClusterBase; import org.apache.accumulo.shell.Shell; import org.apache.accumulo.test.functional.SlowIterator; @@ -1212,7 +1213,7 @@ public class ShellServerIT extends SharedMiniClusterBase { */ public static class HexFormatter implements Formatter { private Iterator> iter = null; - private boolean printTs = false; + private FormatterConfig config; private final static String tab = "\t"; private final static String newline = "\n"; @@ -1231,7 +1232,7 @@ public class ShellServerIT extends SharedMiniClusterBase { String key; // Observe the timestamps - if (printTs) { + if (config.willPrintTimestamps()) { key = entry.getKey().toString(); } else { key = entry.getKey().toStringNoTime(); @@ -1257,9 +1258,9 @@ public class ShellServerIT extends SharedMiniClusterBase { public void remove() {} @Override - public void initialize(final Iterable> scanner, final boolean printTimestamps) { + public void initialize(final Iterable> scanner, final FormatterConfig config) { this.iter = scanner.iterator(); - this.printTs = printTimestamps; + this.config = new FormatterConfig(config); } }