package com.ikai.mapperdemo.servlets; import java.io.IOException; import java.util.Date; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.hadoop.mapreduce.Counter; import org.apache.hadoop.mapreduce.CounterGroup; import org.apache.hadoop.mapreduce.Counters; import org.apache.hadoop.mapreduce.JobID; import com.google.appengine.api.datastore.DatastoreService; import com.google.appengine.api.datastore.DatastoreServiceFactory; import com.google.appengine.api.datastore.Entity; import com.google.appengine.api.datastore.EntityNotFoundException; import com.google.appengine.tools.mapreduce.MapReduceState; import com.ikai.mapperdemo.mappers.CountWordsMapper; /** * This is the servlet that takes care of any processing we have to do after we * have finished running {@link CountWordsMapper}. * * This is just a standard servlet - we can do anything we want here. We can use * any App Engine API such as email or XMPP, for instance, to notify an * administrator. We could also store a final state into the datastore - in * fact, that is what this example below does. * * @author Ikai Lan * */ @SuppressWarnings("serial") public class WordCountCompletedCallbackServlet extends HttpServlet { public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { String jobIdName = req.getParameter("job_id"); JobID jobId = JobID.forName(jobIdName); // A future iteration of this will likely contain a default // option if we don't care which DatastoreService instance we use. DatastoreService datastore = DatastoreServiceFactory .getDatastoreService(); try { // We get the state back from the job_id parameter. The state is // serialized and stored in the datastore, so we pass an instance // of the datastore service. MapReduceState mrState = MapReduceState.getMapReduceStateFromJobID( datastore, jobId); // There's a bit of ceremony to get the actual counter. This // example is intentionally verbose for clarity. First get all the // Counters, // then we get the CounterGroup, then we get the Counter, then we // get the count. Counters counters = mrState.getCounters(); CounterGroup counterGroup = counters.getGroup("CommentWords"); Counter counter = counterGroup.findCounter("count"); long wordCount = counter.getValue(); // Finally! // Let's create a special datastore Entity for this value so // we can reference it on the ViewComments page Entity totalCountEntity = new Entity("TotalWordCount", "total_word_count"); totalCountEntity.setProperty("count", wordCount); // Now we timestamp this bad boy totalCountEntity.setProperty("updatedAt", new Date()); datastore.put(totalCountEntity); } catch (EntityNotFoundException e) { throw new IOException("No datastore state"); } } }