update

update

global num_servers
set num_servers to 12

on open_window_tabs()
	tell application "Terminal"
		activate
		-- Open a new window
		--   http://superuser.com/questions/195633/applescript-to-open-a-new-terminal-window-in-current-space
		do script "clear"
		-- set currentWindow to front window

		-- Open new tabs
		repeat (num_servers * 2 - 1) times
			tell application "System Events" to tell process "Terminal" to keystroke "t" using command down
		end repeat
	end tell
end open_window_tabs

on ssh()
	tell application "Terminal"
		set currentWindow to front window

		-- Without the delay, some connections are not made.
		set delay_after_ssh to 0.5

		set tab_id to 0
		set s_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "sshs" & s_id
			do script (cmd) in tab tab_id of currentWindow
			delay delay_after_ssh

			set tab_id to tab_id + 1
			set cmd to "sshc" & s_id
			do script (cmd) in tab tab_id of currentWindow
			delay delay_after_ssh

			set s_id to s_id + 1
		end repeat
	end tell
end ssh

on screen()
	tell application "Terminal"
		set currentWindow to front window

		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "screen"
			do script (cmd) in tab tab_id of currentWindow
			set cmd to " "
			do script (cmd) in tab tab_id of currentWindow
		end repeat
	end tell
end screen

on install_pkgs_0()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "sudo add-apt-repository -y ppa:webupd8team/java"
			set cmd to cmd & " && sudo apt-get update"
			set cmd to cmd & " && sudo apt-get install oracle-java8-installer git ctags ant htop tree maven gnuplot-nox ntp ioping realpath make gcc cmake g++ libboost-dev libboost-system-dev libboost-timer-dev collectl -y"
			set cmd to cmd & " && sudo apt-get autoremove -y vim-tiny"
			set cmd to cmd & " && mkdir -p ~/work"
			set cmd to cmd & " && cd ~/work"
			set cmd to cmd & " && git clone https://github.com/hoytech/vmtouch.git"
			set cmd to cmd & " && cd vmtouch"
			set cmd to cmd & " && make -j"
			set cmd to cmd & " && sudo make install"
			set cmd to cmd & " && sudo service ntp stop"
			set cmd to cmd & " && sudo ntpdate -bv 0.ubuntu.pool.ntp.org"
			set cmd to cmd & " && sudo service ntp start"
			set cmd to cmd & " && cd ~/work"
			set cmd to cmd & " && git clone git@github.com:hobinyoon/linux-home.git"
			set cmd to cmd & " && cd linux-home"
			set cmd to cmd & " && ./setup-linux.sh"
			do script (cmd) in tab tab_id of currentWindow
		end repeat
	end tell
end install_pkgs_0

on install_pkgs_1()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is (num_servers * 2)
		set tab_id to tab_id + 1
		tell application "System Events" to key code 36 -- enter
		delay 0.2
		tell application "System Events" to key code 123 -- left
		tell application "System Events" to key code 36 -- enter
		tell application "System Events" to key code 124 using {shift down, command down} -- move to the next tab
		delay 0.1
	end repeat
end install_pkgs_1

-- Sometimes the previous step takes forever. Need to make sure.
on install_pkgs_2()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "yes"
			do script (cmd) in tab tab_id of currentWindow
			delay 0.1
		end repeat
	end tell
end install_pkgs_2

on killall_screen()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "killall screen"
			do script (cmd) in tab tab_id of currentWindow
		end repeat
	end tell
end killall_screen

on exit_screen()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "X"

		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "X"

		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "X"

		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "d" using {control down}
		delay 0.1

		-- Move to the right
		tell application "System Events" to key code 124 using {shift down, command down}

		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "d" using {control down}
		delay 0.1

		-- Move to the right
		tell application "System Events" to key code 124 using {shift down, command down}
	end repeat
end exit_screen

on server_screen_split_htop()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "S"
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "c"
		tell application "System Events" to keystroke "htop"
		tell application "System Events" to key code 36

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "S"
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "c"
		tell application "System Events" to keystroke "watch -n 0.5 \"free -mt\""
		tell application "System Events" to key code 36

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "S"
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "c"

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab

		-- Move 2 to the right, since S and C take turns.
		--   124: right arrow
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end server_screen_split_htop

on client_screen_split_htop()
	tell application "Terminal" to activate
	set tab_id to 0
	-- Start from the 2nd tab, which is the first client tab
	tell application "System Events" to key code 124 using {shift down, command down}
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "S"
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "c"
		tell application "System Events" to keystroke "htop"
		tell application "System Events" to key code 36

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab

		-- Move 2 to the right, since S and C take turns.
		--   124: right arrow
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	-- Set the current tab to the 1st one
	tell application "System Events" to key code 123 using {shift down, command down}

end client_screen_split_htop

on build_cass_pressuremem_loadgen()
	tell application "Terminal"
		set currentWindow to front window

		-- Without the delay, some connections are not made.
		set delay_after_ssh to 0.2

		set tab_id to 0
		set s_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "cd ~/work && git clone git@github.com:hobinyoon/apache-cassandra-2.2.3-src.git && ln -s ~/work/apache-cassandra-2.2.3-src ~/work/cassandra && cd ~/work/cassandra/mtdb/tools/pressure-memory && mkdir -p .build && cd .build && cmake .. && make -j && cdcass && time ant"
			do script (cmd) in tab tab_id of currentWindow
			delay delay_after_ssh

			set tab_id to tab_id + 1
			set cmd to "cd ~/work && git clone git@github.com:hobinyoon/apache-cassandra-2.2.3-src.git && ln -s ~/work/apache-cassandra-2.2.3-src ~/work/cassandra && cd ~/work/cassandra/mtdb/loadgen && ./loadgen"
			do script (cmd) in tab tab_id of currentWindow
			delay delay_after_ssh

			set s_id to s_id + 1
		end repeat
	end tell
end build_cass_pressuremem_loadgen

on git_pull()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is (num_servers * 2)
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "c" using {control down}

		-- Move to the next tab
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "cdcass && git pull"
			do script (cmd) in tab tab_id of currentWindow
		end repeat
	end tell
end git_pull

on server_format_ebs_mag_mount_dev_prepare_dirs()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "sudo mkfs.ext4 -m 0 /dev/xvdd"
			set cmd to cmd & " && sudo cp ~/work/cassandra/mtdb/ec2-tools/etc-fstab /etc/fstab"
			set cmd to cmd & " && sudo umount /mnt"
			set cmd to cmd & " && sudo mkdir -p /mnt/local-ssd"
			set cmd to cmd & " && sudo mount /mnt/local-ssd"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/local-ssd"
			set cmd to cmd & " && mkdir /mnt/local-ssd/cass-data"
			set cmd to cmd & " && mkdir ~/cass-data-vol"
			set cmd to cmd & " && sudo ln -s ~/cass-data-vol /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && mkdir /mnt/ebs-ssd-gp2/cass-data"
			set cmd to cmd & " && sudo mkdir -p /mnt/ebs-mag"
			set cmd to cmd & " && sudo mount /mnt/ebs-mag"
			set cmd to cmd & " && sudo mkdir /mnt/ebs-mag/cass-data"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/ebs-mag"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/ebs-mag/cass-data"
			set cmd to cmd & " && sudo mkdir -p /mnt/ebs-ssd-gp2/mtdb-cold"
			set cmd to cmd & " && (sudo mkdir -p /mnt/ebs-mag/mtdb-cold || true)"
			set cmd to cmd & " && sudo ln -s /mnt/ebs-mag /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage/mtdb-cold"
			set cmd to cmd & " && mkdir -p ~/work/cassandra/mtdb/logs/collectl"
			set cmd to cmd & " && ln -s /mnt/local-ssd/cass-data ~/work/cassandra/data"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_format_ebs_mag_mount_dev_prepare_dirs

