This project has retired. For details please refer to its Attic page.
AdaptorController xref
View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.chukwa.datacollection.agent.rest;
19  
20  import org.apache.hadoop.chukwa.datacollection.agent.ChukwaAgent;
21  import org.apache.hadoop.chukwa.datacollection.adaptor.AdaptorException;
22  import org.apache.hadoop.chukwa.datacollection.adaptor.Adaptor;
23  import org.apache.hadoop.chukwa.datacollection.OffsetStatsManager;
24  import org.apache.hadoop.chukwa.util.ExceptionUtil;
25  import org.apache.commons.lang.StringEscapeUtils;
26  import org.json.JSONObject;
27  import org.json.JSONException;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  
31  import javax.ws.rs.Path;
32  import javax.ws.rs.GET;
33  import javax.ws.rs.Produces;
34  import javax.ws.rs.PathParam;
35  import javax.ws.rs.QueryParam;
36  import javax.ws.rs.DELETE;
37  import javax.ws.rs.POST;
38  import javax.ws.rs.Consumes;
39  import javax.ws.rs.WebApplicationException;
40  import javax.ws.rs.core.Context;
41  import javax.ws.rs.core.Response;
42  import javax.ws.rs.core.MediaType;
43  import javax.servlet.ServletContext;
44  import javax.servlet.http.HttpServletResponse;
45  
46  import java.text.DecimalFormat;
47  import java.util.ArrayList;
48  import java.util.List;
49  import java.util.Map;
50  
51  /**
52   * JAX-RS controller to handle all HTTP request to the Agent that deal with adaptors.
53   */
54  @Path("/adaptor")
55  public class AdaptorController {
56  
57    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat();
58    private static final Log log = LogFactory.getLog(AdaptorController.class);
59  
60    static {
61      DECIMAL_FORMAT.setMinimumFractionDigits(2);
62      DECIMAL_FORMAT.setMaximumFractionDigits(2);
63      DECIMAL_FORMAT.setGroupingUsed(false);
64    }
65  
66    /**
67     * Adds an adaptor to the agent and returns the adaptor info
68     * 
69     * @request.representation.example {@link Examples#CREATE_ADAPTOR_SAMPLE}
70     * @response.representation.200.doc Adaptor has been registered
71     * @response.representation.200.mediaType application/json
72     * @response.representation.200.example {@link Examples#ADAPTOR_STATUS_SAMPLE}
73     * @response.representation.400.doc Error in register adaptor
74     * @response.representation.400.mediaType text/plain
75     * @response.representation.400.example Bad Request
76     */
77    @POST
78    @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
79    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
80    public Response addAdaptor(AdaptorConfig ac) {
81      ChukwaAgent agent = ChukwaAgent.getAgent();
82      if (ac.getAdaptorClass() == null || 
83          ac.getDataType() == null) {
84        return badRequestResponse("Bad adaptor config.");
85      }
86    
87      StringBuilder addCommand = new StringBuilder("add ");
88      addCommand.append(ac.getAdaptorClass()).append(' ');
89      addCommand.append(ac.getDataType());
90      if (ac.getAdaptorParams() != null)
91        addCommand.append(' ').append(ac.getAdaptorParams());
92      addCommand.append(' ').append(ac.getOffset());
93  
94      // add the adaptor
95      try {
96        String adaptorId = agent.processAddCommandE(addCommand.toString());
97        return doGetAdaptor(adaptorId);
98      } catch (AdaptorException e) {
99        return badRequestResponse("Could not add adaptor for data type: '" + ac.getDataType() +
100               "', error: " + e.getMessage());
101     }
102   }
103 
104   /**
105    * Remove an adaptor from the agent
106    *
107    * @param adaptorId id of adaptor to remove.
108    * @response.representation.200.doc Delete adaptor by id
109    * @response.representation.200.mediaType text/plain
110    */
111   @DELETE
112   @Path("/{adaptorId}")
113   @Produces({MediaType.TEXT_PLAIN})
114   public Response removeAdaptor(@PathParam("adaptorId") String adaptorId) {
115     ChukwaAgent agent = ChukwaAgent.getAgent();
116 
117     // validate that we have an adaptorId
118     if (adaptorId == null) {
119       return badRequestResponse("Missing adaptorId.");
120     }
121 
122     // validate that we have a valid adaptorId
123     if (agent.getAdaptor(adaptorId) == null) {
124       return badRequestResponse("Invalid adaptorId: " + adaptorId);
125     }
126 
127     // stop the agent
128     agent.stopAdaptor(adaptorId, true);
129     return Response.ok().build();
130   }
131 
132   /**
133    * Get all adaptors
134    * 
135    * @response.representation.200.doc List all configured adaptors
136    * @response.representation.200.mediaType application/json
137    * @response.representation.200.example {@link Examples#ADAPTOR_LIST_SAMPLE}
138    */
139   @GET
140   @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
141   public Response getAdaptors() {
142     return doGetAdaptors();
143   }
144 
145   /**
146    * Get a single adaptor
147    * 
148    * @param adaptorId id of the adaptor to return
149    * @response.representation.200.doc Adaptor status and data transfer rate in 1, 5, 10 minutes averages
150    * @response.representation.200.mediaType application/json
151    * @response.representation.200.example {@link Examples#ADAPTOR_STATUS_SAMPLE}
152    */
153   @GET
154   @Path("/{adaptorId}")
155   @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
156   public Response getAdaptor(@PathParam("adaptorId") String adaptorId) {
157     return doGetAdaptor(adaptorId);
158   }
159 
160   /**
161    * Handles a single adaptor request for rendering data model output.
162    * 
163    * @return Response object
164    */
165   private Response doGetAdaptor(String adaptorId) {
166     return Response.ok(buildAdaptor(adaptorId)).build();
167   }
168 
169   /**
170    * Rendering data model output for all adaptors
171    * 
172    * @return Response object
173    */
174   private Response doGetAdaptors() {
175     return Response.ok(buildAdaptors()).build();
176   }
177   
178   /**
179    * Renders info for one adaptor.
180    */
181   protected AdaptorInfo buildAdaptor(String adaptorId) {
182     ChukwaAgent agent = ChukwaAgent.getAgent();
183     Adaptor adaptor = agent.getAdaptor(adaptorId);
184     OffsetStatsManager adaptorStats = agent.getAdaptorStatsManager();
185 
186     AdaptorInfo info = new AdaptorInfo();
187     info.setId(adaptorId);
188     info.setDataType(adaptor.getType());
189     info.setAdaptorClass(adaptor.getClass().getName());
190     String[] status = adaptor.getCurrentStatus().split(" ",2);
191     info.setAdaptorParams(status[1]);
192     List<AdaptorAveragedRate> rates = new ArrayList<AdaptorAveragedRate>();
193     rates.add(new AdaptorAveragedRate(60, adaptorStats.calcAverageRate(adaptor,  60)));
194     rates.add(new AdaptorAveragedRate(300, adaptorStats.calcAverageRate(adaptor,  300)));
195     rates.add(new AdaptorAveragedRate(600, adaptorStats.calcAverageRate(adaptor,  600)));
196     info.setAdaptorRates(rates);
197     return info;
198   }
199   
200   /**
201    * Renders info for all adaptors.
202    */
203   protected AdaptorList buildAdaptors() {
204     ChukwaAgent agent = ChukwaAgent.getAgent();
205     Map<String, String> adaptorMap = agent.getAdaptorList();
206     AdaptorList list = new AdaptorList();
207     for(String name : adaptorMap.keySet()) {
208       Adaptor adaptor = agent.getAdaptor(name);
209       OffsetStatsManager adaptorStats = agent.getAdaptorStatsManager();
210 
211       AdaptorInfo info = new AdaptorInfo();
212       info.setId(name);
213       info.setDataType(adaptor.getType());
214       info.setAdaptorClass(adaptor.getClass().getName());
215       String[] status = adaptor.getCurrentStatus().split(" ",2);
216       info.setAdaptorParams(status[1]);
217       List<AdaptorAveragedRate> rates = new ArrayList<AdaptorAveragedRate>();
218       rates.add(new AdaptorAveragedRate(60, adaptorStats.calcAverageRate(adaptor,  60)));
219       rates.add(new AdaptorAveragedRate(300, adaptorStats.calcAverageRate(adaptor,  300)));
220       rates.add(new AdaptorAveragedRate(600, adaptorStats.calcAverageRate(adaptor,  600)));
221       info.setAdaptorRates(rates);
222       list.add(info);
223     }
224     return list;
225   }
226 
227   /**
228    * Renders bad request response.
229    */
230   private static Response badRequestResponse(String content) {
231     return Response.status(HttpServletResponse.SC_BAD_REQUEST)
232                      .entity(content).build();
233   }
234 
235 }