use of co.cask.cdap.proto.id.ProgramId in project cdap by caskdata.
the class DatasetBasedStreamSizeScheduleStoreTest method testDeletion.
private void testDeletion(final ProgramId programId) throws Exception {
final boolean defaultVersion = programId.getVersion().equals(ApplicationId.DEFAULT_VERSION);
DatasetId storeTable = NamespaceId.SYSTEM.dataset(ScheduleStoreTableUtil.SCHEDULE_STORE_DATASET_NAME);
final Table table = datasetFramework.getDataset(storeTable, ImmutableMap.<String, String>of(), null);
Assert.assertNotNull(table);
TransactionExecutor txnl = txExecutorFactory.createExecutor(ImmutableList.of((TransactionAware) table));
final byte[] startKey = Bytes.toBytes(DatasetBasedStreamSizeScheduleStore.KEY_PREFIX);
final byte[] stopKey = Bytes.stopKeyForPrefix(startKey);
txnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
Scanner scanner = table.scan(startKey, stopKey);
Assert.assertNull(scanner.next());
scanner.close();
}
});
// Create one stream schedule - this will be persisted with new format
scheduleStore.persist(programId, PROGRAM_TYPE, STREAM_SCHEDULE_1, MAP_1, 0L, 0L, 0L, 0L, true);
// Create one stream schedule - based on the old format
txnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
// Create a programId without version so that we can create a old format schedule
ProgramId defaultProgramId = new ProgramId(programId.getNamespace(), programId.getApplication(), programId.getType(), programId.getProgram());
String newRowKey = scheduleStore.getRowKey(defaultProgramId, PROGRAM_TYPE, STREAM_SCHEDULE_1.getName());
Row row = table.get(Bytes.toBytes(scheduleStore.getRowKey(programId, PROGRAM_TYPE, STREAM_SCHEDULE_1.getName())));
Assert.assertFalse(row.isEmpty());
byte[] oldRowKey = Bytes.toBytes(scheduleStore.removeAppVersion(newRowKey));
for (Map.Entry<byte[], byte[]> entry : row.getColumns().entrySet()) {
table.put(oldRowKey, entry.getKey(), entry.getValue());
}
}
});
// Make sure there are only two stream size schedules
txnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
Scanner scanner = table.scan(startKey, stopKey);
int numRows = 0;
while (true) {
Row row = scanner.next();
if (row == null) {
break;
}
numRows++;
}
scanner.close();
Assert.assertEquals(2, numRows);
}
});
// This delete should have deleted both the old and new row format
scheduleStore.delete(programId, PROGRAM_TYPE, STREAM_SCHEDULE_1.getName());
txnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
Scanner scanner = table.scan(startKey, stopKey);
if (defaultVersion) {
Assert.assertNull(scanner.next());
} else {
Assert.assertNotNull(scanner.next());
Assert.assertNull(scanner.next());
}
scanner.close();
}
});
// If the version is not default, we need to delete the row which didn't have a version
if (!defaultVersion) {
txnl.execute(new TransactionExecutor.Subroutine() {
@Override
public void apply() throws Exception {
// Create a programId without version so that we can create row key to delete the old format schedule
ProgramId defaultProgramId = new ProgramId(programId.getNamespace(), programId.getApplication(), programId.getType(), programId.getProgram());
String newRowKey = scheduleStore.getRowKey(defaultProgramId, PROGRAM_TYPE, STREAM_SCHEDULE_1.getName());
byte[] oldRowKey = Bytes.toBytes(scheduleStore.removeAppVersion(newRowKey));
Row row = table.get(oldRowKey);
Assert.assertFalse(row.isEmpty());
table.delete(oldRowKey);
}
});
}
}
use of co.cask.cdap.proto.id.ProgramId in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method setWorkerInstances.
/**
* Sets the number of instances of a worker.
*/
@PUT
@Path("/apps/{app-id}/workers/{worker-id}/instances")
@AuditPolicy(AuditDetail.REQUEST_BODY)
public void setWorkerInstances(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId, @PathParam("app-id") String appId, @PathParam("worker-id") String workerId) throws Exception {
int instances = getInstances(request);
try {
lifecycleService.setInstances(new ProgramId(namespaceId, appId, ProgramType.WORKER, workerId), instances);
responder.sendStatus(HttpResponseStatus.OK);
} catch (SecurityException e) {
responder.sendStatus(HttpResponseStatus.UNAUTHORIZED);
} catch (Throwable e) {
if (respondIfElementNotFound(e, responder)) {
return;
}
throw e;
}
}
use of co.cask.cdap.proto.id.ProgramId in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method doPerformAction.
private void doPerformAction(HttpRequest request, HttpResponder responder, String namespaceId, String appId, String appVersion, String type, String programId, String action) throws Exception {
ApplicationId applicationId = new ApplicationId(namespaceId, appId, appVersion);
if (SCHEDULES.equals(type)) {
ScheduleId scheduleId = applicationId.schedule(programId);
lifecycleService.suspendResumeSchedule(scheduleId, action);
responder.sendJson(HttpResponseStatus.OK, "OK");
return;
}
ProgramType programType;
try {
programType = ProgramType.valueOfCategoryName(type);
} catch (IllegalArgumentException e) {
throw new BadRequestException(String.format("Unknown program type '%s'", type), e);
}
ProgramId program = applicationId.program(programType, programId);
Map<String, String> args = decodeArguments(request);
// we have already validated that the action is valid
switch(action.toLowerCase()) {
case "start":
lifecycleService.start(program, args, false);
break;
case "debug":
if (!isDebugAllowed(programType)) {
throw new NotImplementedException(String.format("debug action is not implemented for program type %s", programType));
}
lifecycleService.start(program, args, true);
break;
case "stop":
lifecycleService.stop(program);
break;
default:
throw new NotFoundException(String.format("%s action was not found", action));
}
responder.sendStatus(HttpResponseStatus.OK);
}
use of co.cask.cdap.proto.id.ProgramId in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method getStatuses.
/**
* Returns the status for all programs that are passed into the data. The data is an array of JSON objects
* where each object must contain the following three elements: appId, programType, and programId
* (flow name, service name, etc.).
* <p>
* Example input:
* <pre><code>
* [{"appId": "App1", "programType": "Service", "programId": "Service1"},
* {"appId": "App1", "programType": "Mapreduce", "programId": "MapReduce2"},
* {"appId": "App2", "programType": "Flow", "programId": "Flow1"}]
* </code></pre>
* </p><p>
* The response will be an array of JsonObjects each of which will contain the three input parameters
* as well as 2 fields, "status" which maps to the status of the program and "statusCode" which maps to the
* status code for the data in that JsonObjects.
* </p><p>
* If an error occurs in the input (for the example above, App2 does not exist), then all JsonObjects for which the
* parameters have a valid status will have the status field but all JsonObjects for which the parameters do not have
* a valid status will have an error message and statusCode.
* </p><p>
* For example, if there is no App2 in the data above, then the response would be 200 OK with following possible data:
* </p>
* <pre><code>
* [{"appId": "App1", "programType": "Service", "programId": "Service1", "statusCode": 200, "status": "RUNNING"},
* {"appId": "App1", "programType": "Mapreduce", "programId": "Mapreduce2", "statusCode": 200, "status": "STOPPED"},
* {"appId":"App2", "programType":"Flow", "programId":"Flow1", "statusCode":404, "error": "App: App2 not found"}]
* </code></pre>
*/
@POST
@Path("/status")
@AuditPolicy(AuditDetail.REQUEST_BODY)
public void getStatuses(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId) throws Exception {
List<BatchProgram> programs = validateAndGetBatchInput(request, BATCH_PROGRAMS_TYPE);
List<BatchProgramStatus> statuses = new ArrayList<>(programs.size());
for (BatchProgram program : programs) {
ProgramId programId = new ProgramId(namespaceId, program.getAppId(), program.getProgramType(), program.getProgramId());
try {
ProgramStatus programStatus = lifecycleService.getProgramStatus(programId);
statuses.add(new BatchProgramStatus(program, HttpResponseStatus.OK.getCode(), null, programStatus.name()));
} catch (NotFoundException e) {
statuses.add(new BatchProgramStatus(program, HttpResponseStatus.NOT_FOUND.getCode(), e.getMessage(), null));
}
}
responder.sendJson(HttpResponseStatus.OK, statuses);
}
use of co.cask.cdap.proto.id.ProgramId in project cdap by caskdata.
the class ProgramLifecycleHttpHandler method setServiceInstances.
/**
* Set instances of a service.
*/
@PUT
@Path("/apps/{app-id}/services/{service-id}/instances")
@AuditPolicy(AuditDetail.REQUEST_BODY)
public void setServiceInstances(HttpRequest request, HttpResponder responder, @PathParam("namespace-id") String namespaceId, @PathParam("app-id") String appId, @PathParam("service-id") String serviceId) throws Exception {
try {
ProgramId programId = new ProgramId(namespaceId, appId, ProgramType.SERVICE, serviceId);
if (!store.programExists(programId)) {
responder.sendString(HttpResponseStatus.NOT_FOUND, "Service not found");
return;
}
int instances = getInstances(request);
lifecycleService.setInstances(programId, instances);
responder.sendStatus(HttpResponseStatus.OK);
} catch (SecurityException e) {
responder.sendStatus(HttpResponseStatus.UNAUTHORIZED);
} catch (Throwable throwable) {
if (respondIfElementNotFound(throwable, responder)) {
return;
}
throw throwable;
}
}
Aggregations