mutex.sh 4.64 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11

# LECA Bash library
#
# The LECA bash library provides a set of function used for helping
# development of bash script mainly to write job script on the luke
# cluster
#
# The files from the LECA Bash library must be sourced from your main script
#
#

12 13 14
include logging
logdebug "Load mutex package"

Eric Coissac committed
15
if [[ -z "$LOCK_DIR" ]] ; then
Eric Coissac committed
16
  LOCK_DIR="${HOME}/lecalock"
17 18 19 20 21 22
fi

# Create the lockdir if it does not exist
if [[ ! -d "${LOCK_DIR}" ]]; then
	mkdir -p "${LOCK_DIR}"
	chmod a+rwxt "${LOCK_DIR}"
23 24
fi

25 26
include clobber

27
LECA_LOCK_DELAY=2
28
LECA_LOCK_MAXRETRY=0
29

Eric Coissac committed
30
function __lockfile__() {
31 32 33
  echo "${LOCK_DIR}/__${1}__.lecalock"
}

Eric Coissac committed
34
function __locktag__() {
35
  echo "$(hostname).$$"
36 37
}

Eric Coissac committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

function trytogetlock() {
  local lname="$1"
  shift

  local mode="user"

  logdebug "Try to get lock ${lname}"
  
  if [[ "${1}" == "global" ]]; then
    mode="global"
  fi

  if [[ "${mode}" == "global" ]]; then
    name=$(__lockfile__ "${lname}")
  else
    name=$(__lockfile__ "${lname}.$(whoami)")
  fi

  local TAG=$(__locktag__)
  local retry=0

  local notgetlock=1

  pushnoclobber
    echo "${TAG}" 2>/dev/null 1> "${name}"
    notgetlock=$?
  popnoclobber
  
  if (( notgetlock > 0 )); then
    if [[ $(cat "${name}" 2> /dev/null) == "${TAG}" ]]; then
      notgetlock=0
    fi
  fi

  if (( notgetlock == 0 )); then
	  logdebug "Succeed to get lock ${lname}"
  fi

  if (( notgetlock > 0 )); then
    return $notgetlock
  else
  	chmod a+w "${name}"
    return 0
  fi
}

85
function getlock() {
Eric Coissac committed
86
  local lname="$1"
87 88
  shift

89 90
  local mode="user"
  
Eric Coissac committed
91 92
  logdebug "Try to get lock ${lname}"

93 94
  if [[ "${1}" == "global" ]]; then
    mode="global"
95 96 97
  fi

  if [[ "${mode}" == "global" ]]; then
Eric Coissac committed
98
    name=$(__lockfile__ "${lname}")
99
  else
Eric Coissac committed
100
    name=$(__lockfile__ "${lname}.$(whoami)")
101 102
  fi

Eric Coissac committed
103
  local TAG=$(__locktag__)
104 105
  local retry=0

106
  local notgetlock=1
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

  while (( notgetlock > 0 && ( LECA_LOCK_MAXRETRY == 0 || retry > LECA_LOCK_MAXRETRY) )); do

    pushnoclobber
      echo "${TAG}" 2>/dev/null 1> "${name}"
      notgetlock=$?
    popnoclobber

    if (( notgetlock > 0 )); then
      if [[ $(cat "${name}" 2> /dev/null) == "${TAG}" ]]; then
        notgetlock=0
      fi
    fi

    if (( notgetlock > 0 )); then
Eric Coissac committed
122
      logdebug "Failed to get lock ${lname}"
123 124 125 126 127 128 129 130 131
      sleep "${LECA_LOCK_DELAY}"
      retry=$((retry + 1))
    fi

  done

  if (( notgetlock > 0 )); then
    return $notgetlock
  else
Eric Coissac committed
132
	logdebug "Succeed to get lock ${lname}"
133
  	chmod a+w "${name}"
134 135 136 137 138
    return 0
  fi
}