on server_mount_dev_prepare_dirs_cass_data_to_ebs_ssd()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "sudo cp ~/work/cassandra/mtdb/ec2-tools/etc-fstab /etc/fstab"
			set cmd to cmd & " && sudo umount /mnt"
			set cmd to cmd & " && sudo mkdir -p /mnt/local-ssd"
			set cmd to cmd & " && sudo mount /mnt/local-ssd"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/local-ssd"
			set cmd to cmd & " && mkdir /mnt/local-ssd/cass-data"
			set cmd to cmd & " && mkdir ~/cass-data-vol"
			set cmd to cmd & " && sudo ln -s ~/cass-data-vol /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && mkdir /mnt/ebs-ssd-gp2/cass-data"
			set cmd to cmd & " && sudo mkdir -p /mnt/ebs-ssd-gp2/mtdb-cold"
			set cmd to cmd & " && sudo ln -s /mnt/ebs-ssd-gp2 /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage/mtdb-cold"
			set cmd to cmd & " && mkdir -p ~/work/cassandra/mtdb/logs/collectl"
			set cmd to cmd & " && ln -s /mnt/ebs-ssd-gp2/cass-data ~/work/cassandra/data"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_mount_dev_prepare_dirs_cass_data_to_ebs_ssd

on server_mount_dev_prepare_dirs_cass_data_to_local_ssd_cold_data_to_ebs_ssd()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "sudo cp ~/work/cassandra/mtdb/ec2-tools/etc-fstab /etc/fstab"
			set cmd to cmd & " && sudo umount /mnt"
			set cmd to cmd & " && sudo mkdir -p /mnt/local-ssd"
			set cmd to cmd & " && sudo mount /mnt/local-ssd"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/local-ssd"
			set cmd to cmd & " && mkdir /mnt/local-ssd/cass-data"
			set cmd to cmd & " && mkdir ~/cass-data-vol"
			set cmd to cmd & " && sudo ln -s ~/cass-data-vol /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && mkdir /mnt/ebs-ssd-gp2/cass-data"
			set cmd to cmd & " && sudo mkdir -p /mnt/ebs-ssd-gp2/mtdb-cold"
			set cmd to cmd & " && sudo ln -s /mnt/ebs-ssd-gp2 /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage/mtdb-cold"
			set cmd to cmd & " && mkdir -p ~/work/cassandra/mtdb/logs/collectl"
			set cmd to cmd & " && ln -s /mnt/local-ssd/cass-data ~/work/cassandra/data"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_mount_dev_prepare_dirs_cass_data_to_local_ssd_cold_data_to_ebs_ssd

on server_edit_cassandra_yaml()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "sed -i -r 's/^    migrate_to_cold_storage:.+/    migrate_to_cold_storage: true/' ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow
			set cmd to "sed -i -r 's/^    tablet_coldness_threshold:.+/    tablet_coldness_threshold: 75/' ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow
			set cmd to "grep migrate_to_cold_storage: ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow
			set cmd to "grep tablet_coldness_threshold: ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_edit_cassandra_yaml

on client_edit_cassandra_yaml()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 2
		repeat until tab_id > (num_servers * 2)
			set cmd to "sed -i -r 's/^        num_writes_per_simulation_time_mins:.+/        num_writes_per_simulation_time_mins: " & (tab_id * 5000) & "/' ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow
			set cmd to "grep num_writes_per_simulation_time_mins: ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next client tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end client_edit_cassandra_yaml

on save_screen_layout()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is (num_servers * 2)
		set tab_id to tab_id + 1

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke ":layout save default"
		tell application "System Events" to key code 36

		-- Move to the next tab
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end save_screen_layout

-- One-time fix. Won't need again
on mkdir_collectl()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "mkdir ~/work/cassandra/mtdb/logs/collectl"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end mkdir_collectl

on run_server()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "sudo -- sh -c 'echo 1 > /proc/sys/vm/drop_caches' && cdcass && time ant && rm -rf ~/work/cassandra/data/* && rm -rf /mnt/cold-storage/mtdb-cold/* && (killall mon-num-cass-threads.sh >/dev/null 2>&1 || true) && (~/work/cassandra/mtdb/tools/mon-num-cass-threads.sh &) && (killall collectl >/dev/null 2>&1 || true) && ((collectl -i 1 -sCDN -oTm > ~/work/cassandra/mtdb/logs/collectl/collectl-`date +'%y%m%d-%H%M%S'` 2>/dev/null) &) && bin/cassandra -f | grep --color -E '^|MTDB:'"
			do script (cmd) in tab tab_id of currentWindow
			-- Give enough delay to make sure the logs have different datetimes.
			delay 3

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end run_server

on server_pressure_memory()
	tell application "Terminal" to activate

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "cd ~/work/cassandra/mtdb/tools/pressure-memory/.build"
			set cmd to cmd & " && (./pressure-memory &)"
			set cmd to cmd & " && watchsstables"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end server_pressure_memory

on client_run_loadgen()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 2
		repeat until tab_id > (num_servers * 2)
			set cmd to "cd ~/work/cassandra/mtdb/loadgen && ./create-db.sh && ./loadgen"
			do script (cmd) in tab tab_id of currentWindow
			-- Make sure we get different exp datetime
			delay 2
			-- Go to the next client tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end client_run_loadgen

on screen_detach()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is (num_servers * 2)
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "d"
		delay 0.1
		-- Move to the next tab
		tell application "System Events" to key code 124 using {shift down, command down}
	end repeat
end screen_detach

on screen_reattach()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "screen -r"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next tab
			set tab_id to tab_id + 1
		end repeat
	end tell
end screen_reattach

on server_get_client_logs_and_process()
	tell application "Terminal" to activate

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "c" using {control down}

		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "(killall pressure-memory > /dev/null 2>&1 || true) && (sudo killall collectl > /dev/null 2>&1 || true) && (sudo killall mon-num-cass-threads.sh > /dev/null 2>&1 || true) && rsync -ave \"ssh -o StrictHostKeyChecking=no\" $CASSANDRA_CLIENT_ADDR:work/cassandra/mtdb/logs/loadgen ~/work/cassandra/mtdb/logs && cd ~/work/cassandra/mtdb/process-log/calc-cost-latency-plot-tablet-timeline && (\\rm *.pdf || true) && ./plot-cost-latency-tablet-timelines.py && du -hs ~/work/cassandra/data/"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end server_get_client_logs_and_process

-- One-time fix. Won't need again
on server_rename_client_log()
	tell application "Terminal" to activate

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			-- I don't like the float division. oh well.
			set cmd to "mv ~/work/cassandra/mtdb/logs/loadgen/160302-023811 ~/work/cassandra/mtdb/logs/loadgen/160302-023811-" & ((tab_id - 1) / 2) & " && mv ~/work/cassandra/mtdb/logs/cassandra/160302-023811 ~/work/cassandra/mtdb/logs/cassandra/160302-023811-" & ((tab_id - 1) / 2)
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end server_rename_client_log

-- One-time use.
on server_kill_monitor_processes()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "(killall pressure-memory > /dev/null 2>&1 || true) && (sudo killall collectl > /dev/null 2>&1 || true) && (sudo killall mon-num-cass-threads.sh > /dev/null 2>&1 || true)"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_kill_monitor_processes

on server_switch_data_dir_to_ebs_mag()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "cdcass"
			set cmd to cmd & " && \\rm data"
			set cmd to cmd & " && ln -s /mnt/ebs-mag/cass-data data"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_switch_data_dir_to_ebs_mag

