Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions core/src/main/java/org/apache/accumulo/core/data/Mutation.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package org.apache.accumulo.core.data;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.requireNonNull;

import java.io.DataInput;
Expand Down Expand Up @@ -1772,4 +1773,35 @@ protected SERIALIZED_FORMAT getSerializedFormat() {
return this.useOldDeserialize ? SERIALIZED_FORMAT.VERSION1 : SERIALIZED_FORMAT.VERSION2;
}

/**
* Creates a multi-lined, human-readable String for this mutation.
*
* This method creates many intermediate Strings and should not be used for large volumes of
* Mutations.
*
* @return A multi-lined, human-readable String for this mutation.
*
* @since 2.1.0
*/
public String prettyPrint() {
StringBuilder sb = new StringBuilder();

sb.append("mutation: ").append(new String(row, UTF_8)).append('\n');
for (ColumnUpdate update : getUpdates()) {
sb.append(" update: ");
sb.append(new String(update.getColumnFamily(), UTF_8));
sb.append(':');
sb.append(new String(update.getColumnQualifier(), UTF_8));
sb.append(" value ");

if (update.isDeleted()) {
sb.append("[delete]");
} else {
sb.append(new String(update.getValue(), UTF_8));
}
sb.append('\n');
}

return sb.toString();
}
}
20 changes: 20 additions & 0 deletions core/src/test/java/org/apache/accumulo/core/data/MutationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -920,4 +920,24 @@ public void testSanityCheck() {
m.estRowAndLargeValSize += (Long.MAX_VALUE / 2);
m.put("cf", "cq2", "v");
}

@Test
public void testPrettyPrint() {
String row = "row";
String fam1 = "fam1";
String fam2 = "fam2";
String qual1 = "qual1";
String qual2 = "qual2";
String value1 = "value1";

Mutation m = new Mutation("row");
m.put(fam1, qual1, value1);
m.putDelete(fam2, qual2);
m.getUpdates(); // serialize

String expected = "mutation: " + row + "\n update: " + fam1 + ":" + qual1 + " value " + value1
+ "\n update: " + fam2 + ":" + qual2 + " value [delete]\n";

assertEquals(expected, m.prettyPrint());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,27 +144,32 @@ private static void update(ServerContext context, Mutation m, KeyExtent extent)
public static void update(ServerContext context, ServiceLock zooLock, Mutation m,
KeyExtent extent) {
Writer t = extent.isMeta() ? getRootTable(context) : getMetadataTable(context);
update(context, t, zooLock, m);
update(context, t, zooLock, m, extent);
}

public static void update(ServerContext context, Writer t, ServiceLock zooLock, Mutation m) {
public static void update(ServerContext context, Writer t, ServiceLock zooLock, Mutation m,
KeyExtent extent) {
if (zooLock != null)
putLockID(context, zooLock, m);
while (true) {
try {
t.update(m);
return;
} catch (AccumuloException | TableNotFoundException | AccumuloSecurityException e) {
log.error("{}", e.getMessage(), e);
logUpdateFailure(m, extent, e);
} catch (ConstraintViolationException e) {
log.error("{}", e.getMessage(), e);
logUpdateFailure(m, extent, e);
// retrying when a CVE occurs is probably futile and can cause problems, see ACCUMULO-3096
throw new RuntimeException(e);
}
sleepUninterruptibly(1, TimeUnit.SECONDS);
}
}

private static void logUpdateFailure(Mutation m, KeyExtent extent, Exception e) {
log.error("Failed to write metadata updates for extent {} {}", extent, m.prettyPrint(), e);
}

public static void updateTabletFlushID(KeyExtent extent, long flushID, ServerContext context,
ServiceLock zooLock) {
TabletMutator tablet = context.getAmple().mutateTablet(extent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void test() throws Exception {
m.put("badcolfam", "badcolqual", "3");

try {
MetadataTableUtil.update(context, w, null, m);
MetadataTableUtil.update(context, w, null, m, extent);
} catch (RuntimeException e) {
if (e.getCause().getClass().equals(ConstraintViolationException.class)) {
throw (ConstraintViolationException) e.getCause();
Expand Down