mutex.sh 3.62 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's avatar
Eric Coissac committed
15
if [[ -z "$LOCK_DIR" ]] ; then
Eric Coissac's avatar
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's avatar
Eric Coissac committed
30
function __lockfile__() {
31 32 33
  echo "${LOCK_DIR}/__${1}__.lecalock"
}

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

function getlock() {
39 40 41
  local name="$1"
  shift

42 43 44 45
  local mode="user"
  
  if [[ "${1}" == "global" ]]; then
    mode="global"
46 47 48
  fi

  if [[ "${mode}" == "global" ]]; then
Eric Coissac's avatar
Eric Coissac committed
49
    name=$(__lockfile__ "${name}")
50
  else
Eric Coissac's avatar
Eric Coissac committed
51
    name=$(__lockfile__ "${name}.$(whoami)")
52 53
  fi

Eric Coissac's avatar
Eric Coissac committed
54
  local TAG=$(__locktag__)
55 56
  local retry=0

57
  local notgetlock=1
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81

  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
      sleep "${LECA_LOCK_DELAY}"
      retry=$((retry + 1))
    fi

  done

  if (( notgetlock > 0 )); then
    return $notgetlock
  else
82
  	chmod a+w "${name}"
83 84 85 86 87 88 89 90
    return 0
  fi
}

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

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

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

Eric Coissac's avatar
Eric Coissac committed
103
  local TAG=$(__locktag__)
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
  local LOCK=""

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


  if [[ "${LOCK}" == "${TAG}" ]]; then
    rm -f "${name}"
    return 0
  fi

  return 1
119
}
120

121 122 123 124 125 126 127 128 129 130 131 132 133 134 135

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

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

Eric Coissac's avatar
Eric Coissac committed
136
  local TAG=$(__locktag__)
137 138 139 140 141 142 143 144 145
  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's avatar
Eric Coissac committed
146
		  name=$(__lockfile__ "${semname}.@${i}")
147
		else
Eric Coissac's avatar
Eric Coissac committed
148
		  name=$(__lockfile__ "${semname}.$(whoami).@${i}")
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
		fi
			  
		pushnoclobber
		  echo "${TAG}" 2>/dev/null 1> "${name}"
		  notgetlock=$?
		popnoclobber
		
        if (( notgetlock > 0 )); then
	        i=$((i + 1))
        fi
        
	  done
  	
      if (( notgetlock > 0 )); then
        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's avatar
Eric Coissac committed
188
	  name=$(__lockfile__ "${name}.@*")
189
  else
Eric Coissac's avatar
Eric Coissac committed
190
	  name=$(__lockfile__ "${name}.$(whoami).@*")
191 192
  fi

193
  toremove=$(ls -tr $name  2> /dev/null | head -1)
194 195 196 197 198 199 200 201 202 203 204
  
  if [[ ! -z "$toremove" ]] ; then
      rm -f "$toremove"
      return 0
  fi
  
  return 1
 }
 
 
 function releaseoldlock() {
205 206
	local minutes=10
	
207
	if [[ ! -z "$1" ]]; then
208 209 210
		minutes="$1"
	fi
	
Eric Coissac's avatar
Eric Coissac committed
211
	for lock in $(find "${LOCK_DIR}" -type f -cmin "+${minutes}" -print); do
212
		rm "${lock}"
Eric Coissac's avatar
Eric Coissac committed
213
		loginfo "releasing old lock: ${lock}"
214
	done
Eric Coissac's avatar
Eric Coissac committed
215

216
}
217