on server_switch_data_dir_to_local_ssd()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "cdcass"
			set cmd to cmd & " && \\rm data"
			set cmd to cmd & " && ln -s /mnt/local-ssd/cass-data data"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_switch_data_dir_to_local_ssd

on open_window_tabs_ssh_screen()
	my open_window_tabs()
	my ssh()
	my screen()
end open_window_tabs_ssh_screen

on run_all()
	my open_window_tabs_ssh_screen()

	my install_pkgs_0()
	my install_pkgs_1()
	my install_pkgs_2()

	-- Not a normal process. In case something goes wrong.
	-- my exit_screen()

	-- Need to logout and login again to make the new .bashrc in effect
	-- Hit ^D until all tabs are closed
	my open_window_tabs_ssh_screen()

	-- These can be grouped
	my server_screen_split_htop()
	my client_screen_split_htop()
	my build_cass_pressuremem_loadgen()

	my save_screen_layout()
	my screen_detach()
	my screen_reattach()

	-- Run either of these, depending on what dev you have
	-- my server_format_ebs_mag_mount_dev_prepare_dirs()
	-- my server_mount_dev_prepare_dirs_cass_data_to_ebs_ssd()
	my server_mount_dev_prepare_dirs_cass_data_to_local_ssd_cold_data_to_ebs_ssd()

	-- Switch data directory to ebs mag
	-- my server_switch_data_dir_to_ebs_mag()

	-- Make sure which experiment you want, by editing migrate_to_cold_storage
	my server_edit_cassandra_yaml()
	my client_edit_cassandra_yaml()

	-- This takes some time to make sure each server has different exp datetime
	my run_server()

	-- Wait till all servers are ready before pressuring memory
	my server_pressure_memory()

	-- This takes some time too.
	my client_run_loadgen()

	-- Detach screen to save network traffic while running experiments
	my save_screen_layout()
	my screen_detach()

	-- May want to check the last tabs to see if the system saturates or cold sstables are created

	-- When done, reattach the screen and process the logs
	my screen_reattach()
	my server_get_client_logs_and_process()

	-- Switch data directory to ebs mag
	-- my server_switch_data_dir_to_ebs_mag()
end run_all

global num_servers
set num_servers to 12

on open_window_tabs()
	tell application "Terminal"
		activate
		-- Open a new window
		--   http://superuser.com/questions/195633/applescript-to-open-a-new-terminal-window-in-current-space
		do script "clear"
		-- set currentWindow to front window

		-- Open new tabs
		repeat (num_servers * 2 - 1) times
			tell application "System Events" to tell process "Terminal" to keystroke "t" using command down
		end repeat
	end tell
end open_window_tabs

on ssh()
	tell application "Terminal"
		set currentWindow to front window

		-- Without the delay, some connections are not made.
		set delay_after_ssh to 0.5

		set tab_id to 0
		set s_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "sshs" & s_id
			do script (cmd) in tab tab_id of currentWindow
			delay delay_after_ssh

			set tab_id to tab_id + 1
			set cmd to "sshc" & s_id
			do script (cmd) in tab tab_id of currentWindow
			delay delay_after_ssh

			set s_id to s_id + 1
		end repeat
	end tell
end ssh

on screen()
	tell application "Terminal"
		set currentWindow to front window

		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "screen"
			do script (cmd) in tab tab_id of currentWindow
			set cmd to " "
			do script (cmd) in tab tab_id of currentWindow
		end repeat
	end tell
end screen

on install_pkgs_0()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "sudo add-apt-repository -y ppa:webupd8team/java && sudo apt-get update && sudo apt-get install oracle-java8-installer git ctags ant htop tree maven gnuplot-nox ntp ioping realpath make gcc cmake g++ libboost-dev libboost-system-dev libboost-timer-dev collectl -y && sudo apt-get autoremove -y vim-tiny && mkdir -p ~/work && cd ~/work && git clone https://github.com/hoytech/vmtouch.git && cd vmtouch && make -j && sudo make install && sudo service ntp stop && sudo ntpdate -bv 0.ubuntu.pool.ntp.org && sudo service ntp start && cd ~/work && git clone git@github.com:hobinyoon/linux-home.git && cd linux-home && ./setup-linux.sh"
			do script (cmd) in tab tab_id of currentWindow
		end repeat
	end tell
end install_pkgs_0

on install_pkgs_1()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is (num_servers * 2)
		set tab_id to tab_id + 1
		tell application "System Events" to key code 36 -- enter
		delay 0.2
		tell application "System Events" to key code 123 -- left
		tell application "System Events" to key code 36 -- enter
		tell application "System Events" to key code 124 using {shift down, command down} -- move to the next tab
		delay 0.1
	end repeat
end install_pkgs_1

-- Sometimes the previous step takes forever. Need to make sure.
on install_pkgs_2()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "yes"
			do script (cmd) in tab tab_id of currentWindow
			delay 0.1
		end repeat
	end tell
end install_pkgs_2

on killall_screen()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "killall screen"
			do script (cmd) in tab tab_id of currentWindow
		end repeat
	end tell
end killall_screen

on exit_screen()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "X"

		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "X"

		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "X"

		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "d" using {control down}
		delay 0.1

		-- Move to the right
		tell application "System Events" to key code 124 using {shift down, command down}

		tell application "System Events" to keystroke "d" using {control down}
		tell application "System Events" to keystroke "d" using {control down}
		delay 0.1

		-- Move to the right
		tell application "System Events" to key code 124 using {shift down, command down}
	end repeat
end exit_screen

on server_screen_split_htop()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "S"
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "c"
		tell application "System Events" to keystroke "htop"
		tell application "System Events" to key code 36

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "S"
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "c"
		tell application "System Events" to keystroke "watch -n 0.5 \"free -mt\""
		tell application "System Events" to key code 36

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "S"
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "c"

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab

		-- Move 2 to the right, since S and C take turns.
		--   124: right arrow
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end server_screen_split_htop

on client_screen_split_htop()
	tell application "Terminal" to activate
	set tab_id to 0
	-- Start from the 2nd tab, which is the first client tab
	tell application "System Events" to key code 124 using {shift down, command down}
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "S"
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "c"
		tell application "System Events" to keystroke "htop"
		tell application "System Events" to key code 36

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab

		-- Move 2 to the right, since S and C take turns.
		--   124: right arrow
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	-- Set the current tab to the 1st one
	tell application "System Events" to key code 123 using {shift down, command down}

end client_screen_split_htop

on build_cass_pressuremem_loadgen()
	tell application "Terminal"
		set currentWindow to front window

		-- Without the delay, some connections are not made.
		set delay_after_ssh to 0.2

		set tab_id to 0
		set s_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "cd ~/work && git clone git@github.com:hobinyoon/apache-cassandra-2.2.3-src.git && ln -s ~/work/apache-cassandra-2.2.3-src ~/work/cassandra && cd ~/work/cassandra/mtdb/tools/pressure-memory && mkdir -p .build && cd .build && cmake .. && make -j && cdcass && time ant"
			do script (cmd) in tab tab_id of currentWindow
			delay delay_after_ssh

			set tab_id to tab_id + 1
			set cmd to "cd ~/work && git clone git@github.com:hobinyoon/apache-cassandra-2.2.3-src.git && ln -s ~/work/apache-cassandra-2.2.3-src ~/work/cassandra && cd ~/work/cassandra/mtdb/loadgen && ./loadgen"
			do script (cmd) in tab tab_id of currentWindow
			delay delay_after_ssh

			set s_id to s_id + 1
		end repeat
	end tell
end build_cass_pressuremem_loadgen