function releaselock() {
Eric Coissac committed
139
  local lname="$1"
140 141
  shift

142 143
  local mode="user"
  
Eric Coissac committed
144 145
  logdebug "Try to release lock ${lname}"
  
146 147
  if [[ "${1}" == "global" ]]; then
    mode="global"
148 149 150
  fi

  if [[ "${mode}" == "global" ]]; then
Eric Coissac committed
151
    name=$(__lockfile__ "${lname}")
152
  else
Eric Coissac committed
153
    name=$(__lockfile__ "${lname}.$(whoami)")
154 155
  fi

Eric Coissac committed
156
  local TAG=$(__locktag__)
157 158 159 160 161 162 163 164 165 166 167
  local LOCK=""

  if [[ -f "${name}" ]]; then
    LOCK=$(cat "${name}" 2> /dev/null)
  else
    return 0
  fi


  if [[ "${LOCK}" == "${TAG}" ]]; then
    rm -f "${name}"
Eric Coissac committed
168
    logdebug "Lock ${lname} released"
169 170 171 172
    return 0
  fi

  return 1
173
}
174

175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

function getsemaphore() {
  local semname="$1"
  shift

  local maxcount="$1"
  shift
  
  local name=""
  local mode="user"
  
  if [[ "${1}" == "global" ]]; then
    mode="global"
  fi

Eric Coissac committed
190
  local TAG=$(__locktag__)
191 192 193 194 195 196 197 198 199
  local retry=0
  local notgetlock=1

  while (( notgetlock > 0 && ( LECA_LOCK_MAXRETRY == 0 || retry > LECA_LOCK_MAXRETRY) )); do
	  local i=0
	  
	  while (( notgetlock > 0 )) && (( i < maxcount )) ; do
	  
		if [[ "${mode}" == "global" ]]; then
Eric Coissac committed
200
		  name=$(__lockfile__ "${semname}.@${i}")
201
		else
Eric Coissac committed
202
		  name=$(__lockfile__ "${semname}.$(whoami).@${i}")
203 204 205 206 207 208 209 210 211 212 213 214 215 216
		fi
			  
		pushnoclobber
		  echo "${TAG}" 2>/dev/null 1> "${name}"
		  notgetlock=$?
		popnoclobber
		
        if (( notgetlock > 0 )); then
	        i=$((i + 1))
        fi
        
	  done
  	
      if (( notgetlock > 0 )); then
217
        loginfo "Failed to get semaphore $semname"
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
        sleep "${LECA_LOCK_DELAY}"
        retry=$((retry + 1))
      fi
  done

  if (( notgetlock > 0 )); then
    return $notgetlock
  else
  	chmod a+w "${name}"
    return 0
  fi
  
}

function releasesemaphore() {
  local name="$1"
  shift

  local mode="user"
  
  if [[ "${1}" == "global" ]]; then
    mode="global"
  fi

  if [[ "${mode}" == "global" ]]; then
Eric Coissac committed
243
	  name=$(__lockfile__ "${name}.@*")
244
  else
Eric Coissac committed
245
	  name=$(__lockfile__ "${name}.$(whoami).@*")
246 247
  fi

248
  toremove=$(ls -tr $name  2> /dev/null | head -1)
249 250 251 252 253 254 255 256 257 258 259
  
  if [[ ! -z "$toremove" ]] ; then
      rm -f "$toremove"
      return 0
  fi
  
  return 1
 }
 
 
 function releaseoldlock() {
260 261
	local minutes=10
	
262
	if [[ ! -z "$1" ]]; then
263 264 265
		minutes="$1"
	fi
	
Eric Coissac committed
266
	for lock in $(find "${LOCK_DIR}" -type f -cmin "+${minutes}" -print); do
267
		rm "${lock}"
Eric Coissac committed
268
		loginfo "releasing old lock: ${lock}"
269
	done
Eric Coissac committed
270

271
}
272