001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.oozie.service; 020 021import org.apache.oozie.util.Instrumentable; 022import org.apache.oozie.util.Instrumentation; 023import org.apache.oozie.lock.LockToken; 024import org.apache.oozie.lock.MemoryLocks; 025 026import com.google.common.annotations.VisibleForTesting; 027 028/** 029 * Service that provides in-memory locks. Assumes no other Oozie servers are using the database. 030 */ 031public class MemoryLocksService implements Service, Instrumentable { 032 033 public static enum Type { 034 READ, WRITE 035 } 036 037 protected static final String INSTRUMENTATION_GROUP = "locks"; 038 private MemoryLocks locks; 039 040 /** 041 * Initialize the memory locks service 042 * 043 * @param services services instance. 044 */ 045 @Override 046 public void init(Services services) throws ServiceException { 047 locks = new MemoryLocks(); 048 } 049 050 /** 051 * Destroy the memory locks service. 052 */ 053 @Override 054 public void destroy() { 055 locks = null; 056 } 057 058 /** 059 * Return the public interface for the memory locks services 060 * 061 * @return {@link MemoryLocksService}. 062 */ 063 @Override 064 public Class<? extends Service> getInterface() { 065 return MemoryLocksService.class; 066 } 067 068 /** 069 * Instruments the memory locks service. 070 * 071 * @param instr instance to instrument the memory locks service to. 072 */ 073 public void instrument(Instrumentation instr) { 074 final MemoryLocks finalLocks = this.locks; 075 instr.addVariable(INSTRUMENTATION_GROUP, "locks", new Instrumentation.Variable<Long>() { 076 public Long getValue() { 077 return (long) finalLocks.size(); 078 } 079 }); 080 } 081 082 /** 083 * Obtain a READ lock for a source. 084 * 085 * @param resource resource name. 086 * @param wait time out in milliseconds to wait for the lock, -1 means no timeout and 0 no wait. 087 * @return the lock token for the resource, or <code>null</code> if the lock could not be obtained. 088 * @throws InterruptedException thrown if the thread was interrupted while waiting. 089 */ 090 public LockToken getReadLock(String resource, long wait) throws InterruptedException { 091 return locks.getLock(resource, Type.READ, wait); 092 } 093 094 /** 095 * Obtain a WRITE lock for a source. 096 * 097 * @param resource resource name. 098 * @param wait time out in milliseconds to wait for the lock, -1 means no timeout and 0 no wait. 099 * @return the lock token for the resource, or <code>null</code> if the lock could not be obtained. 100 * @throws InterruptedException thrown if the thread was interrupted while waiting. 101 */ 102 public LockToken getWriteLock(String resource, long wait) throws InterruptedException { 103 return locks.getLock(resource, Type.WRITE, wait); 104 } 105 106 @VisibleForTesting 107 public MemoryLocks getMemoryLocks() { 108 return locks; 109 } 110}