35f03e6060e0bfaf9bd4711cd2c171217100a25d
[music.git] / src / main / java / org / onap / music / rest / RestMusicLocksAPI.java
1 /*
2  * ============LICENSE_START==========================================
3  * org.onap.music
4  * ===================================================================
5  *  Copyright (c) 2017 AT&T Intellectual Property
6  * ===================================================================
7  *  *  Modifications Copyright (c) 2019 Samsung
8  * ===================================================================
9  * 
10  *  Licensed under the Apache License, Version 2.0 (the "License");
11  *  you may not use this file except in compliance with the License.
12  *  You may obtain a copy of the License at
13  * 
14  *     http://www.apache.org/licenses/LICENSE-2.0
15  * 
16  *  Unless required by applicable law or agreed to in writing, software
17  *  distributed under the License is distributed on an "AS IS" BASIS,
18  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  *  See the License for the specific language governing permissions and
20  *  limitations under the License.
21  * 
22  * ============LICENSE_END=============================================
23  * ====================================================================
24  */
25
26 package org.onap.music.rest;
27
28 import java.util.List;
29 import java.util.Map;
30
31 import javax.ws.rs.Consumes;
32 import javax.ws.rs.DELETE;
33 import javax.ws.rs.GET;
34 import javax.ws.rs.HeaderParam;
35 import javax.ws.rs.POST;
36 import javax.ws.rs.Path;
37 import javax.ws.rs.PathParam;
38 import javax.ws.rs.Produces;
39 import javax.ws.rs.core.MediaType;
40 import javax.ws.rs.core.Response;
41 import javax.ws.rs.core.Response.ResponseBuilder;
42 import javax.ws.rs.core.Response.Status;
43
44 import org.onap.music.datastore.jsonobjects.JsonLeasedLock;
45 import org.onap.music.datastore.jsonobjects.JsonLock;
46 import org.onap.music.eelf.logging.EELFLoggerDelegate;
47 import org.onap.music.eelf.logging.format.AppMessages;
48 import org.onap.music.eelf.logging.format.ErrorSeverity;
49 import org.onap.music.eelf.logging.format.ErrorTypes;
50 import org.onap.music.exceptions.MusicLockingException;
51 import org.onap.music.lockingservice.cassandra.LockType;
52 import org.onap.music.lockingservice.cassandra.MusicLockState;
53 import org.onap.music.main.MusicCore;
54 import org.onap.music.main.MusicUtil;
55 import org.onap.music.main.ResultType;
56 import org.onap.music.main.ReturnType;
57 import org.onap.music.response.jsonobjects.JsonResponse;
58
59 import io.swagger.annotations.Api;
60 import io.swagger.annotations.ApiOperation;
61 import io.swagger.annotations.ApiParam;
62 import io.swagger.annotations.ApiResponse;
63 import io.swagger.annotations.ApiResponses;
64 import io.swagger.annotations.Example;
65 import io.swagger.annotations.ExampleProperty;
66
67
68 @Path("/v2/locks/")
69 @Api(value="Locking Api")
70 public class RestMusicLocksAPI {
71
72     private EELFLoggerDelegate logger =EELFLoggerDelegate.getLogger(RestMusicLocksAPI.class);
73     private static final String XMINORVERSION = "X-minorVersion";
74     private static final String XPATCHVERSION = "X-patchVersion";
75     private static final String VERSION = "v2";
76
77     /**
78      * Puts the requesting process in the q for this lock. The corresponding
79      * node will be created if it did not already exist
80      * 
81      * @param lockName
82      * @return
83      * @throws Exception 
84      */
85     @POST
86     @Path("/create/{lockname}")
87     @ApiOperation(value = "Create and Acquire a Lock Id for a single row.",
88         notes = "Creates and Acquires a Lock Id for a specific Row in a table based on the key of that row.\n"
89         + " The corresponding lock will be created if it did not already exist."
90         + " Lock Name also the Lock is in the form of keyspaceName.tableName.rowId.\n"
91         + " The Response will be in the form of \"$kesypaceName.tableName.rowId$lockRef\" "
92         + " where the lockRef is a integer representing the Lock Name buffered by \"$\" " 
93         + " followed by the lock number. This term for "
94         + " this response is a lockId and it will be used in other /locks API calls where a "
95         + " lockId is required. If just a lock is required then the form that would be "
96         + " the original lockname(without the buffered \"$\").",
97         response = Map.class)
98     @Consumes(MediaType.APPLICATION_JSON)
99     @Produces(MediaType.APPLICATION_JSON)
100     @ApiResponses(value={
101         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
102             @ExampleProperty(mediaType="application/json",value = 
103                 "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"},"
104                 + "\"status\" : \"SUCCESS\"}")
105         })),
106         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
107             @ExampleProperty(mediaType="application/json",value = 
108                 "{\"error\" : \"Unable to aquire lock\","
109                 + "\"status\" : \"FAILURE\"}") 
110         }))
111     })  
112     public Response createLockReference(
113             @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName,
114             @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
115             @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
116             @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
117             @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
118             JsonLock lockObject,
119             @ApiParam(value = "Application namespace",
120                             required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{
121         try {
122             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
123             Map<String, Object> resultMap = MusicCore.validateLock(lockName);
124             if (resultMap.containsKey("Error")) {
125                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.MISSINGINFO  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
126                 response.status(Status.BAD_REQUEST);
127                 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build();
128             }
129             String keyspaceName = (String) resultMap.get("keyspace");
130             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) ");
131             
132             //default lock type is write, as this is always semantically safe
133             LockType locktype = LockType.WRITE;
134             if (lockObject!=null && lockObject.getLocktype()!=null) {
135                 locktype = lockObject.getLocktype();
136             }
137             String lockId;
138             try {
139                 lockId= MusicCore.createLockReference(lockName, locktype);
140             } catch (MusicLockingException e) {
141                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
142             }
143             
144             if (lockId == null) {  
145                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.LOCKINGERROR  ,ErrorSeverity.CRITICAL, ErrorTypes.LOCKINGERROR);
146                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Lock Id is null").toMap()).build();
147             }
148             return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).setLock(lockId).toMap()).build();
149         } finally {
150             EELFLoggerDelegate.mdcRemove("keyspace");
151         }
152     }
153
154     /**
155      * 
156      * Checks if the node is in the top of the queue and hence acquires the lock
157      * 
158      * @param lockId
159      * @return
160      * @throws Exception 
161      */
162     @GET
163     @Path("/acquire/{lockId}")
164     @ApiOperation(value = "Aquire Lock Id ", 
165         notes = "Checks if the node is in the top of the queue and hence acquires the lock",
166         response = Map.class)
167     @Produces(MediaType.APPLICATION_JSON)    
168     @ApiResponses(value={
169         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
170             @ExampleProperty(mediaType="application/json",value = 
171                 "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"},"
172                 + "\"message\" : \"<integer> is the lock holder for the key\","
173                 + "\"status\" : \"SUCCESS\"}") 
174         })),
175         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
176             @ExampleProperty(mediaType="application/json",value = 
177                 "{\"error\" : \"Unable to aquire lock\","
178                 + "\"status\" : \"FAILURE\"}") 
179         }))
180     })  
181     public Response accquireLock(
182             @ApiParam(value="Lock Id",required=true) @PathParam("lockId") String lockId,
183             @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
184             @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
185             @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
186             @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
187             @ApiParam(value = "Application namespace",
188                             required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{
189         try { 
190             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
191             Map<String, Object> resultMap = MusicCore.validateLock(lockId);
192             if (resultMap.containsKey("Error")) {
193                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
194                 response.status(Status.BAD_REQUEST);
195                 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build();
196             }
197             
198             String keyspaceName = (String) resultMap.get("keyspace");
199             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) ");
200             try {
201                 String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$'));
202                 ReturnType lockStatus = MusicCore.acquireLock(lockName,lockId);
203                 if ( lockStatus.getResult().equals(ResultType.SUCCESS)) {
204                     response.status(Status.OK);
205                 } else {
206                     response.status(Status.BAD_REQUEST);
207                 }
208                 return response.entity(new JsonResponse(lockStatus.getResult()).setLock(lockId).setMessage(lockStatus.getMessage()).toMap()).build();
209             } catch (Exception e) {
210                 logger.error(EELFLoggerDelegate.errorLogger,AppMessages.INVALIDLOCK + lockId, ErrorSeverity.CRITICAL,
211                     ErrorTypes.LOCKINGERROR, e);
212                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError("Unable to aquire lock").toMap()).build();
213             }
214         } finally {
215             EELFLoggerDelegate.mdcRemove("keyspace");
216         }
217     }
218     
219
220     @POST
221     @Path("/acquire-with-lease/{lockId}")
222     @ApiOperation(
223         hidden = false,
224         value = " ** DEPRECATED ** - Aquire Lock with Lease", 
225         notes = "Acquire the lock with a lease, where lease period is in Milliseconds.\n"
226         + "This will ensure that a lock will expire in set milliseconds.\n"
227         + "This is no longer available after v3.2.0",
228         response = Map.class)
229     @Consumes(MediaType.APPLICATION_JSON)
230     @Produces(MediaType.APPLICATION_JSON) 
231     @ApiResponses(value={
232         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
233             @ExampleProperty(mediaType="application/json",value = 
234                 "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\","
235                 + "\"lock-lease\" : \"6000\"},"
236                 + "\"message\" : \"<integer> is the lock holder for the key\","
237                 + "\"status\" : \"SUCCESS\"}")
238         })),
239         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
240             @ExampleProperty(mediaType="application/json",value = 
241                 "{\"error\" : \"Unable to aquire lock\","
242                 + "\"status\" : \"FAILURE\"}") 
243         }))
244     })  
245     @Deprecated
246     public Response accquireLockWithLease(
247         JsonLeasedLock lockObj, 
248         @ApiParam(value="Lock Id",required=true) @PathParam("lockId") String lockId,
249         @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
250         @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
251         @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
252         @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
253         @ApiParam(value = "Application namespace",required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{
254         try {
255             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
256             Map<String, Object> resultMap = MusicCore.validateLock(lockId);
257             if (resultMap.containsKey("Error")) {
258                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
259                 response.status(Status.BAD_REQUEST);
260                 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build();
261             }
262             String keyspaceName = (String) resultMap.get("keyspace");
263             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) ");
264             String lockName = lockId.substring(lockId.indexOf('$')+1, lockId.lastIndexOf('$'));
265             ReturnType lockLeaseStatus = MusicCore.acquireLockWithLease(lockName, lockId, lockObj.getLeasePeriod());
266             if ( lockLeaseStatus.getResult().equals(ResultType.SUCCESS)) {
267                 response.status(Status.OK);
268             } else {
269                 response.status(Status.BAD_REQUEST);
270             }
271             return response.entity(new JsonResponse(lockLeaseStatus.getResult()).setLock(lockName)
272                 .setMessage(lockLeaseStatus.getMessage())
273                 .setLockLease(String.valueOf(lockObj.getLeasePeriod())).toMap()).build();
274         } finally {
275             EELFLoggerDelegate.mdcRemove("keyspace");
276         }
277
278
279     } 
280     
281
282     @GET
283     @Path("/enquire/{lockname}")
284     @ApiOperation(value = "Get the top of the lock queue", 
285         notes = "Gets the current single lockholder at top of lock queue",
286         response = Map.class)
287     @Produces(MediaType.APPLICATION_JSON)    
288     @ApiResponses(value={
289         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
290             @ExampleProperty(mediaType="application/json",value = 
291                 "{\"lock\" : {\"lock\" : \"keyspace.table.rowId\","
292                 + "\"lock-holder\" : \"$tomtest.employees.tom$<integer>\"}},"
293                 + "\"status\" : \"SUCCESS\"}") 
294         })),
295         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
296             @ExampleProperty(mediaType="application/json",value = 
297                 "{\"error\" : \"Error Message\","
298                 + "\"status\" : \"FAILURE\"}") 
299         }))
300     })  
301     public Response enquireLock(
302             @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName,
303             @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
304             @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
305             @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
306             @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
307             @ApiParam(value = "Application namespace",
308                             required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{
309         try {
310             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
311             Map<String, Object> resultMap = MusicCore.validateLock(lockName);
312             if (resultMap.containsKey("Error")) {
313                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
314                 response.status(Status.BAD_REQUEST);
315                 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build();
316             }
317             String keyspaceName = (String) resultMap.get("keyspace");
318             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) ");
319             String who = MusicCore.whoseTurnIsIt(lockName);
320             ResultType status = ResultType.SUCCESS;
321             String error = "";
322             if ( who == null ) { 
323                 status = ResultType.FAILURE; 
324                 error = "There was a problem getting the lock holder";
325                 logger.error(EELFLoggerDelegate.errorLogger,"There was a problem getting the lock holder", AppMessages.INCORRECTDATA  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
326                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build();
327             }
328             return response.status(Status.OK).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build();
329         } finally {
330             EELFLoggerDelegate.mdcRemove("keyspace");
331         }
332     }
333
334     @GET
335     @Path("/holders/{lockname}")
336     @ApiOperation(value = "Get Lock Holders", 
337         notes = "Gets the current Lock Holders.\n"
338         + "Will return an array of READ Lock References.",
339         response = Map.class)
340     @Produces(MediaType.APPLICATION_JSON)    
341     @ApiResponses(value={
342         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
343             @ExampleProperty(mediaType="application/json",value = 
344                 "{\"lock\" : {\"lock\" : \"keyspace.table.rowId\","
345                 + "\"lock-holder\" : [\"$keyspace.table.rowId$<integer1>\",\"$keyspace.table.rowId$<integer2>\"]}},"
346                 + "\"status\" : \"SUCCESS\"}") 
347         })),
348         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
349             @ExampleProperty(mediaType="application/json",value = 
350                 "{\"error\" : \"Error message\","
351                 + "\"status\" : \"FAILURE\"}") 
352         }))
353     })  
354     public Response currentLockHolder(@ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName,
355             @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
356             @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
357             @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
358             @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
359             @ApiParam(value = "Application namespace",
360                             required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{
361         try {
362             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
363             Map<String, Object> resultMap = MusicCore.validateLock(lockName);
364             if (resultMap.containsKey("Error")) {
365                 logger.error(EELFLoggerDelegate.errorLogger, "", AppMessages.INCORRECTDATA, ErrorSeverity.CRITICAL,
366                         ErrorTypes.GENERALSERVICEERROR);
367                 response.status(Status.BAD_REQUEST);
368                 return response.entity(
369                         new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap())
370                         .build();
371             }
372             String keyspaceName = (String) resultMap.get("keyspace");
373             List<String> who = MusicCore.getCurrentLockHolders(lockName);
374             ResultType status = ResultType.SUCCESS;
375             String error = "";
376             if (who == null || who.isEmpty()) {
377                 status = ResultType.FAILURE;
378                 error = (who !=null && who.isEmpty()) ? "No lock holders for the key":"There was a problem getting the lock holder";
379                 logger.error(EELFLoggerDelegate.errorLogger, "There was a problem getting the lock holder",
380                         AppMessages.INCORRECTDATA, ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
381                 return response.status(Status.BAD_REQUEST)
382                         .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap())
383                         .build();
384             }
385             return response.status(Status.OK)
386                 .entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).setisLockHolders(true).toMap())
387                 .build();
388         } finally {
389             EELFLoggerDelegate.mdcRemove("keyspace");
390         }
391     }
392     
393     
394     @GET
395     @Path("/{lockname}")
396     @ApiOperation(value = "Lock State",
397         notes = "Returns current Lock State and Holder.",
398         response = Map.class,hidden = true)
399     @Produces(MediaType.APPLICATION_JSON)    
400     @ApiResponses(value={
401         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
402             @ExampleProperty(mediaType="application/json",value = 
403                 "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"},"
404                 + "\"message\" : \"<integer> is the lock holder for the key\","
405                 + "\"status\" : \"SUCCESS\"}") 
406         })),
407         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
408             @ExampleProperty(mediaType="application/json",value = 
409                 "{\"error\" : \"Unable to aquire lock\","
410                 + "\"status\" : \"FAILURE\"}") 
411         }))
412     })  
413     public Response currentLockState(
414             @ApiParam(value="Lock Name",required=true) @PathParam("lockname") String lockName,
415             @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
416             @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
417             @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
418             @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
419             @ApiParam(value = "Application namespace",
420                             required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{
421         try {
422             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
423             Map<String, Object> resultMap = MusicCore.validateLock(lockName);
424             if (resultMap.containsKey("Error")) {
425                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
426                 response.status(Status.BAD_REQUEST);
427                 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build();
428             }
429             String keyspaceName = (String) resultMap.get("keyspace");
430             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
431             String who = MusicCore.whoseTurnIsIt(lockName);
432             ResultType status = ResultType.SUCCESS;
433             String error = "";
434             if ( who == null ) {
435                 status = ResultType.FAILURE; 
436                 error = "There was a problem getting the lock holder";
437                 logger.error(EELFLoggerDelegate.errorLogger,"There was a problem getting the lock holder", AppMessages.INCORRECTDATA  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
438                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build();
439             }
440             return response.status(Status.OK).entity(new JsonResponse(status).setError(error).setLock(lockName).setLockHolder(who).toMap()).build();
441         } finally {
442             EELFLoggerDelegate.mdcRemove("keyspace");
443         }
444
445     }
446
447     /**
448      * 
449      * deletes the process from the lock queue
450      * 
451      * @param lockId
452      * @throws Exception 
453      */
454     @DELETE
455     @Path("/release/{lockreference}")
456     @ApiOperation(value = "Release Lock",
457         notes = "Releases the lock from the lock queue.",
458         response = Map.class)
459     @Produces(MediaType.APPLICATION_JSON)    
460     @ApiResponses(value={
461         @ApiResponse(code=200, message = "Success - UNLOCKED = Lock Removed.",examples = @Example( value =  {
462             @ExampleProperty(mediaType="application/json",value = 
463                 "{\"lock\" : {\"lock\" : \"$keyspace.table.rowId$<integer>\"},"
464                 + "\"lock-status\" : \"UNLOCKED\"},"
465                 + "\"status\" : \"SUCCESS\"}")
466         })),
467         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
468             @ExampleProperty(mediaType="application/json",value = 
469                 "{\"error\" : \"Unable to aquire lock\","
470                 + "\"status\" : \"FAILURE\"}") 
471         }))
472     })  
473     public Response unLock(@PathParam("lockreference") String lockId,
474             @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
475             @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
476             @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
477             @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
478             @ApiParam(value = "Application namespace",
479                 required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{
480         try {
481             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
482             Map<String, Object> resultMap = MusicCore.validateLock(lockId);
483             if (resultMap.containsKey("Error")) {
484                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
485                 response.status(Status.BAD_REQUEST);
486                 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build();
487             }
488
489             String keyspaceName = (String) resultMap.get("keyspace");
490             EELFLoggerDelegate.mdcPut("keyspace", "( "+keyspaceName+" ) ");
491             boolean voluntaryRelease = true; 
492             MusicLockState mls = MusicCore.releaseLock(lockId,voluntaryRelease);
493             if(mls.getErrorMessage() != null) {
494                 resultMap.put(ResultType.EXCEPTION.getResult(), mls.getErrorMessage());
495                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.INCORRECTDATA  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
496                 return response.status(Status.BAD_REQUEST).entity(resultMap).build();
497             }
498             Map<String,Object> returnMap = null;
499             if (mls.getLockStatus() == MusicLockState.LockStatus.UNLOCKED) {
500                 returnMap = new JsonResponse(ResultType.SUCCESS).setLock(lockId)
501                     .setLockStatus(mls.getLockStatus()).toMap();
502                 response.status(Status.OK);
503             }
504             if (mls.getLockStatus() == MusicLockState.LockStatus.LOCKED) {
505                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.LOCKINGERROR  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
506                 returnMap = new JsonResponse(ResultType.FAILURE).setLock(lockId)
507                     .setLockStatus(mls.getLockStatus()).toMap();
508                 response.status(Status.BAD_REQUEST);
509             }
510             return response.entity(returnMap).build();
511         } finally {
512             EELFLoggerDelegate.mdcRemove("keyspace");
513         }
514     }
515
516     /**
517      * 
518      * @param lockName
519      * @throws Exception 
520      */
521     @Deprecated
522     @DELETE
523     @Path("/delete/{lockname}")
524     @ApiOperation(
525         hidden = true,
526         value = "-DEPRECATED- Delete Lock", response = Map.class,
527         notes = "-DEPRECATED- Delete the lock.")
528     @Produces(MediaType.APPLICATION_JSON)    
529     @ApiResponses(value={
530         @ApiResponse(code=200, message = "Success",examples = @Example( value =  {
531             @ExampleProperty(mediaType="application/json",value = 
532                 "{\"status\" : \"SUCCESS\"}") 
533         })),
534         @ApiResponse(code=400, message = "Failure",examples = @Example( value =  {
535             @ExampleProperty(mediaType="application/json",value = 
536                 "{\"error\" : \"Error Message if any\","
537                 + "\"status\" : \"FAILURE\"}") 
538         }))
539     })
540     public Response deleteLock(@PathParam("lockname") String lockName,
541             @ApiParam(value = "Minor Version",required = false) @HeaderParam(XMINORVERSION) String minorVersion,
542             @ApiParam(value = "Patch Version",required = false) @HeaderParam(XPATCHVERSION) String patchVersion,
543             @ApiParam(value = "AID", required = false, hidden = true) @HeaderParam("aid") String aid,
544             @ApiParam(value = "Authorization", required = true) @HeaderParam(MusicUtil.AUTHORIZATION) String authorization,
545             @ApiParam(value = "Application namespace",
546                             required = false, hidden = true) @HeaderParam("ns") String ns) throws Exception{
547         try {
548             ResponseBuilder response = MusicUtil.buildVersionResponse(VERSION, minorVersion, patchVersion);
549             Map<String, Object> resultMap = MusicCore.validateLock(lockName);
550             if (resultMap.containsKey("Error")) {
551                 logger.error(EELFLoggerDelegate.errorLogger,"", AppMessages.UNKNOWNERROR  ,ErrorSeverity.CRITICAL, ErrorTypes.GENERALSERVICEERROR);
552                 response.status(Status.BAD_REQUEST);
553                 return response.entity(new JsonResponse(ResultType.FAILURE).setError(String.valueOf(resultMap.get("Error"))).toMap()).build();
554             }
555
556             String keyspaceName = (String) resultMap.get("keyspace");
557             EELFLoggerDelegate.mdcPut("keyspace", "( " + keyspaceName + " ) ");
558             try{
559                 MusicCore.destroyLockRef(lockName);
560             }catch (Exception e) {
561                 logger.error(EELFLoggerDelegate.errorLogger, e);
562                 return response.status(Status.BAD_REQUEST).entity(new JsonResponse(ResultType.FAILURE).setError(e.getMessage()).toMap()).build();
563             }
564             return response.status(Status.OK).entity(new JsonResponse(ResultType.SUCCESS).toMap()).build();
565         } finally {
566             EELFLoggerDelegate.mdcRemove("keyspace");
567         }
568     }
569
570 }