Advertisement
PanaPatryk44

Ucztujący filozofowie 1.061917

Jun 19th, 2017
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.57 KB | None | 0 0
  1. #!/usr/bin/bash
  2. # -*- coding: utf-8 -*-
  3.  
  4.  
  5. quiet_run() {
  6. "$@" >/dev/null 2>&1
  7. }
  8.  
  9. c_locale_run() {
  10. LC_ALL="C.UTF-8" LANG="C.UTF-8" LANGUAGE="C" "$@"
  11. }
  12.  
  13.  
  14. is_int() {
  15. c_locale_run quiet_run printf "%d" "$1"
  16. }
  17.  
  18.  
  19. is_float() {
  20. c_locale_run quiet_run printf "%f" "$1"
  21. }
  22.  
  23. log() {
  24. DATE_MAIN=`date +"%F %T.%N"`
  25. echo "[""$DATE_MAIN"" ""$LOG_IDENTITY""PID-""$BASHPID""] " "$@"
  26. }
  27.  
  28. run_philosopher() {
  29. local PHILOSOPHER_ID=$1
  30. local TABLE_PATH=$2
  31. local MAX_MEALS=$3
  32. local EATING_TIME=$4
  33. local SLEEPING_TIME=$5
  34.  
  35.  
  36. MESSAGE=""
  37. MESSAGE="$MESSAGE""Script file: "`realpath -- "$0"`"; "
  38.  
  39. if [[ "$PHILOSOPHER_ID" -eq "0" ]]
  40. then
  41. LOG_IDENTITY="Main"
  42. MESSAGE="$MESSAGE""Context: ""$LOG_IDENTITY""; "
  43. else
  44. MESSAGE="$MESSAGE""Context: ""$LOG_IDENTITY""; "
  45. if [[ "$PHILOSOPHER_ID" -eq "$PHILOSOPHERS_COUNT" ]]
  46. then
  47. FORK_B="$PHILOSOPHER_ID"
  48. FORK_A="1"
  49. else
  50. FORK_A="$PHILOSOPHER_ID"
  51. FORK_B=$[PHILOSOPHER_ID+1]
  52. fi
  53. FORK_A_PATH=`realpath -- "$TABLE_PATH""/""$FORK_A"`
  54. FORK_B_PATH=`realpath -- "$TABLE_PATH""/""$FORK_B"`
  55. fi
  56.  
  57. MESSAGE="$MESSAGE""Table path: \`\`""$TABLE_PATH""''; "
  58. if [[ "$PHILOSOPHER_ID" -ne "0" ]]
  59. then
  60. MESSAGE="$MESSAGE""Primary fork: ""$FORK_A_PATH""; "
  61. MESSAGE="$MESSAGE""Secondary fork: ""$FORK_B_PATH""; "
  62. fi
  63. MESSAGE="$MESSAGE""Philosophers count: ""$PHILOSOPHERS_COUNT""; "
  64. MESSAGE="$MESSAGE""Maximum meals: ""$MAX_MEALS""; "
  65.  
  66. if [[ -z $EATING_TIME ]]
  67. then
  68. MESSAGE="$MESSAGE""Eating time: randomized; "
  69. else
  70. MESSAGE="$MESSAGE""Eating time: ""$EATING_TIME""s; "
  71. fi
  72.  
  73. if [[ -z $SLEEPING_TIME ]]
  74. then
  75. MESSAGE="$MESSAGE""Sleeping time: randomized; "
  76. else
  77. MESSAGE="$MESSAGE""Sleeping time: ""$SLEEPING_TIME""s; "
  78. fi
  79.  
  80. log "FID#$PHILOSOPHER_ID ""^^^START^^^ ""$MESSAGE"
  81.  
  82. HALF_TIME=$[(MAX_MEALS+1)/2]
  83. MEALS_CONSUMED=0
  84.  
  85. for MEAL_ID in `seq 1 "$MAX_MEALS"`
  86. do
  87. ACTUAL_EATING_TIME=${EATING_TIME:-`random_time`}
  88. ACTUAL_SLEEPING_TIME=${SLEEPING_TIME:-`random_time`}
  89.  
  90. log "FID#$PHILOSOPHER_ID ""FID#$PHILOSOPHER_ID ""Trying to acquire Fork WID#""$FORK_A"
  91. (
  92. flock -x 9
  93. log "FID#$PHILOSOPHER_ID ""Fork WID#""$FORK_A"" acquired successfully (exclusive lock put on fork "$FORK_A")"
  94.  
  95. log "FID#$PHILOSOPHER_ID ""Trying to acquire Fork WID#""$FORK_B (trying to put exclusive lock on fork "$FORK_B")"
  96. (
  97. flock -x 10
  98. log "FID#$PHILOSOPHER_ID ""Fork WID#""$FORK_B"" acquired successfully (exclusive lock put on fork "$FORK_B")"
  99.  
  100. log "FID#$PHILOSOPHER_ID ""Eating Meal#""$MEAL_ID "" started, it will take ""$ACTUAL_EATING_TIME""s"
  101. sleep "$ACTUAL_EATING_TIME"
  102. log "FID#$PHILOSOPHER_ID ""Eating Meal#""$MEAL_ID "" finished"
  103. ) 10>"$FORK_B_PATH"
  104. log "FID#$PHILOSOPHER_ID ""Putting Fork WID#""$FORK_A"" back (exclusive lock dropped from fork "$FORK_B")"
  105.  
  106. ) 9>"$FORK_A_PATH"
  107. log "FID#$PHILOSOPHER_ID ""Putting Fork WID#""$FORK_B"" back (exclusive lock dropped from fork "$FORK_B")"
  108.  
  109. MEALS_CONSUMED=$[MEALS_CONSUMED+1]
  110.  
  111. log "FID#$PHILOSOPHER_ID ""Sleeping after Meal#""$MEAL_ID "" started, it will take ""$ACTUAL_SLEEPING_TIME""s"
  112. sleep "$ACTUAL_SLEEPING_TIME"
  113. log "FID#$PHILOSOPHER_ID ""Sleeping after Meal#""$MEAL_ID "" finished"
  114.  
  115. if [[ "$MEAL_ID" -eq "$HALF_TIME" ]]
  116. then
  117. log "FID#$PHILOSOPHER_ID ""---POŁOWA--- Meals consumed: ""$MEALS_CONSUMED"
  118. echo > "$TABLE_LOCK"
  119. read line < "$TABLE_LOCK""1"
  120. log "FID#$PHILOSOPHER_ID ""Barrier is passed."
  121.  
  122. fi
  123. done
  124.  
  125. log "FID#$PHILOSOPHER_ID ""___STOP___ Meals consumed: ""$MEALS_CONSUMED"
  126. }
  127.  
  128.  
  129.  
  130. random_time() {
  131. echo "0.""$RANDOM"
  132. }
  133.  
  134.  
  135.  
  136.  
  137. #Scrypt start
  138. while getopts ":s:f:n:k:r:i:" OPT
  139. do
  140. case "$OPT" in
  141. s)
  142. FAIL=false
  143. mkdir -p -- "$OPTARG" || FAIL=true
  144.  
  145. if "$FAIL"
  146. then
  147. log "Cannot parse \`\`""$OPTARG""'' as table path, , exiting program with exit code 2..."
  148. exit 2
  149. else
  150. TABLE_PATH="$OPTARG"
  151. fi
  152. ;;
  153. f)
  154. FAIL=false
  155. is_int "$OPTARG" || FAIL=true
  156. if "$FAIL"
  157. then
  158. log "Cannot parse \`\`""$OPTARG""'' as number of philosopers - a non-integer parameter has been given. Exiting program with exit code 4..."
  159. exit 4
  160. fi
  161.  
  162. [[ "$OPTARG" -ge "2" ]] || FAIL=true
  163.  
  164. if "$FAIL"
  165. then
  166. log "Cannot parse \`\`""$OPTARG""'' as number of philosopers - there must be at least 2 philosophers. Exiting program with exit code 5..."
  167. exit 5
  168. else
  169. PHILOSOPHERS_COUNT="$OPTARG"
  170. fi
  171. ;;
  172. n)
  173. FAIL=false
  174. is_int "$OPTARG" || FAIL=true
  175.  
  176. if "$FAIL"
  177. then
  178. log "Cannot parse \`\`""$OPTARG""'' as maximum number meals. Parameter is not an integer. Exiting program with exit code 6..."
  179. exit 6
  180. fi
  181.  
  182. [[ "$OPTARG" -ge "0" ]] || FAIL=true
  183.  
  184. if "$FAIL"
  185. then
  186. log "Cannot parse \`\`""$OPTARG""'' as maximum number meals. Parameter must be a positive integer. Exiting program with exit code 7..."
  187. exit 7
  188. else
  189. MAX_MEALS="$OPTARG"
  190. fi
  191. ;;
  192. k)
  193. FAIL=false
  194. is_float "$OPTARG" || FAIL=true
  195.  
  196. if "$FAIL"
  197. then
  198. log "Cannot parse \`\`""$OPTARG""'' as eating time. Parameter is not a floating-point number. Exiting program with exit code 8..."
  199. exit 8
  200. fi
  201.  
  202. if (( $(echo "$OPTARG<0" | bc) )); then
  203. FAIL=true
  204. fi
  205.  
  206. if "$FAIL"
  207. then
  208. log "Cannot parse \`\`""$OPTARG""'' as eating time. This parameter cannot be a negative number. Exiting program with exit code 9..."
  209. exit 9
  210. else
  211. EATING_TIME="$OPTARG"
  212. fi
  213. ;;
  214. r)
  215. FAIL=false
  216. is_float "$OPTARG" || FAIL=true
  217. if "$FAIL"
  218. then
  219. log "Cannot parse \`\`""$OPTARG""'' as sleeping time. The parameter is not a floating-point number. Exiting program with exit code 10..."
  220. exit 10
  221. fi
  222.  
  223. if (( $(echo "$OPTARG<0" | bc) )); then
  224. FAIL=true
  225. fi
  226. if "$FAIL"
  227. then
  228. log "Cannot parse \`\`""$OPTARG""'' as sleeping time. The parameter cannot be a negative number. Exiting program with exit code 11..."
  229. exit 11
  230. else
  231. SLEEPING_TIME="$OPTARG"
  232. fi
  233. ;;
  234. i)
  235. FAIL=false
  236. is_int "$OPTARG" || FAIL=true
  237. if "$FAIL"
  238. then
  239. log "Cannot parse \`\`""$OPTARG""'' as philosopher ID. The parameter is not an integer. Exiting program with exit code 12..."
  240. exit 12
  241. fi
  242.  
  243. [[ "$OPTARG" -ge "1" ]] || FAIL=true
  244.  
  245. if "$FAIL"
  246. then
  247. log "Cannot parse \`\`""$OPTARG""'' as philosopher ID. The parameter cannot be lesser than 1. Exiting program with exit code 13..."
  248. exit 13
  249. else
  250. PHILOSOPHER_ID="$OPTARG"
  251. LOG_IDENTITY="FID#""$PHILOSOPHER_ID"
  252. fi
  253. ;;
  254. \:)
  255. log "\`\`""-$OPTARG""'' requires some value. Exiting program with exit code 14..."
  256. exit 14
  257. ;;
  258. \?)
  259. log "\`\`""-$OPTARG""'' is not a valid argument. Exiting program with exit code 15..."
  260. exit 15
  261. ;;
  262. esac
  263. done
  264.  
  265. if [ ! -d "$TABLE_PATH""stol" ]; then
  266. mkdir -p "$TABLE_PATH""stol"
  267.  
  268. fi
  269.  
  270.  
  271.  
  272. TABLE_PATH=${TABLE_PATH:-`realpath -- "$TABLE_PATH""stol"`}
  273. TABLE_PATH=`realpath -- "$TABLE_PATH"`
  274. PHILOSOPHERS_COUNT=${PHILOSOPHERS_COUNT:-5}
  275. MAX_MEALS=${MAX_MEALS:-7}
  276. PHILOSOPHER_ID=${PHILOSOPHER_ID:-0}
  277. TABLE_LOCK="$TABLE_PATH""/table.lock"
  278.  
  279.  
  280. for i in `seq 1 "$PHILOSOPHERS_COUNT"`
  281. do
  282. if [ -f "$TABLE_PATH""stol""/""$i" ]; then
  283. touch "$TABLE_PATH""stol""/""$i"
  284. if [ $? -ne 0 ]; then
  285. log "Failed to create fork $i, exiting program with exit code 16..."
  286. exit 16;
  287. fi
  288.  
  289. fi
  290. done
  291.  
  292. if [ -f "$TABLE_LOCK" ]; then
  293. mkfifo "$TABLE_LOCK"
  294. if [ $? -ne 0 ]; then
  295. log "Failed to create pipe, exiting program with exit code 3..."
  296. exit 3;
  297. fi
  298. fi
  299. if [ -f "$TABLE_LOCK""1" ]; then
  300. mkfifo "$TABLE_LOCK""1"
  301. if [ $? -ne 0 ]; then
  302. log "Failed to create pipe, exiting program with exit code 3..."
  303. exit 3;
  304. fi
  305. fi
  306. a=( $(shuf -e $(seq 1 "$PHILOSOPHERS_COUNT")) )
  307. for i in "${a[@]}"
  308. do
  309.  
  310. log `hostname`" STARTUJE FILOZOF... "$i" "$TABLE_PATH" "$MAX_MEALS" "$EATING_TIME" "$SLEEPING_TIME""
  311. run_philosopher "$i" "$TABLE_PATH" "$MAX_MEALS" "$EATING_TIME" "$SLEEPING_TIME" &
  312. done
  313. for i in `seq 1 "$PHILOSOPHERS_COUNT"`
  314. do
  315. read line < "$TABLE_LOCK"
  316. done
  317. for i in `seq 1 "$PHILOSOPHERS_COUNT"`
  318. do
  319. echo > "$TABLE_LOCK""1"
  320. done
  321.  
  322. for CPID in `pgrep -P "$$" | xargs`
  323. do
  324. wait "$CPID"
  325. done
  326.  
  327. log "___STOP___"
  328.  
  329. #Description of all non-zero exit codes:
  330. #Exit code 2 -- occurs if table with given name could not be created - either another, non-directory file with same name exists within present working directory, or you do not have proper permissions
  331. # występuje w sytuacji, gdy nie udało się utworzyć stołu o podanej nazwie - istnieje plik regularny o takiej samej nazwie jak zadany stół lub obecny użytkownik nie posiada uprawnień niezbędnych do stworzenia nowego folderu
  332. #Exit code 3 -- occurs if one or both of the pipes with names table.lock and table.lock1 could not be created - for similar reasons as in case of exit code 2
  333. # występuje, gdy nie uda się utworzyć któregoś z potoków (o nazwach table.lock i table.lock1) - powody dla których nie udało się tego dokonać mogą być podobne do tych co w przypadku kodu wyjścia 2
  334. #Exit code 4 -- occurs if -f parameter is not an integer - problem assumes, that number of philosophers is a positive integer greater or equal 2
  335. # występuje w przypadku, gdy podany parametr -f nie jest liczbą całkowitą - poprawne sformułowanie problemu wymaga, by liczba filozofów była liczbą naturalną niemniejszą niż 2
  336. #Exit code 5 -- occurs if -f parameter is an integer, but it is lesser than 2 - problem assumes that there are at least 2 philosophers
  337. # występuje w przypadku, gdy podany parametr -f jest liczbą całkowitą, ale jest mniejszy od 2 - poprawne sformułowanie problemu zakłada, że liczba filozofów jest niemniejsza niż 2
  338. #Exit code 6 -- occurs if -n parameter, describing number of meals to be eaten by each philosopher is not an integer
  339. # występuje w sytuacji, gdy parametr -n opisujący liczbę posiłków, które zje każdy z filozofów nie jest liczbą całkowitą
  340. #Exit code 7 -- occurs if -n parameter is not a positive integer, which is not possible for the correct formulation of the problem
  341. # występuje w sytuacji, gdy parametr -n nie jest liczbą naturalną dodatnią -- w poprawnie sformułowanym problemie nie jest możliwe, by filozofowie spożyli niedodatnią liczbę posiłków
  342. #Exit code 8 -- occurs if -k parameter, describing eating time is not a floating-point number
  343. # występuje w przypadku, gdy parametr -k opisujący czas spożywania posiłku nie jest liczbą zmiennoprzecinkową
  344. #Exit code 9 -- occurs if -k parameter is a floating-point number, but it is not positive
  345. # występuje w przypadku, gdy parametr -k jest niedodatnią liczbą zmiennoprzecinkową
  346. #Exit code 10 -- occurs if -r parameter, describing sleeping time is not a floating-point number
  347. # występuje w przypadku, gdy parametr -r opisujący czas rozmyślania po posiłku nie jest liczbą zmiennoprzecinkową
  348. #Exit code 11 -- occurs if -r parameter is a nonpositive floating-point number
  349. # występuje w przypadku, gdy parametr -r jest liczbą zmiennoprzecinkową niedodatnią
  350. #Exit code 12 -- occurs if philosopher id parameter -i is not an integer
  351. # występuje w przypadku, gdy zadeklarowano ID filozofa nie będące liczbą całkowitą (opcja -i)
  352. #Exit code 13 -- occurs if philosopher id parameter -i is a nonpositive integer
  353. # występuje w przypadku, gdy zadeklarowano ID filozofa będące liczbą całkowitą mniejszą od 1
  354. #Exit code 14 -- occurs if some option is obtained without a parameter
  355. # występuje w przypadku, gdy podana zostanie nazwa opcji obsługiwanej przez skrypt, jednak bez wartości parametru
  356. #Exit code 15 -- occurs if user gave an option which is not described and irrevelant to dining philosophers problem
  357. # występuje, gdy użytkownik poda nazwę opcji nieopisanej w skrypcie i niepotrzebnej w problemie ucztujących filozofów
  358. #Exit code 16 -- occurs if creating one of the forks was not possible -- for similar reasons as in case of exit code 2
  359. # występuje, gdy nie można utworzyć któregoś z plików widelców -- z przyczyn podobnych jak w przypadku kodu wyjścia 2
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement