Repository: giraph Updated Branches: refs/heads/trunk fda1bb382 -> 8675c84a8
http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/gui/js/valpanel.js ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/gui/js/valpanel.js b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/gui/js/valpanel.js new file mode 100644 index 0000000..98da751 --- /dev/null +++ b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/gui/js/valpanel.js @@ -0,0 +1,430 @@ +/* + * ValidationPanel is a class that abstracts the message, vertex + * and exception details. It has three view modes - compact, preview and expanded. + * @param {container, resizeCallback} options - Initialize panel with these options. + * @param options.validationPanelContainer - Container of the panel. + * @param {callback} options.resizeCallback - Called when manual resize of the panel is complete. + * @param {object} options.editor - Reference to the graph editor object. + */ +function ValidationPanel(options) { + // JSON object of the buttons appearing. + // The key, i.e. M, E, V are used in the compact mode + this.buttonData = { + 'M' : { + fullName : 'Message Integrity', + clickHandler : this.showMessageViolations.bind(this) + }, + 'E' : { + fullName : 'Exceptions', + clickHandler : this.showExceptions.bind(this) + }, + 'V' : { + fullName : 'Vertex Integrity', + clickHandler : this.showVertexViolations.bind(this) + } + } + + // Both in px + this.compactWidth = 60; + this.previewWidth = 170; + // This is in % + this.expandWidth = 55; + this.state = ValidationPanel.StateEnum.COMPACT; + this.container = options.container; + this.resizeCallback = options.resizeCallback; + this.debuggerServerRoot = options.debuggerServerRoot; + this.editor = options.editor; + // Which label is currently being shown + this.currentLabel = null; + + $(this.container).css('height', this.height + 'px') + // Make it resizable horizontally + $(this.container).resizable({ handles : 'e', minWidth : this.previewWidth, + stop: (function(event, ui) { + this.resizeCallback(); + }).bind(this) + }); + this.initElements(); + this.compact(); +} + +ValidationPanel.StateEnum = { + COMPACT : 'compact', + PREVIEW : 'preview', + EXPAND : 'expand' +} + +/* + * Deferred callbacks for capture scenario + */ +ValidationPanel.prototype.onCaptureVertex = function(done, fail) { + this.onCaptureVertex.done = done; + this.onCaptureVertex.fail = fail; +} + +/* + * Creates HTML elements for valpanel. + */ +ValidationPanel.prototype.initElements = function() { + // Div to host the right arrow and close button on the top right. + var iconsContainer = $('<div />') + .attr('class', 'valpanel-icons-container') + .appendTo(this.container) + + // Create a right-pointed arrow + this.rightArrow = $('<span />') + .attr('class', 'glyphicon glyphicon-circle-arrow-right') + .appendTo(iconsContainer); + + // Create a close button - Clicking it will compact the panel. + this.btnClose = $('<span />') + .attr('class', 'glyphicon glyphicon-remove valpanel-btn-close') + .click((function() { + this.compact(); + }).bind(this)) + .hide() + .appendTo(iconsContainer); + + // Create all the buttons. + this.btnContainer = $('<ul />') + .attr('class', 'list-unstyled valpanel-btn-container') + .appendTo(this.container); + + // This is the container for the main content. + this.contentContainer = $('<div />') + .attr('class', 'valpanel-content-container') + .hide() + .appendTo(this.container); + + // Preloader reference. + this.preloader = $('<div />') + .attr('class', 'valpanel-preloader') + .hide() + .appendTo(this.container); + + for (var label in this.buttonData) { + var button = $('<button />') + .attr('class', 'btn btn-success btn-valpanel') + .attr('id', this.btnLabelToId(label)) + .attr('disabled', 'true') + .click(this.buttonData[label]['clickHandler']); + var iconSpan = $('<span />') + .appendTo(button); + var textSpan = $("<span />") + .html(' ' + label) + .appendTo(button); + // Associate this physical button element with the cache entry. + this.buttonData[label].button = button; + this.buttonData[label].iconSpan = iconSpan; + this.buttonData[label].textSpan = textSpan; + $(this.btnContainer).append( + $("<li />").append(button) + ); + } +} + +ValidationPanel.prototype.btnLabelToId = function(label) { + return 'btn-valpanel-' + label; +} + +/* + * Expands the width of the panel to show full names of each of the buttons. + */ +ValidationPanel.prototype.preview = function() { + if (!$(this.container).is(':animated')) { + // Set state to preview. + this.btnContainer.removeClass(this.state); + this.state = ValidationPanel.StateEnum.PREVIEW; + this.btnContainer.addClass(this.state); + $(this.btnClose).hide(); + $(this.contentContainer).hide(); + $(this.container).animate({ width: this.previewWidth + 'px'}, 300, + (function() { + this.resizeCallback(); + }).bind(this)); + + // Expand names to full names + for (var label in this.buttonData) { + var buttonData = this.buttonData[label]; + $(buttonData.textSpan).html(buttonData.fullName); + } + } +} + +/* + * Compacts the width of the panel to show only the labels of the buttons. + */ +ValidationPanel.prototype.compact = function() { + if (!$(this.container).is(':animated')) { + var prevState = this.state; + this.currentLabel = null; + this.state = ValidationPanel.StateEnum.COMPACT; + // Uncolor all editor nodes + this.editor.colorNodes([], null /* not required */, true); + $(this.btnClose).hide(); + $(this.rightArrow).show(); + $(this.contentContainer).hide(); + $(this.container).animate({ width: this.compactWidth + 'px'}, 300, + (function() { + // Compact names to labels. + for (var label in this.buttonData) { + var buttonData = this.buttonData[label]; + $(buttonData.textSpan).html(label); + } + this.btnContainer.removeClass(prevState); + this.btnContainer.addClass(this.state); + this.resizeCallback(); + }).bind(this)); + } +} + +ValidationPanel.prototype.expand = function() { + this.btnContainer.removeClass(this.state); + this.state = ValidationPanel.StateEnum.EXPAND; + this.btnContainer.addClass(this.state); + // Show close button, hide right arrow, show content. + $(this.btnClose).show(); + $(this.rightArrow).hide(); + $(this.container).animate({ width: this.expandWidth + '%'}, 500, + (function() { + $(this.contentContainer).show('slow'); + this.resizeCallback(); + }).bind(this)); +} + +/* + * Fetch the message integrity violations from the debugger server + * and construct a table to show the data. + */ +ValidationPanel.prototype.showMessageViolations = function() { + this.expand(); + this.currentLabel = 'M'; + // Empty the content container and add violations table. + this.contentContainer.empty(); + // The data should already be present in the buttonData cache. + var data = this.buttonData[this.currentLabel].data; + var table = $("<table />") + .attr('class', 'table') + .attr('id', 'valpanel-M-table') + .html('<thead><tr><th>Source ID</th><th>Destination ID</th><th>Message</th><th></th></tr></thead>') + .appendTo(this.contentContainer); + + var btnCaptureScenario = + $('<button type="button" class="btn btn-sm btn-primary btn-vp-M-capture">Capture Scenario</button>'); + + var dataTable = $(table).DataTable({ + 'columns' : [ + { 'data' : 'srcId' }, + { 'data' : 'destinationId' }, + { 'data' : 'message' }, + { + 'orderable' : false, + 'data' : null, + 'defaultContent' : $(btnCaptureScenario).prop('outerHTML') + }, + ] + }); + if (data) { + for (var taskId in data) { + var violations = data[taskId].violations; + for (var i = 0; violations && i < violations.length; ++i) { + var violation = violations[i]; + violation.superstepId = this.superstepId; + dataTable.row.add(violation).draw(); + } + } + } + // Attach click event to the capture Scenario button. + $('button.btn-vp-M-capture').click((function(event) { + var tr = $(event.target).parents('tr'); + var row = dataTable.row(tr); + var data = row.data(); + Utils.fetchVertexTest(this.debuggerServerRoot, this.jobId, + this.superstepId, data.srcId, 'msg') + .done((function(response) { + this.onCaptureVertex.done(response); + }).bind(this)) + .fail((function(response) { + this.onCaptureVertex.fail(response.responseText); + }).bind(this)) + }).bind(this)); +} + +/* + * Fetch vertex value violations from the server and + * construct a table to show the data. + */ +ValidationPanel.prototype.showVertexViolations = function() { + this.expand(); + this.currentLabel = 'V'; + var data = this.buttonData[this.currentLabel].data; + // Empty the content container and add violations table. + this.contentContainer.empty(); + var table = $("<table />") + .attr('class', 'table') + .attr('id', 'valpanel-V-table') + .html('<thead><tr><th>Vertex ID</th><th>Vertex Value</th><th></th></tr></thead>') + .appendTo(this.contentContainer); + + var btnCaptureScenario = + $('<button type="button" class="btn btn-sm btn-primary btn-vp-V-capture">Capture Scenario</button>'); + + var dataTable = $(table).DataTable({ + 'columns' : [ + { 'data' : 'vertexId' }, + { 'data' : 'vertexValue' }, + { + 'orderable' : false, + 'data' : null, + 'defaultContent' : $(btnCaptureScenario).prop('outerHTML') + }, + ] + }); + var violationIds = []; + if (data) { + for (var vertexId in data) { + var violation = data[vertexId]; + violation.superstepId = this.superstepId; + dataTable.row.add(violation).draw(); + violationIds.push(vertexId); + } + } + // Attach click event to the capture Scenario button. + $('button.btn-vp-V-capture').click((function(event) { + var tr = $(event.target).parents('tr'); + var row = dataTable.row(tr); + var data = row.data(); + Utils.fetchVertexTest(this.debuggerServerRoot, this.jobId, + this.superstepId, data.vertexId, 'vv') + .done((function(response) { + this.onCaptureVertex.done(response); + }).bind(this)) + .fail((function(response) { + this.onCaptureVertex.fail(response.responseText); + }).bind(this)) + }).bind(this)); + // Color the vertices with violations + this.editor.colorNodes(violationIds, this.editor.errorColor, true); +} + +/* + * Show exceptions for this superstep. + */ +ValidationPanel.prototype.showExceptions = function() { + this.expand(); + this.currentLabel = 'E'; + var data = this.buttonData[this.currentLabel].data; + // Empty the content container and add violations table. + // TODO(vikesh) Master exceptions. + this.contentContainer.empty(); + var table = $("<table />") + .attr('class', 'table') + .attr('id', 'valpanel-V-table') + .html('<thead><tr><th>Vertex ID</th><th>Message</th><th>Stack Trace</th><th></th></tr></thead>') + .appendTo(this.contentContainer); + + var btnCaptureScenario = + $('<button type="button" class="btn btn-sm btn-primary btn-vp-E-capture">Capture Scenario</button>'); + + var dataTable = $(table).DataTable({ + 'columns' : [ + { 'data' : 'vertexId' }, + { 'data' : 'exception.message' }, + { 'data' : 'exception.stackTrace' }, + { + 'orderable' : false, + 'data' : null, + 'defaultContent' : $(btnCaptureScenario).prop('outerHTML') + } + ] + }); + var violationIds = []; + if (data) { + for (var vertexId in data) { + var violation = data[vertexId]; + violation.superstepId = this.superstepId; + dataTable.row.add(violation).draw(); + violationIds.push(vertexId); + } + } + // Attach click event to the capture Scenario button. + $('button.btn-vp-E-capture').click((function(event) { + var tr = $(event.target).parents('tr'); + var row = dataTable.row(tr); + var data = row.data(); + Utils.fetchVertexTest(this.debuggerServerRoot, this.jobId, + this.superstepId, data.vertexId, 'err') + .done((function(response) { + this.onCaptureVertex.done(response); + }).bind(this)) + .fail((function(response) { + this.onCaptureVertex.fail(response.responseText); + }).bind(this)) + }).bind(this)); + // Color the nodes with exception. + this.editor.colorNodes(violationIds, this.editor.errorColor, true); +} + +/* + * Handle the received data from the debugger server. + */ +ValidationPanel.prototype.onReceiveData = function(buttonType) { + return (function(response) { + // Data is set here. The click handlers will simply use this data. + this.buttonData[buttonType].data = response; + this.buttonData[buttonType].button.attr('disabled', false); + // No violations. + if($.isEmptyObject(response)) { + this.buttonData[buttonType].button.addClass('btn-success'); + this.buttonData[buttonType].button.removeClass('btn-danger'); + } else { + this.buttonData[buttonType].button.addClass('btn-danger'); + this.buttonData[buttonType].button.removeClass('btn-success'); + } + // If this is the currently selected label, update the contents. + if (buttonType === this.currentLabel) { + this.buttonData[buttonType].clickHandler(); + } + }).bind(this); +} + +/* + * Sets the current jobId and superstepId. Expected to called by the + * orchestrator (debugger.js) while stepping through the job. + * @param {jobId, superstepId} data + * @param data.jobId - Current jobId + * @param data.superstepId - Current superstepId + */ +ValidationPanel.prototype.setData = function(jobId, superstepId) { + this.jobId = jobId; + this.superstepId = superstepId; + + // setData makes AJAX calls to the debugger server for each button type + for (var type in this.buttonData) { + // Disable all buttons to begin with + this.buttonData[type].button.attr('disabled', true); + $.ajax({ + url: this.debuggerServerRoot + '/integrity', + data: {'jobId' : this.jobId, 'superstepId' : this.superstepId, 'type' : type} + }) + .retry({ + times: 3, + timeout: 1000, + }) + .done(this.onReceiveData(type)) + .fail((function(buttonLabel) { + return function(response) { + noty({text : 'Failed to fetch data for ' + buttonLabel + + '. Please check your network and debugger server.', type : 'error'}); + } + })(this.buttonData[type].fullName)) + } +} + +ValidationPanel.prototype.showPreloader = function() { + this.preloader.show('slow'); +} + +ValidationPanel.prototype.hidePreloader = function() { + this.preloader.hide('slow'); +} http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeSetUpFuncTemplate.vm ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeSetUpFuncTemplate.vm b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeSetUpFuncTemplate.vm new file mode 100644 index 0000000..4ac8e1f --- /dev/null +++ b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeSetUpFuncTemplate.vm @@ -0,0 +1,14 @@ + @Before + public void setUp() throws Exception { + GiraphConfiguration config = new GiraphConfiguration(); + config.setComputationClass($classUnderTestName#[[.class]]#); + GiraphConfiguration.VERTEX_ID_CLASS.set(config, $vertexIdType#[[.class]]#); + GiraphConfiguration.VERTEX_VALUE_CLASS.set(config, $vertexValueType#[[.class]]#); + GiraphConfiguration.EDGE_VALUE_CLASS.set(config, $edgeValueType#[[.class]]#); + GiraphConfiguration.INCOMING_MESSAGE_VALUE_CLASS.set(config, $inMsgType#[[.class]]#); + GiraphConfiguration.OUTGOING_MESSAGE_VALUE_CLASS.set(config, $outMsgType#[[.class]]#); +#foreach( $config in $configs ) + config.set#evaluate($config.classStr)("$config.key", $helper.format($config.value)); +#end + conf = new ImmutableClassesGiraphConfiguration<>(config); + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeTestFuncTemplate.vm ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeTestFuncTemplate.vm b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeTestFuncTemplate.vm new file mode 100644 index 0000000..3b3db4b --- /dev/null +++ b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeTestFuncTemplate.vm @@ -0,0 +1,55 @@ + @Test + public final void testCompute() { + try { + $classUnderTestName classUnderTest = ($classUnderTestName) conf.createComputation(); + + GraphState graphState = mock(GraphState.class); + when(graphState.getSuperstep()).thenReturn($superstepNo#[[l]]#); + when(graphState.getTotalNumVertices()).thenReturn($nVertices#[[l]]#); + when(graphState.getTotalNumEdges()).thenReturn($nEdges#[[l]]#); + + WorkerClientRequestProcessor<$vertexIdType, $vertexValueType, $edgeValueType> processor = + mock(WorkerClientRequestProcessor.class); + + WorkerAggregatorUsage aggr = mock(WorkerAggregatorUsage.class); +#foreach ($aggr in $aggregators) + when(aggr.getAggregatedValue("$aggr.key")).thenReturn($helper.formatWritable($aggr.value)); +#end + + classUnderTest.initialize(graphState, processor, null, aggr, null); + + Vertex<$vertexIdType, $vertexValueType, $edgeValueType> vertex = conf.createVertex(); + vertex.initialize($helper.formatWritable($vertexId), $helper.formatWritable($vertexValue)); + +#if ($neighbors) + ReusableEdge<$vertexIdType, $edgeValueType> edge = conf.createReusableEdge(); +#foreach ($neighbor in $neighbors) + edge.setTargetVertexId($helper.formatWritable($neighbor.NbrId)); +#if ($neighbor.edgeValue) + edge.setValue($helper.formatWritable($neighbor.edgeValue)); +#end + vertex.addEdge(edge); +#end +#end + + ArrayList<$inMsgType> inMsgs = new ArrayList<>(); +#foreach ($inMsg in $inMsgs) + inMsgs.add($helper.formatWritable($inMsg)); +#end + + classUnderTest.compute(vertex, inMsgs); + +#if ($vertexValueAfter) + // assertEquals($vertexValueAfter, vertex.getValue().get(), 0.001f); +#end + + // verifyZeroInteractions(processor); + +#foreach ($outMsg in $outMsgs) + // verify(processor, times($outMsg.times)).sendMessageRequest($helper.formatWritable($outMsg.msg.destinationId), $helper.formatWritable($outMsg.msg.Message)); +#end + + } catch (IOException e) { + e.printStackTrace(); + } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeTestTemplate.vm ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeTestTemplate.vm b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeTestTemplate.vm new file mode 100644 index 0000000..e4b68e0 --- /dev/null +++ b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ComputeTestTemplate.vm @@ -0,0 +1,41 @@ +#if ($package) +package $package; +#end + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.io.IOException; +import java.util.ArrayList; + +import org.apache.giraph.comm.WorkerClientRequestProcessor; +import org.apache.giraph.conf.GiraphConfiguration; +import org.apache.giraph.conf.ImmutableClassesGiraphConfiguration; +import org.apache.giraph.edge.ReusableEdge; +import org.apache.giraph.graph.GraphState; +import org.apache.giraph.graph.Vertex; +import org.apache.giraph.utils.WritableUtils; +import org.apache.giraph.worker.WorkerAggregatorUsage; +import org.junit.Before; +import org.junit.Test; + +import $classUnderTestFullName; +#if ($usedTypes) +#foreach ($type in $usedTypes) +import $type.Name; +#end +#end + +public class $className { + + private ImmutableClassesGiraphConfiguration<$vertexIdType, $vertexValueType, $edgeValueType> conf; + +#parse("ComputeTestFuncTemplate.vm") + + +#parse("ComputeSetUpFuncTemplate.vm") + + +#parse("ReadWritableFromByteArrayTemplate.vm") + +} http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/MasterComputeTestTemplate.vm ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/MasterComputeTestTemplate.vm b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/MasterComputeTestTemplate.vm new file mode 100644 index 0000000..723fc97 --- /dev/null +++ b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/MasterComputeTestTemplate.vm @@ -0,0 +1,57 @@ +#if ($package) +package $package; +#end + +import static org.mockito.Mockito.*; + +import org.junit.Test; +import org.apache.giraph.conf.GiraphConfiguration; +import org.apache.giraph.conf.ImmutableClassesGiraphConfiguration; +import org.apache.giraph.graph.GraphState; +import org.apache.giraph.bsp.CentralizedServiceMaster; +import org.apache.giraph.master.MasterAggregatorHandler; + +import $classUnderTestFullName; +#if ($usedTypesByAggregators) +#foreach ($type in $usedTypesByAggregators) +import $type.Name; +#end +#end + +public class $className { + + @Test + public void test() { + GiraphConfiguration config = new GiraphConfiguration(); + config.setMasterComputeClass($classUnderTestName#[[.class]]#); + setupConfiguration(config); + ImmutableClassesGiraphConfiguration conf = new ImmutableClassesGiraphConfiguration<>(config); + + $classUnderTestName classUnderTest = ($classUnderTestName) conf.createMasterCompute(); + + GraphState graphState = mock(GraphState.class); + when(graphState.getSuperstep()).thenReturn($superstepNo#[[l]]#); + when(graphState.getTotalNumVertices()).thenReturn($nVertices#[[l]]#); + when(graphState.getTotalNumEdges()).thenReturn($nEdges#[[l]]#); + classUnderTest.setGraphState(graphState); + + MasterAggregatorHandler aggregatorHandler = mock(MasterAggregatorHandler.class); +#foreach ($aggr in $aggregators) + when(aggregatorHandler.getAggregatedValue("$aggr.key")).thenReturn($helper.formatWritable($aggr.value)); +#end + CentralizedServiceMaster serviceMaster = mock(CentralizedServiceMaster.class); + when(serviceMaster.getAggregatorHandler()).thenReturn(aggregatorHandler); + classUnderTest.setMasterService(serviceMaster); + + classUnderTest.compute(); + } + + + #parse("ReadWritableFromStringTemplate.vm") + + public void setupConfiguration(GiraphConfiguration config) { +#foreach( $config in $configs ) + config.set#evaluate($config.classStr)("$config.key", $helper.format($config.value)); +#end + } +} http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ReadWritableFromByteArrayTemplate.vm ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ReadWritableFromByteArrayTemplate.vm b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ReadWritableFromByteArrayTemplate.vm new file mode 100644 index 0000000..bc67347 --- /dev/null +++ b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ReadWritableFromByteArrayTemplate.vm @@ -0,0 +1,16 @@ +#if ($complexWritables) +#foreach ($class in $complexWritables) +#set ($writableClassName = $class.simpleName) + private $writableClassName read$writableClassName#[[FromByteArray]]#(byte[] byteArray) { + $writableClassName writable = null; + try { + writable = $writableClassName#[[.class.newInstance();]]# + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + WritableUtils.readFieldsFromByteArray(byteArray, writable); + return writable; + } + +#end +#end \ No newline at end of file http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ReadWritableFromStringTemplate.vm ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ReadWritableFromStringTemplate.vm b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ReadWritableFromStringTemplate.vm new file mode 100644 index 0000000..dcf2ada --- /dev/null +++ b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/ReadWritableFromStringTemplate.vm @@ -0,0 +1,16 @@ +#if ($complexWritables) +#foreach ($class in $complexWritables) +#set ($writableClassName = $class.simpleName) + private $writableClassName read$writableClassName#[[FromString]]#(String str) { + $writableClassName writable = null; + try { + writable = $writableClassName#[[.class.newInstance();]]# + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + WritableUtils.readFieldsFromByteArray(str.getBytes(), writable); + return writable; + } + +#end +#end \ No newline at end of file http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/TestGraphTemplate.vm ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/TestGraphTemplate.vm b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/TestGraphTemplate.vm new file mode 100644 index 0000000..a97a031 --- /dev/null +++ b/giraph-debugger/src/main/resources/org/apache/giraph/debugger/mock/TestGraphTemplate.vm @@ -0,0 +1,10 @@ + TestGraph<$vertexIdClass, $vertexValueClass, $edgeValueClass> graph + = new TestGraph<>(new GiraphConfiguration()); + graph +#foreach ($vertex in $vertices) + .addVertex($helper.formatWritable($vertex.id), $helper.formatWritable($vertex.value)) +#foreach ($neighbor in $vertex.neighbors) + .addEdge($helper.formatWritable($vertex.id), $helper.formatWritable($neighbor.id), $helper.formatWritable($neighbor.edgeValue)) +#end +#end + ; \ No newline at end of file http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/BaseComputation.java ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/BaseComputation.java b/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/BaseComputation.java new file mode 100644 index 0000000..b8f9d1a --- /dev/null +++ b/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/BaseComputation.java @@ -0,0 +1,61 @@ +/* + * 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.giraph.debugger.instrumenter.test.basecompute; + +import java.io.IOException; + +import org.apache.giraph.graph.BasicComputation; +import org.apache.giraph.graph.Vertex; +import org.apache.hadoop.io.DoubleWritable; +import org.apache.hadoop.io.FloatWritable; +import org.apache.hadoop.io.LongWritable; + +/** + * TODO(semih, jaeho): What's this class used for? + */ +public abstract class BaseComputation extends BasicComputation<LongWritable, + DoubleWritable, FloatWritable, DoubleWritable> { + + @Override + public final void compute( + Vertex<LongWritable, DoubleWritable, FloatWritable> vertex, + Iterable<DoubleWritable> messages) throws IOException { + collect(vertex, messages); + signal(vertex, messages); + vertex.voteToHalt(); + } + + /** + * TODO(semih, jaeho): Fill in. + * @param vertex + * @param messages + */ + protected abstract void signal( + Vertex<LongWritable, DoubleWritable, FloatWritable> vertex, + Iterable<DoubleWritable> messages); + + /** + * TODO(semih, jaeho): Fill in. + * @param vertex + * @param messages + */ + protected abstract void collect( + Vertex<LongWritable, DoubleWritable, FloatWritable> vertex, + Iterable<DoubleWritable> messages); + +} http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/CommonDebugConfig.java ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/CommonDebugConfig.java b/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/CommonDebugConfig.java new file mode 100644 index 0000000..7e55727 --- /dev/null +++ b/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/CommonDebugConfig.java @@ -0,0 +1,36 @@ +/* + * 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.giraph.debugger.instrumenter.test.basecompute; + +import org.apache.giraph.debugger.DebugConfig; +import org.apache.hadoop.io.DoubleWritable; +import org.apache.hadoop.io.FloatWritable; +import org.apache.hadoop.io.LongWritable; + +/** + * TODO(semih, jaeho): What's this class used for? + */ +public class CommonDebugConfig extends DebugConfig<LongWritable, + DoubleWritable, FloatWritable, DoubleWritable, DoubleWritable> { + + @Override + public boolean shouldCatchExceptions() { + return true; + } + +} http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/DerivedComputation.java ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/DerivedComputation.java b/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/DerivedComputation.java new file mode 100644 index 0000000..78e8f4c --- /dev/null +++ b/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/DerivedComputation.java @@ -0,0 +1,99 @@ +/* + * 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.giraph.debugger.instrumenter.test.basecompute; + +import org.apache.giraph.conf.LongConfOption; +import org.apache.giraph.edge.Edge; +import org.apache.giraph.graph.BasicComputation; +import org.apache.giraph.graph.Vertex; +import org.apache.hadoop.io.DoubleWritable; +import org.apache.hadoop.io.FloatWritable; +import org.apache.hadoop.io.LongWritable; +import org.apache.log4j.Logger; + +/** + * TODO(semih, jaeho): What's this class used for? + */ +public class DerivedComputation extends BaseComputation { + + /** + * The shortest paths id. + */ + public static final LongConfOption SOURCE_ID = new LongConfOption( + "SimpleShortestPathsVertex.sourceId", 1, "The shortest paths id"); + + /** + * Class logger. + */ + private static final Logger LOG = Logger.getLogger(BasicComputation.class); + + /** + * Minimum distance found so far. Kept as a global variable for efficiency. + */ + private double minDist; + + @Override + protected void collect( + Vertex<LongWritable, DoubleWritable, FloatWritable> vertex, + Iterable<DoubleWritable> messages) { + if (getSuperstep() == 0) { + vertex.setValue(new DoubleWritable(Double.MAX_VALUE)); + } + if (getSuperstep() == 8) { + throw new RuntimeException("bug"); + } + minDist = isSource(vertex) ? 0d : Double.MAX_VALUE; + for (DoubleWritable message : messages) { + minDist = Math.min(minDist, message.get()); + } + if (LOG.isDebugEnabled()) { + LOG.debug("Vertex " + vertex.getId() + " got minDist = " + minDist + + " vertex value = " + vertex.getValue()); + } + } + + @Override + protected void signal( + Vertex<LongWritable, DoubleWritable, FloatWritable> vertex, + Iterable<DoubleWritable> messages) { + if (minDist < vertex.getValue().get()) { + vertex.setValue(new DoubleWritable(minDist)); + for (Edge<LongWritable, FloatWritable> edge : vertex.getEdges()) { + double distance = minDist + edge.getValue().get(); + if (LOG.isDebugEnabled()) { + LOG.debug("Vertex " + vertex.getId() + " sent to " + + edge.getTargetVertexId() + " = " + distance); + } + // INTENTIONAL BUG:Instead of sending the distance (i.e. by + // adding edge values), we send the vertex value. + sendMessage(edge.getTargetVertexId(), new DoubleWritable(minDist)); + } + } + } + + /** + * Is this vertex the source id? + * + * @param vertex + * Vertex + * @return True if the source id + */ + private boolean isSource(Vertex<LongWritable, ?, ?> vertex) { + return vertex.getId().get() == SOURCE_ID.get(getConf()); + } +} http://git-wip-us.apache.org/repos/asf/giraph/blob/8675c84a/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/package-info.java ---------------------------------------------------------------------- diff --git a/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/package-info.java b/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/package-info.java new file mode 100644 index 0000000..fac388c --- /dev/null +++ b/giraph-debugger/src/test/java/org/apache/giraph/debugger/instrumenter/test/basecompute/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/** + * Some tests for Graft instrumenter. + */ +package org.apache.giraph.debugger.instrumenter.test.basecompute;