on git_pull()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is (num_servers * 2)
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "c" using {control down}

		-- Move to the next tab
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 0
		repeat until tab_id is (num_servers * 2)
			set tab_id to tab_id + 1
			set cmd to "cdcass && git pull"
			do script (cmd) in tab tab_id of currentWindow
		end repeat
	end tell
end git_pull

on server_format_ebs_mag_mount_dev_prepare_dirs()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "sudo mkfs.ext4 -m 0 /dev/xvdd"
			set cmd to cmd & " && sudo cp ~/work/cassandra/mtdb/ec2-tools/etc-fstab /etc/fstab"
			set cmd to cmd & " && sudo umount /mnt"
			set cmd to cmd & " && sudo mkdir -p /mnt/local-ssd"
			set cmd to cmd & " && sudo mount /mnt/local-ssd"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/local-ssd"
			set cmd to cmd & " && mkdir /mnt/local-ssd/cass-data"
			set cmd to cmd & " && mkdir ~/cass-data-vol"
			set cmd to cmd & " && sudo ln -s ~/cass-data-vol /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && mkdir /mnt/ebs-ssd-gp2/cass-data"
			set cmd to cmd & " && sudo mkdir -p /mnt/ebs-mag"
			set cmd to cmd & " && sudo mount /mnt/ebs-mag"
			set cmd to cmd & " && sudo mkdir /mnt/ebs-mag/cass-data"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/ebs-mag"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/ebs-mag/cass-data"
			set cmd to cmd & " && sudo mkdir -p /mnt/ebs-ssd-gp2/mtdb-cold"
			set cmd to cmd & " && (sudo mkdir -p /mnt/ebs-mag/mtdb-cold || true)"
			set cmd to cmd & " && sudo ln -s /mnt/ebs-mag /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage/mtdb-cold"
			set cmd to cmd & " && mkdir -p ~/work/cassandra/mtdb/logs/collectl"
			set cmd to cmd & " && ln -s /mnt/local-ssd/cass-data ~/work/cassandra/data"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_format_ebs_mag_mount_dev_prepare_dirs

on server_mount_dev_prepare_dirs_cass_data_to_ebs_ssd()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "sudo cp ~/work/cassandra/mtdb/ec2-tools/etc-fstab /etc/fstab"
			set cmd to cmd & " && sudo umount /mnt"
			set cmd to cmd & " && sudo mkdir -p /mnt/local-ssd"
			set cmd to cmd & " && sudo mount /mnt/local-ssd"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/local-ssd"
			set cmd to cmd & " && mkdir /mnt/local-ssd/cass-data"
			set cmd to cmd & " && mkdir ~/cass-data-vol"
			set cmd to cmd & " && sudo ln -s ~/cass-data-vol /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && mkdir /mnt/ebs-ssd-gp2/cass-data"
			set cmd to cmd & " && sudo mkdir -p /mnt/ebs-ssd-gp2/mtdb-cold"
			set cmd to cmd & " && sudo ln -s /mnt/ebs-ssd-gp2 /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/ebs-ssd-gp2"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage"
			set cmd to cmd & " && sudo chown -R ubuntu /mnt/cold-storage/mtdb-cold"
			set cmd to cmd & " && mkdir -p ~/work/cassandra/mtdb/logs/collectl"
			set cmd to cmd & " && ln -s /mnt/ebs-ssd-gp2/cass-data ~/work/cassandra/data"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_mount_dev_prepare_dirs_cass_data_to_ebs_ssd

on server_edit_cassandra_yaml()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			--			set cmd to "sed -i -r 's/^    migrate_to_cold_storage:.+/    migrate_to_cold_storage: true/' ~/work/cassandra/conf/cassandra.yaml"
			set cmd to "sed -i -r 's/^    migrate_to_cold_storage:.+/    migrate_to_cold_storage: false/' ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow
			set cmd to "sed -i -r 's/^    tablet_coldness_threshold:.+/    tablet_coldness_threshold: 75/' ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_edit_cassandra_yaml

on client_edit_cassandra_yaml()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 2
		repeat until tab_id > (num_servers * 2)
			set cmd to "sed -i -r 's/^        num_writes_per_simulation_time_mins:.+/        num_writes_per_simulation_time_mins: " & (tab_id * 5000) & "/' ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow
			set cmd to "grep num_writes_per_simulation_time_mins: ~/work/cassandra/conf/cassandra.yaml"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next client tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end client_edit_cassandra_yaml

on save_screen_layout()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is (num_servers * 2)
		set tab_id to tab_id + 1

		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke ":layout save default"
		tell application "System Events" to key code 36

		-- Move to the next tab
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end save_screen_layout

-- One-time fix. Won't need again
on mkdir_collectl()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "mkdir ~/work/cassandra/mtdb/logs/collectl"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end mkdir_collectl

on run_server()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "sudo -- sh -c 'echo 1 > /proc/sys/vm/drop_caches' && cdcass && time ant && rm -rf ~/work/cassandra/data/* && rm -rf /mnt/cold-storage/mtdb-cold/* && (killall mon-num-cass-threads.sh >/dev/null 2>&1 || true) && (~/work/cassandra/mtdb/tools/mon-num-cass-threads.sh &) && (killall collectl >/dev/null 2>&1 || true) && ((collectl -i 1 -sCDN -oTm > ~/work/cassandra/mtdb/logs/collectl/collectl-`date +'%y%m%d-%H%M%S'` 2>/dev/null) &) && bin/cassandra -f | grep --color -E '^|MTDB:'"
			do script (cmd) in tab tab_id of currentWindow
			-- Give enough delay to make sure the logs have different datetimes.
			delay 3

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end run_server

on server_pressure_memory()
	tell application "Terminal" to activate

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "cd ~/work/cassandra/mtdb/tools/pressure-memory/.build"
			set cmd to cmd & " && (./pressure-memory &)"
			set cmd to cmd & " && watchsstables"
			do script (cmd) in tab tab_id of currentWindow

			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end server_pressure_memory

on client_run_loadgen()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 2
		repeat until tab_id > (num_servers * 2)
			set cmd to "cd ~/work/cassandra/mtdb/loadgen && ./create-db.sh && ./loadgen"
			do script (cmd) in tab tab_id of currentWindow
			-- Make sure we get different exp datetime
			delay 2
			-- Go to the next client tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end client_run_loadgen

on screen_detach()
	tell application "Terminal" to activate
	set tab_id to 0
	repeat until tab_id is (num_servers * 2)
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke "d"
		delay 0.1
		-- Move to the next tab
		tell application "System Events" to key code 124 using {shift down, command down}
	end repeat
end screen_detach

on screen_reattach()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "screen -r"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next tab
			set tab_id to tab_id + 1
		end repeat
	end tell
end screen_reattach

on server_get_client_logs_and_process()
	tell application "Terminal" to activate

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "c" using {control down}

		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "(killall pressure-memory > /dev/null 2>&1 || true) && (sudo killall collectl > /dev/null 2>&1 || true) && (sudo killall mon-num-cass-threads.sh > /dev/null 2>&1 || true) && rsync -ave \"ssh -o StrictHostKeyChecking=no\" $CASSANDRA_CLIENT_ADDR:work/cassandra/mtdb/logs/loadgen ~/work/cassandra/mtdb/logs && cd ~/work/cassandra/mtdb/process-log/calc-cost-latency-plot-tablet-timeline && (\\rm *.pdf || true) && ./plot-cost-latency-tablet-timelines.py && du -hs ~/work/cassandra/data/"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end server_get_client_logs_and_process

-- One-time fix. Won't need again
on server_rename_client_log()
	tell application "Terminal" to activate

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat

	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			-- I don't like the float division. oh well.
			set cmd to "mv ~/work/cassandra/mtdb/logs/loadgen/160302-023811 ~/work/cassandra/mtdb/logs/loadgen/160302-023811-" & ((tab_id - 1) / 2) & " && mv ~/work/cassandra/mtdb/logs/cassandra/160302-023811 ~/work/cassandra/mtdb/logs/cassandra/160302-023811-" & ((tab_id - 1) / 2)
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell

	set tab_id to 0
	repeat until tab_id is num_servers
		set tab_id to tab_id + 1
		tell application "System Events" to keystroke "a" using {control down}
		tell application "System Events" to keystroke tab
		-- Move to the next server tab
		tell application "System Events" to key code 124 using {shift down, command down}
		tell application "System Events" to key code 124 using {shift down, command down}
		delay 0.1
	end repeat
end server_rename_client_log

-- One-time use.
on server_kill_monitor_processes()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "(killall pressure-memory > /dev/null 2>&1 || true) && (sudo killall collectl > /dev/null 2>&1 || true) && (sudo killall mon-num-cass-threads.sh > /dev/null 2>&1 || true)"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_kill_monitor_processes

on server_switch_data_dir_to_ebs_mag()
	tell application "Terminal"
		set currentWindow to front window
		set tab_id to 1
		repeat until tab_id > (num_servers * 2)
			set cmd to "cdcass"
			set cmd to cmd & " && \\rm data"
			set cmd to cmd & " && ln -s /mnt/ebs-mag/cass-data data"
			do script (cmd) in tab tab_id of currentWindow
			-- Go to the next server tab
			set tab_id to tab_id + 2
		end repeat
	end tell
end server_switch_data_dir_to_ebs_mag

on open_window_tabs_ssh_screen()
	my open_window_tabs()
	my ssh()
	my screen()
end open_window_tabs_ssh_screen

on run_all()
	my open_window_tabs_ssh_screen()

	my install_pkgs_0()
	my install_pkgs_1()
	my install_pkgs_2()

	-- Not a normal process. In case something goes wrong.
	-- my exit_screen()

	-- Need to logout and login again to make the new .bashrc in effect
	-- Hit ^D until all tabs are closed
	my open_window_tabs_ssh_screen()

	-- These can be grouped
	my server_screen_split_htop()
	my client_screen_split_htop()
	my build_cass_pressuremem_loadgen()

	my save_screen_layout()
	my screen_detach()
	my screen_reattach()

	-- Run either of these, depending on what dev you have
	-- my server_format_ebs_mag_mount_dev_prepare_dirs()
	my server_mount_dev_prepare_dirs_cass_data_to_ebs_ssd()

	-- Switch data directory to ebs mag
	-- my server_switch_data_dir_to_ebs_mag()

	-- Make sure which experiment you want, by editing migrate_to_cold_storage
	my server_edit_cassandra_yaml()
	my client_edit_cassandra_yaml()

	-- This takes some time to make sure each server has different exp datetime
	my run_server()

	-- Wait till all servers are ready before pressuring memory
	my server_pressure_memory()

	-- This takes some time too.
	my client_run_loadgen()

	my server_get_client_logs_and_process()

	-- Switch data directory to ebs mag
	-- my server_switch_data_dir_to_ebs_mag()
end run_all


Add "Edit Log" action

Add "Edit Log" action

(*
	Log Page - Log categorized web page bookmarks to a text file

	Version: @@VERSION@@
	Date:    2011-02-09
	Author:  Steve Wheeler

	Get the title, URL, current date and time, and a user-definable
	category for the frontmost Safari window and log the info to a text
	file.

	This program is free software available under the terms of a
	BSD-style (3-clause) open source license detailed below.
*)

(*
Copyright (c) 2011 Steve Wheeler
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)

(*
	TODO: Change the following local-only config before any public release.
	The log file should be: $GTD_IN/logs/urls/urls.YYYY.txt
	Or just: $GTD_IN/logs/urls.txt

	TODO: The edit_log() function is currently incomplete. It will only launch
	an editor from the shell and only if that editor is a GUI editor (in this
	case, MacVim). If I release this script publicly, I will still need to
	implement funtionality to launch a GUI editor normally (with the 'open'
	AppleScript commmand) as well as a command-line editor run in the Terminal.
*)

property script_name : "Log Page"
property script_version : "@@VERSION@@"

---------- USER CONFIGURATION ----------------------------------------
-- Default log directory to use if one is not read from config file:
--set log_dir to POSIX path of (path to application support folder from user domain) & "Jazzhead/Log Page/"
set log_dir to POSIX path of (path to desktop folder) & "Log Page/" -- :DEBUG:

-- Log file name:
set log_name to "urls.txt"

-- Default categories/labels if none are found in (or there is no)
-- URL file. Modify as desired:
set default_cats to "Development
Development:AppleScript
Development:AppleScript:Mail
Design
Productivity:GTD
Apple:Mac OS X
Apple:iOS
Career
Education
Health
Health:Diet
Health:Fitness
General"

-- Text editor to use if manually editing the log file.
--
-- This example:
--	1. Opens the file using MacVim ('mvim' as installed by MacPorts)
--	2. Switches the local working directory for just that buffer to the
--	    directory containing the file ('lcd')
--	3. Gives the MacVim window a name ('--servername').
--
set text_editor to "/opt/local/bin/mvim \"+lcd %:p:h\" --servername LOG_PAGE"

-- Should the specified editor be launched from the unix shell?
set should_use_shell to true
---------- END User Configuration ----------------------------------------

---------- ADVANCED (EXPERIMENTAL) ---------------------------------------------
-- For advanced users familiar with the command-line, override the default log
-- directory path. This probably won't be in a public release.
--
-- Grab an exported shell environment variable from a config file to use as the
-- log directory path. For this example, I have a "~/.gtdrc" config file that I
-- source from my "~/.bash_profile" file so that it exportss environment
-- variables relating to my GTD system. That makes those variables available to
-- any of the shell scripts and tools that I use. For instance, when I'm
-- editing files in Vim, I can write paths to other files using one of the
-- environment variables rather than a full or relative path and the 'gf'
-- command will work for jumping to that file. The config file looks like this:
--
--         # ~/.gtdrc
--         #
--         # File locations for GTD documents
--
--         export GTD_DIR=$HOME/Documents/org  # GTD root directory
--         export GTD_IN=$GTD_DIR/content      # source/input files
--         export GTD_OUT=$GTD_DIR/html        # generated HTML output files
--         export GTD_LIB=$GTD_DIR/lib         # code library files
--         export GTD_BIN=$GTD_LIB/script      # scripts
--
-- Remove (or comment out) the "(*" and "*)" comment markers below to use this
-- section. Make sure you also configure the two variables for your system.
--(*
--------------- USER CONFIGURATION ----------
-- Path to your config file:
set cfg_file to POSIX path of (path to home folder) & ".gtdrc"
-- The environment variable you're interested in:
set env_var to "GTD_IN"
--------------- END User Configuration ---------

-- Check for environment variable in config file:
set s to "egrep '\\<" & env_var & "=' " & quoted form of cfg_file &
	" > /dev/null 2>&1; echo $?"
set shell_status to (do shell script s) as integer
-- Source the config file and echo the desired variable:
if shell_status is 0 then -- (means that grep found a match)
	set s to ". " & quoted form of cfg_file & " && echo $" & env_var
	set gtd_in_dir to do shell script s
	set log_dir to gtd_in_dir & "/logs/"

	--------------------
	-- OPTIONAL: Override the Text editor to integrate with my GTD system.
	--
	-- This example:
	--	1. Opens the file using MacVim ('mvim' as installed by MacPorts)
	--	2. Switches the local working directory ('lcd') for just that buffer to
	--	    my GTD content directory ($GTD_IN after escaping potential spaces)
	--	3. Gives the MacVim window a name ('--servername').

	----- First, escape any potential spaces in the directory path:
	--
	--set gtd_in_dir to gtd_in_dir & " foo    bar" -- :DEBUG: spaces in path
	--
	set s to "echo " & quoted form of gtd_in_dir & " | sed 's/ \\{1,\\}/\\\\ /g'" -- escape spaces
	set gtd_in_dir to do shell script s
	--
	--log gtd_in_dir -- :DEBUG: need to use 'log' to see the value w/o AppleScript escapes

	----- Finally, set the editor with all of the options:
	--
	set text_editor to "/opt/local/bin/mvim \"+lcd " & gtd_in_dir & "\" --servername GTD --remote-silent"
	--
	--log text_editor -- :DEBUG:
	--return text_editor -- :DEBUG:
	--------------------
end if
---------- END Advanced --------------------------------------------------------
--*)

