# !/bin/ bash ## In this scenario, we create the number of consumers, each with their ## own fifo, and then the producer will hand out messages by cycling through ## their fifos and if the dirlock is available it will write to their fifo ## (otherwise it will continue to cycle through) FIFO_PREF = "/tmp/bgfifo" LOCK_PREF = "/tmp/bgfifo.lock." # message number N =1 # number of consumers C =10 create_fifos () { ## create the fifos for i in $( seq 0 $((C-1))); do CONSUMER_FIFO = "$FIFO_PREF$i" CONSUMER_LOCK = "$LOCK_PREF$i" mkfifo "$CONSUMER_FIFO" rmdir $ CONSUMER_LOCK done } # make a table with these columns # pid_consumer,pid_echo # this table should be used when checking the status of writes # or checking which pid has which index declare -A status init_consumers () { pids =$( pgrep -f "consumer-back" ) # C rows, 2 columns for (( i =0;i<=C-1;i++)) do CONSUMER_FIFO = "$FIFO_PREF$i" # we start the consumer in the background, it will wait for data # to be available on its associated fifo echo "Creating consumer.." nohup ./consumer-back.sh "$i" & # consumer pid status [$ i ,0]=$ ! # slot for consumer echo pid status [$ i ,1]=0 done } kill_consumers () { # needs to be reimplemented echo "closing consumers" for (( i =0;i<=C-1;i++)) do CONSUMER_LOCK = "$LOCK_PREF$i" cpid =${ status [$ i ,0]} epid =${ status [$ i ,1]} if [[ $ cpid > 0 ]]; then echo "closing consumer $cpid" kill -9 $ cpid 2>/dev/null fi if [[ $ epid > 0 ]]; then kill -9 $ epid 2>/dev/null fi done } producer () { ## start generating messages and distribute them ## among the consumers while (( N <= 5000 )); do ## NOTE: We overcome the problems related to blocking writes because ## we put in the background every single write we make # produce message and send it to the first free consumer for (( i =0;i<=C-1;i++)) do CONSUMER_FIFO = "$FIFO_PREF$i" CONSUMER_LOCK = "$LOCK_PREF$i" cpid =${ status [$ i ,0]} epid =${ status [$ i ,1]} kill -0 $ cpid 2>/dev/null ok_cons =$ ? kill -0 $ epid 2>/dev/null ok_echo =$ ? # if the consumer is still there and there's no previous # writes on this consumer's fifo then dispatch a message to it if [[ $ ok_cons -eq 0 && $( mkdir $ CONSUMER_LOCK 2>/dev/null; echo $ ? ;) == 1 ]]; then echo "consumer $cpid was free" # produce next message # and send it echo "message $N" > $ CONSUMER_FIFO 2>/dev/null & # update epid status [$ i ,1]=$ ! # we could break here and wait for the next iteration # find another free consumer N =$((N+1)) else echo "consumer $cpid was busy" fi done echo "====================" done } # kill consumers upon exit trap '{ kill_consumers; exit 0; }' SIGINT create_fifos init_consumers producer wait