--return log_dir -- :DEBUG:

--
-- Get URL and title from front browser window
--
tell application "Safari"
	--activate
	try
		set this_url to URL of front document
		set this_title to name of first tab of front window whose visible is true
	on error
		return false
	end try
end tell
-- Transliterate non-ASCII characters to ASCII
set this_title to convert_to_ascii(this_title)

--return this_title -- :DEBUG:

--
-- Format the record separator between log entries
--
set rule_char to "-"
set rule_width to 80
set field_width to 7
set field_sep to " | "
set rec_sep to "" & multiply_text(rule_char, field_width - 1) &
	"+" & multiply_text(rule_char, rule_width - field_width)

--
-- Format date-time string as "YYYY-MM-DD HH:MM:SS"
--
set {year:y, month:m, day:d, hours:hh, minutes:mm, seconds:ss} to current date
set m to m as integer -- coerce month string
-- Pad numbers with leading zeros:
set tmp_list to {}
repeat with this_item in {m, d, hh, mm, ss}
	set this_item to text 2 thru -1 of (100 + this_item as text)
	set end of tmp_list to this_item
end repeat
set {m, d, hh, mm, ss} to tmp_list
-- Final string:
set date_time to join_list({y, m, d}, "-") & " " & join_list({hh, mm, ss}, ":")

-- Log file name
--set log_name to "urls." & y & ".txt"

--
-- Create log directory if it doesn't already exist. (Go ahead and use a shell
-- command since it's easy to create intermediate directories all in one step.):
--
try
	set s to "mkdir -pm700 " & quoted form of log_dir
	do shell script s
on error err_msg number err_num
	error "Can't create log directory: " & err_msg number err_num
	return "Fatal Error: Can't create log directory"
end try

set log_file_posix to "" & log_dir & log_name
set log_file to POSIX file log_file_posix

--
-- Add header to new or empty log file
--
set should_init to false
tell application "Finder"
	if (not (exists log_file)) or (_IO's read_file(log_file) is "") then
		set should_init to true
	end if
end tell

set head_sep to multiply_text("#", 80)
if should_init then
	set file_header to head_sep & "
# urls.txt - Timestamped and categorized URL archive
# ==================================================
# Optionally list some categories/labels of URLs below that might not yet
# be used. Any categories/lables listed here or in the web page records
# will be presented as a list to select from when saving new URLs.
" & head_sep & linefeed & default_cats & linefeed & head_sep & "
# END: category/label list
" & head_sep & linefeed
	tell _IO to write_file(log_file, file_header)
	set cat_txt to default_cats
else
	-- Read categories from file
	(*
		:TODO: Error handling.
	*)
	set cat_txt to text 2 thru -2 of (item 3 of split_text(_IO's read_file(log_file), head_sep))
end if

-- Parse any existing labels from the "Label" fields of the URLs file:
set s to "egrep '^Label ' " & quoted form of log_file_posix &
	" | sed 's/^Label | //' | sort | uniq"
--return s
set used_cats to do shell script s without altering line endings
-- Sort those along with the manually entered categories/labels:
set s to "echo \"" & cat_txt & linefeed & used_cats & "\" | egrep -v '^$' | sort | uniq"
set cat_txt to do shell script s
-- Coerce the lines into a list:
set cat_list to paragraphs of cat_txt
--return cat_list -- :DEBUG:

--
-- Prompt for category/subcategory of URL
--

-- Select an existing category
set msg to "Please select a category for the URL you want to log. You will have a chance to edit your choice."
set cat_choice to choose from list cat_list with title script_name with prompt msg OK button name "Select"
--if cat_choice is false then return false
if cat_choice is false then set cat_choice to "Please enter a category..."

-- Modify or enter a new category
set btns to {"Cancel", "Manually Edit Log File", "Append URL to Log File"}
set msg to "To log the URL for:" & return & return
	& tab & "\"" & this_title & "\"" & return & return &
	"please provide a category and any optional subcategories (or edit your selected category) for the URL. Example: \"Development:AppleScript:Mail\""
display dialog msg default answer cat_choice with title script_name buttons btns default button last item of btns
set {this_label, btn_pressed} to {text returned of result, button returned of result}

--
-- Append or edit the log file
--
if btn_pressed is last item of btns then
	set final_text to join_list({
		"Date " & field_sep & date_time,
		"Label" & field_sep & this_label,
		"Title" & field_sep & this_title,
		"URL  " & field_sep & this_url,
		rec_sep}, linefeed) & linefeed
	_IO's append_file(log_file, final_text)
else
	if should_use_shell then
		set this_log_file to quoted form of log_file_posix
	else
		set this_log_file to log_file
	end if
	edit_log(this_log_file, text_editor, should_use_shell)
end if

--display alert "Log Page" message "DEBUG: Script complete."

(************************************************************
 *	Subroutines
 ************************************************************)

-- ===== Main Functions =====

on edit_log(log_file, text_editor, should_use_shell)
	(*
		TODO:MAYBE:
		Have a configuration variable in the main script to specify which text
		editor to use. Have another variable for configuring whether or not
		it's a GUI application. Then this function would use 'open' to launch a
		GUI app or script the Terminal to launch a command-line editor.
		Optionally use 'do shell script' to launch a compatible GUI app from a
		command line (so that the working directory can be changed to that of
		the file first), but I don't know if that will really be necessary
		since I have a Vim shortcut for quickly changing the working directory
		if need be.
	*)
	if should_use_shell then
		set s to text_editor & space & log_file & space & "> /dev/null 2>&1"
		do shell script s
		return
	else
		set t to script_name
		set m to ":TODO: edit_log() function: use non-shell-invoked editor."
		set b to {"Cancel"}
		display alert t message m buttons b cancel button 1 as critical
		return false
	end if
end edit_log

-- ===== Utility Functions =====

on convert_to_ascii(non_ascii_txt)
	set s to "iconv -f UTF-8 -t US-ASCII//TRANSLIT <<<" & quoted form of non_ascii_txt
	do shell script s
end convert_to_ascii

on multiply_text(str, n)
	if n < 1 or str = "" then return ""
	set lst to {}
	repeat n times
		set end of lst to str
	end repeat
	return lst as string
end multiply_text

on split_text(txt, delim)
	set old_tids to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to (delim as string)
		set lst to every text item of (txt as string)
		set AppleScript's text item delimiters to old_tids
		return lst
	on error err_msg number err_num
		set AppleScript's text item delimiters to old_tids
		error "Can't split_text(): " & err_msg number err_num
	end try
end split_text

on join_list(lst, delim)
	set old_tids to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to (delim as string)
		set txt to lst as string
		set AppleScript's text item delimiters to old_tids
		return txt
	on error err_msg number err_num
		set AppleScript's text item delimiters to old_tids
		error "Can't join_list(): " & err_msg number err_num
	end try
end join_list

(************************************************************
 *	Script Objects
 ************************************************************)

script _IO

	(* == PUBLIC == *)

	on write_file(file_path, this_data)
		_write_file(file_path, this_data, string, false) -- overwrite existing file
	end write_file

	on append_file(file_path, this_data)
		_write_file(file_path, this_data, string, true) -- append new data to end of existing file
	end append_file

	on read_file(file_path)
		_read_file(file_path, string)
	end read_file

	(* == PRIVATE == *)

	on _write_file(file_path, this_data, data_class, should_append_data)
		try
			set file_path to file_path as text
			set file_handle to
				open for access file file_path with write permission
			if not should_append_data then
				set eof of the file_handle to 0
			write this_data as data_class to file_handle starting at eof
			close access file_handle
			return true
		on error err_msg number err_num
			try
				close access file file_path
			end try
			error err_msg number err_num
			return false
		end try
	end _write_file

	on _read_file(file_path, data_class)
		try
			set file_path to file_path as text
			if (get eof file file_path) is 0 then
				set file_contents to ""
			else
				set file_contents to read file file_path as data_class
			end if
			return file_contents
		on error
			return 0
		end try
	end _read_file
end script

(*
	Log Page - Log categorized web page bookmarks to a text file

	Version: @@VERSION@@
	Date:    2011-02-09
	Author:  Steve Wheeler

	Get the title, URL, current date and time, and a user-definable
	category for the frontmost Safari window and log the info to a text
	file.

	This program is free software available under the terms of a
	BSD-style (3-clause) open source license detailed below.
*)

(*
Copyright (c) 2011 Steve Wheeler
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)

(*
	TODO: Change the following local-only config before any public release.
	The log file should be: $GTD_IN/logs/urls/urls.YYYY.txt
	Or just: $GTD_IN/logs/urls.txt
*)

property script_name : "Log Page"
property script_version : "@@VERSION@@"

---------- USER CONFIGURATION ----------------------------------------
-- Default log directory to use if one is not read from config file:
set log_dir to POSIX path of (path to application support folder from user domain) & "Jazzhead/Log Page/"
--set log_dir to POSIX path of (path to desktop folder) & "Log Page/" -- :DEBUG:

-- Log file name:
set log_name to "urls.txt"

-- Default categories/labels if none are found in (or there is no)
-- URL file. Modify as desired:
set default_cats to "Development
Development:AppleScript
Development:AppleScript:Mail
Design
Productivity:GTD
Apple:Mac OS X
Apple:iOS
Career
Education
Health
Health:Diet
Health:Fitness
General"
---------- END User Configuration ----------------------------------------

---------- ADVANCED (EXPERIMENTAL) ---------------------------------------------
-- For advanced users familiar with the command-line, override the default log
-- directory path. This probably won't be in a public release.
--
-- Grab an exported shell environment variable from a config file to use as the
-- log directory path. For this example, I have a "~/.gtdrc" config file that I
-- source from my "~/.bash_profile" file so that it exportss environment
-- variables relating to my GTD system. That makes those variables available to
-- any of the shell scripts and tools that I use. For instance, when I'm
-- editing files in Vim, I can write paths to other files using one of the
-- environment variables rather than a full or relative path and the 'gf'
-- command will work for jumping to that file. The config file looks like this:
--
--         # ~/.gtdrc
--         #
--         # File locations for GTD documents
--
--         export GTD_DIR=$HOME/Documents/org  # GTD root directory
--         export GTD_IN=$GTD_DIR/content      # source/input files
--         export GTD_OUT=$GTD_DIR/html        # generated HTML output files
--         export GTD_LIB=$GTD_DIR/lib         # code library files
--         export GTD_BIN=$GTD_LIB/script      # scripts
--
-- Remove (or comment out) the "(*" and "*)" comment markers below to use this
-- section. Make sure you also configure the two variables for your system.
--(*
--------------- USER CONFIGURATION ----------
-- Path to your config file:
set cfg_file to POSIX path of (path to home folder) & ".gtdrc"
-- The environment variable you're interested in:
set env_var to "GTD_IN"
--------------- END User Configuration ---------

-- Check for environment variable in config file:
set s to "egrep '\\<" & env_var & "=' " & quoted form of cfg_file &
	" > /dev/null 2>&1; echo $?"
set shell_status to (do shell script s) as integer
-- Source the config file and echo the desired variable:
if shell_status is 0 then -- (means that grep found a match)
	set s to ". " & quoted form of cfg_file & " && echo $" & env_var
	set log_dir to (do shell script s) & "/logs/"
end if
---------- END Advanced --------------------------------------------------------
--*)

--return log_dir -- :DEBUG:

--
-- Get URL and title from front browser window
--
tell application "Safari"
	--activate
	try
		set this_url to URL of front document
		set this_title to name of first tab of front window whose visible is true
	on error
		return false
	end try
end tell
-- Transliterate non-ASCII characters to ASCII
set this_title to convert_to_ascii(this_title)

--return this_title -- :DEBUG:

--
-- Format the record separator between log entries
--
set rule_char to "-"
set rule_width to 80
set field_width to 7
set field_sep to " | "
set rec_sep to "" & multiply_text(rule_char, field_width - 1) &
	"+" & multiply_text(rule_char, rule_width - field_width)

--
-- Format date-time string as "YYYY-MM-DD HH:MM:SS"
--
set {year:y, month:m, day:d, hours:hh, minutes:mm, seconds:ss} to current date
set m to m as integer -- coerce month string
-- Pad numbers with leading zeros:
set tmp_list to {}
repeat with this_item in {m, d, hh, mm, ss}
	set this_item to text 2 thru -1 of (100 + this_item as text)
	set end of tmp_list to this_item
end repeat
set {m, d, hh, mm, ss} to tmp_list
-- Final string:
set date_time to join_list({y, m, d}, "-") & " " & join_list({hh, mm, ss}, ":")

-- Log file name
--set log_name to "urls." & y & ".txt"

--
-- Create log directory if it doesn't already exist. (Go ahead and use a shell
-- command since it's easy to create intermediate directories all in one step.):
--
try
	set s to "mkdir -pm700 " & quoted form of log_dir
	do shell script s
on error err_msg number err_num
	error "Can't create log directory: " & err_msg number err_num
	return "Fatal Error: Can't create log directory"
end try

set log_file_posix to "" & log_dir & log_name
set log_file to POSIX file log_file_posix

--
-- Add header to new or empty log file
--
set should_init to false
tell application "Finder"
	if (not (exists log_file)) or (_IO's read_file(log_file) is "") then
		set should_init to true
	end if
end tell

set head_sep to multiply_text("#", 80)
if should_init then
	set file_header to head_sep & "
# urls.txt - Timestamped and categorized URL archive
# ==================================================
# Optionally list some categories/labels of URLs below that might not yet
# be used. Any categories/lables listed here or in the web page records
# will be presented as a list to select from when saving new URLs.
" & head_sep & linefeed & default_cats & linefeed & head_sep & "
# END: category/label list
" & head_sep & linefeed
	tell _IO to write_file(log_file, file_header)
	set cat_txt to default_cats
else
	-- Read categories from file
	(*
		:TODO: Error handling.
	*)
	set cat_txt to text 2 thru -2 of (item 3 of split_text(_IO's read_file(log_file), head_sep))
end if

-- Parse any existing labels from the "Label" fields of the URLs file:
set s to "egrep '^Label ' " & quoted form of log_file_posix &
	" | sed 's/^Label | //' | sort | uniq"
--return s
set used_cats to do shell script s without altering line endings
-- Sort those along with the manually entered categories/labels:
set s to "echo \"" & cat_txt & linefeed & used_cats & "\" | egrep -v '^$' | sort | uniq"
set cat_txt to do shell script s
-- Coerce the lines into a list:
set cat_list to paragraphs of cat_txt
--return cat_list -- :DEBUG:

--
-- Prompt for category/subcategory of URL
--

-- Select an existing category
set msg to "Please select a category for the URL you want to log. You will have a chance to edit your choice."
set cat_choice to choose from list cat_list with title script_name with prompt msg OK button name "Select"
--if cat_choice is false then return false
if cat_choice is false then set cat_choice to "Please enter a category..."

-- Modify or enter a new category
set btns to {"Cancel", "TODO: Edit Log File", "Append URL to File"}
set msg to "To log the URL for:" & return & return
	& tab & "\"" & this_title & "\"" & return & return &
	"please provide a category and any optional subcategories (or edit your selected category) for the URL. Example: \"Development:AppleScript:Mail\""
display dialog msg default answer cat_choice with title script_name buttons btns default button last item of btns
set {this_label, btn_pressed} to {text returned of result, button returned of result}

--
-- Append or edit the log file
--
if btn_pressed is last item of btns then
	set final_text to join_list({
		"Date " & field_sep & date_time,
		"Label" & field_sep & this_label,
		"Title" & field_sep & this_title,
		"URL  " & field_sep & this_url,
		rec_sep}, linefeed) & linefeed
	_IO's append_file(log_file, final_text)
else
	edit_log()
end if

(************************************************************
 *	Subroutines
 ************************************************************)

-- ===== Main Functions =====

on edit_log()
	(*
		TODO:MAYBE:
		Have a configuration variable in the main script to specify which text
		editor to use. Have another variable for configuring whether or not
		it's a GUI application. Then this function would use 'open' to launch a
		GUI app or script the Terminal to launch a command-line editor.
		Optionally use 'do shell script' to launch a compatible GUI app from a
		command line (so that the working directory can be changed to that of
		the file first), but I don't know if that will really be necessary
		since I have a Vim shortcut for quickly changing the working directory
		if need be.
	*)
	set t to script_name
	set m to ":TODO: Implement edit_log() function."
	set b to {"Cancel"}
	display alert t message m buttons b cancel button 1 as critical
	return false
end edit_log

-- ===== Utility Functions =====

on convert_to_ascii(non_ascii_txt)
	set s to "iconv -f UTF-8 -t US-ASCII//TRANSLIT <<<" & quoted form of non_ascii_txt
	do shell script s
end convert_to_ascii

on multiply_text(str, n)
	if n < 1 or str = "" then return ""
	set lst to {}
	repeat n times
		set end of lst to str
	end repeat
	return lst as string
end multiply_text

on split_text(txt, delim)
	set old_tids to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to (delim as string)
		set lst to every text item of (txt as string)
		set AppleScript's text item delimiters to old_tids
		return lst
	on error err_msg number err_num
		set AppleScript's text item delimiters to old_tids
		error "Can't split_text(): " & err_msg number err_num
	end try
end split_text

on join_list(lst, delim)
	set old_tids to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to (delim as string)
		set txt to lst as string
		set AppleScript's text item delimiters to old_tids
		return txt
	on error err_msg number err_num
		set AppleScript's text item delimiters to old_tids
		error "Can't join_list(): " & err_msg number err_num
	end try
end join_list

(************************************************************
 *	Script Objects
 ************************************************************)

script _IO

	(* == PUBLIC == *)

	on write_file(file_path, this_data)
		_write_file(file_path, this_data, string, false) -- overwrite existing file
	end write_file

	on append_file(file_path, this_data)
		_write_file(file_path, this_data, string, true) -- append new data to end of existing file
	end append_file

	on read_file(file_path)
		_read_file(file_path, string)
	end read_file

	(* == PRIVATE == *)

	on _write_file(file_path, this_data, data_class, should_append_data)
		try
			set file_path to file_path as text
			set file_handle to
				open for access file file_path with write permission
			if not should_append_data then
				set eof of the file_handle to 0
			write this_data as data_class to file_handle starting at eof
			close access file_handle
			return true
		on error err_msg number err_num
			try
				close access file file_path
			end try
			error err_msg number err_num
			return false
		end try
	end _write_file

	on _read_file(file_path, data_class)
		try
			set file_path to file_path as text
			if (get eof file file_path) is 0 then
				set file_contents to ""
			else
				set file_contents to read file file_path as data_class
			end if
			return file_contents
		on error
			return 0
		end try
	end _read_file
end script


Fixed keynote file opening

Fixed keynote file opening

-- thumbscrew.scpt
-- usage: thumbscript.scpt <keynotePresentation>
--
-- Will create scaled thumbnails of length `thumbSize` in the directory
-- <path_to_keynotePresentation>/<thumbnailDir>
property thumbSize : 480
property thumbnailDir: "thumbnail"

on getImages(f)
  tell application "Finder" to return (files of folder f) as alias list
end getImages

on run argv
  set repoPath to item 1 of argv
  set documentName to item 2 of argv
  set documentFullName to repoPath & "/" & documentName

  set keynoteFile to (POSIX file documentFullName) as alias
  set documentPath to posix file (POSIX path of (do shell script "dirname " & quoted form of documentFullName)) as alias

  tell application "Finder"
    if not (exists folder thumbnailDir of folder documentPath)
      make new folder at folder documentPath with properties {name:thumbnailDir}
    end if
    set the targetFolder to folder thumbnailDir of folder documentPath
    set the targetFolderHFSPath to targetFolder as string
  end tell

  tell application "Keynote" to run
  tell application "Keynote"
    open keynoteFile

    if playing is true then stop the front document

    export front document as slide images to file targetFolderHFSPath with properties {image format: JPEG}
    set jpegs to my getImages(targetFolderHFSPath)
    repeat with thisJPEG in jpegs
      try
        tell application "Image Events"
          launch
          set this_image to open thisJPEG
          scale this_image to size thumbSize
          save this_image with icon
          close this_image
        end tell
        on error error_message
          display dialog error_message
      end try
    end repeat

    close front document without saving
  end tell

end run

-- thumbscrew.scpt
-- usage: thumbscript.scpt <keynotePresentation>
--
-- Will create scaled thumbnails of length `thumbSize` in the directory
-- <path_to_keynotePresentation>/<thumbnailDir>
property thumbSize : 480
property thumbnailDir: "thumbnail"

on getImages(f)
  tell application "Finder" to return (files of folder f) as alias list
end getImages

on run argv
  set repoPath to item 1 of argv
  set documentName to item 2 of argv
  set documentFullName to repoPath & "/" & documentName

  set documentPath to posix file (POSIX path of (do shell script "dirname " & quoted form of documentFullName)) as alias

  tell application "Finder"
    if not (exists folder thumbnailDir of folder documentPath)
      make new folder at folder documentPath with properties {name:thumbnailDir}
    end if
    set the targetFolder to folder thumbnailDir of folder documentPath
    set the targetFolderHFSPath to targetFolder as string
  end tell

  tell application "Keynote" to run
  tell application "Keynote"
    open documentFullName

    if playing is true then stop the front document

    export front document as slide images to file targetFolderHFSPath with properties {image format: JPEG}
    set jpegs to my getImages(targetFolderHFSPath)
    repeat with thisJPEG in jpegs
      try
        tell application "Image Events"
          launch
          set this_image to open thisJPEG
          scale this_image to size thumbSize
          save this_image with icon
          close this_image
        end tell
        on error error_message
          display dialog error_message
      end try
    end repeat

    close front document without saving
  end tell

end run