No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cbl.sh 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. #!/bin/bash
  2. #
  3. # CBL : Curl Benchmark on Lodel
  4. #
  5. # Usage : $0 [HOSTNAME] [INSTANCE_LIST_FILE] [N_CREATE] [N_EDIT] [N_DELETE]
  6. #
  7. # Instance_list_file is expected to be a file containing instances name (1 per
  8. # line). Uses by default /tmp/lodel2_instance_list.txt
  9. #
  10. # Instances base URL are generated given the current webui implementation :
  11. # http://HOST/INSTANCE_NAME/
  12. #
  13. #
  14. # Scenario description :
  15. #
  16. # mass_creation instance_name iteration_count :
  17. # Create iteration_count time a random leobject in given instance_name
  18. # note : do note create relation between objects, only populate content
  19. #
  20. # step 1 : fetch all non abstract class name
  21. # step 2 : loop on creation (using bash function curl_opt_create_CLSNAME)
  22. # that return the POST fields (populated with random values)
  23. #
  24. # mass_deletion instance_name iteration_count :
  25. # Foreach non asbtracty class delete iteration_count time an object of
  26. # current class in current instance
  27. #
  28. # step 1 : fetch all non abstract class name
  29. # step 2 : loop on non abstract class name
  30. # step 3 : loop iteration_count time on deletion
  31. #
  32. # mass_link_edit instance_name iteration_count :
  33. # Foreach non abstract class make iteration_count time edition of an
  34. # object in current class
  35. # note : only implemented for Person for the moment
  36. # note : can maybe ask for invalid modifications
  37. #
  38. # step 1 : fetch all non abstract class name
  39. # step 2 : loop on non abstract class name
  40. # step 3 : depends on curent class :
  41. # - fetch all existing id of current class
  42. # - fetch all existing id in class that can be linked with
  43. # current class
  44. # step 4 : loop iteration_count time :
  45. # - choose a random id in current class
  46. # - choose random ids from linkable classes
  47. # - trigger edition using curl (with datas from the same
  48. # bash function than creation : curl_opt_create_CLSNAME)
  49. #
  50. # Current way to run scenarios :
  51. #
  52. # using the function run_bg_with_param FUNCTION_NAME INSTANCE_LIST_FILE *ARGS
  53. #
  54. # The function name can be one of the scenario functions
  55. # INSTANCE_LIST_FILE is the file containing instances list
  56. # *ARGS are args given as it to FUNCTION_NAME after the instance_name argument
  57. #
  58. # function call : FUN_NAME INSTANCE_NAME *ARGS
  59. #
  60. # The run_bg_with_param run a scenario in background for each instance allowing
  61. # to send a lot of request at the same time
  62. #
  63. #
  64. usage() {
  65. echo "Usage : $0 [HOSTNAME] [INSTANCE_LIST_FILE] [CREATE_COUNT] [EDIT_COUNT] [DELETE_COUNT]"
  66. exit
  67. }
  68. host=$1
  69. host=${host:=localhost}
  70. instance_list=$2
  71. instance_list=${instance_list:=/tmp/lodel2_instance_list.txt}
  72. #A modifier for requests count
  73. n_create=$3
  74. n_create=${n_create:=50}
  75. n_edit=$4
  76. n_edit=${n_edit:=10}
  77. n_delete=$5
  78. n_delete=${n_delete:=10}
  79. for i in $(seq $#)
  80. do
  81. echo $1 |grep -E "^-?-h" &>/dev/null
  82. shift
  83. done
  84. #curl_options='--silent -o /dev/null -s -w %{http_code}:%{time_connect}:%{time_starttransfer}:%{time_total}\n'
  85. curl_options='--silent -o /dev/null -s -w %{url_effective};%{http_code};%{time_connect};%{time_starttransfer};%{time_total}\n'
  86. curl_debug_opt='-v -w %{url_effective};%{http_code};%{time_connect};%{time_starttransfer};%{time_total}\n'
  87. curl_cmd="curl $curl_options"
  88. curl_raw="curl --silent"
  89. curl_debug="curl $curl_debug_opt"
  90. curcurl="$curl_cmd"
  91. cmktemp="mktemp -t lodel2_cbl_XXXXXXXX"
  92. _base_uri() {
  93. echo -n "http://$host/$1"
  94. }
  95. rnd_str() {
  96. len=$1
  97. cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $len | head -n 1
  98. }
  99. rnd_str_len() {
  100. minlen=$1
  101. maxlen=$2
  102. cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w $(shuf -i${minlen}-${maxlen} -n1) | head -n 1
  103. }
  104. mass_creation() {
  105. #mass creation scenario
  106. #$1 is instance name
  107. #$2 is iteration count (1 iteration is 1 creation of a random class)
  108. instance_name=$1
  109. iteration_count=$2
  110. base_uri=$(_base_uri $1)
  111. cls_list_file=$(fetch_all_classes $1)
  112. if [ -z "$(cat $cls_list_file)" ]
  113. then
  114. echo "Failed to fetch class list for instance $1. Abording..." >&2
  115. exit
  116. fi
  117. if [ "$iteration_count" -le "0" ]
  118. then
  119. return
  120. fi
  121. for i in $(seq $iteration_count)
  122. do
  123. cls=$(shuf -n1 $cls_list_file)
  124. echo "${base_uri}$(uri_create $cls) POST $(curl_opt_create_$cls)"
  125. done
  126. rm -v $cls_list_file >&2
  127. }
  128. mass_link_edit() {
  129. #mass linking & edition scenarion
  130. #$1 is instance name
  131. #$2 is iteration count
  132. instance_name=$1
  133. iteration_count=$2
  134. base_uri=$(_base_uri $1)
  135. cls_list_file=$(fetch_all_classes $1)
  136. for cls in $(cat $cls_list_file)
  137. do
  138. case $cls in
  139. Person)
  140. person_ids=$(fetch_all_ids $1 Person)
  141. section_ids=$(fetch_all_ids $1 Section)
  142. subsection_ids=$(fetch_all_ids $1 Subsection)
  143. text_ids=$($cmktemp)
  144. cat $section_ids $subsection_ids | shuf > $text_ids
  145. for i in $(seq $iteration_count)
  146. do
  147. cur_id=$(shuf -n1 $person_ids)
  148. alias_count=$(shuf -i1-5 -n1)
  149. ltext_count=$(shuf -i1-5 -n1)
  150. alias_param=$(head -n $(expr $alias_count \* $i) $person_ids| tail -n$alias_count|tr -s "\n" "," | sed 's/,$//')
  151. txt_param=$(head -n $(expr $ltext_count \* $i) $text_ids | tail -n$ltext_count|tr -s "\n" "," | sed 's/,$//')
  152. echo "$base_uri/admin/update?classname=$cls&lodel_id=$cur_id POST $(curl_opt_create_$cls $alias_param $txt_param)&uid=$cur_id"
  153. done
  154. rm -v $text_ids $person_ids $section_ids $subsection_ids >&2
  155. ;;
  156. Collection)
  157. collections_ids=$(fetch_all_ids $1 Collection)
  158. publication_ids=$(fetch_all_ids $1 Publication)
  159. for i in $(seq $iteration_count)
  160. do
  161. cur_id=$(shuf -n1 $collections_ids)
  162. publications_count=$(shuf -i1-5 -n1)
  163. publication_param=$(head -n $(expr $publications_count \* $i) $publication_ids| tail -n$publications_count|tr -s "\n" ",")
  164. echo "$base_uri/admin/update?classname=$cls&lodel_id=$cur_id POST $(curl_opt_create_$cls $publication_param)&uid=$cur_id"
  165. done
  166. rm -v $collections_ids $publication_ids >&2
  167. ;;
  168. Publication)
  169. publication_ids=$(fetch_all_ids $1 Publication)
  170. collection_ids=$(fetch_all_ids $1 Collection)
  171. for i in $(seq $iteration_count)
  172. do
  173. cur_id=$(shuf -n1 $publication_ids)
  174. collections_count=$(shuf -i1-5 -n1)
  175. collection_param=$(head -n $(expr $collections_count \* $i) $collection_ids| tail -n$collections_count|tr -s "\n" ",")
  176. echo "$base_uri/admin.update?classname=$cls&lodel_id=$cur_id POST $(curl_opt_create_$cls $collection_param)&uid=$cur_id"
  177. done
  178. rm -v $publication_ids $collection_ids >&2
  179. ;;
  180. Section)
  181. section_ids=$(fetch_all_ids $1 Section)
  182. child_ids=$(fetch_all_ids $1 Subsection)
  183. person_ids=$(fetch_all_ids $1 Person)
  184. for i in $(seq $iteration_count)
  185. do
  186. cur_id=$(shuf -n1 $section_ids)
  187. child_count=$(shuf -i1-5 -n1)
  188. person_count=$(shuf -i1-5 -n1)
  189. child_param=$(head -n $(expr $child_count \* $i) $child_ids| tail -n$child_count|tr -s "\n" ",")
  190. person_param=$(head -n $(expr $person_count \* $i) $person_ids| tail -n$person_count|tr -s "\n" ",")
  191. echo "$base_uri/admin/update?classname=$cls&lodel_id=$cur_id POST $(curl_opt_create_$cls $child_param $person_param)&uid=$cur_id"
  192. done
  193. rm -v $section_ids $child_ids $person_ids >&2
  194. ;;
  195. Subsection)
  196. subsection_ids=$(fetch_all_ids $1 Subsection)
  197. section_ids=$(fetch_all_ids $1 Section)
  198. persons_ids=$(fetch_all_ids $1 Person)
  199. parent_ids=$($cmktemp)
  200. cat $section_ids $subsection_ids | shuf > $parent_ids
  201. child_ids=$subsection_ids
  202. for i in $(seq $iteration_count)
  203. do
  204. cur_id=$(shuf -n1 $subsection_ids)
  205. child_count=$(shuf -i1-5 -n1)
  206. parent_count=$(shuf -i1-5 -n1)
  207. person_count=$(shuf -i1-5 -n1)
  208. child_param=$(head -n $(expr $child_count \* $i) $child_ids| tail -n$child_count|tr -s "\n" ",")
  209. parent_param=$(head -n $(expr $parent_count \* $i) $parent_ids| tail -n$parent_count|tr -s "\n" ",")
  210. person_param=$(head -n $(expr $person_count \* $i) $persons_ids| tail -n$person_count|tr -s "\n" ",")
  211. echo "$base_uri/admin/update?classname=$cls&lodel_id=$cur_id POST $(curl_opt_create_$cls $child_param $person_param $parent_param)&uid=$cur_id"
  212. done
  213. rm -v $subsection_ids $parent_ids $section_ids $persons_ids >&2
  214. ;;
  215. *)
  216. ;;
  217. esac
  218. done
  219. rm -v $cls_list_file >&2
  220. }
  221. mass_deletion() {
  222. #mass deletion scenario
  223. #$1 is instance name
  224. #$2 number of deletion per classes !
  225. instance_name=$1
  226. iteration_count=$2
  227. base_uri=$(_base_uri $1)
  228. cls_list_file=$(fetch_all_classes $1)
  229. for cls in $(cat $cls_list_file)
  230. do
  231. id_list_file=$(fetch_all_ids $1 $cls)
  232. if [ "$iteration_count" -gt "$(wc -l $id_list_file | cut -d " " -f1)" ]
  233. then
  234. max_iter=$(wc -l $id_list_file | cut -d " " -f1)
  235. else
  236. max_iter="$iteration_count"
  237. fi
  238. for i in $(seq $max_iter)
  239. do
  240. id=$(tail -n $i $id_list_file | head -n1)
  241. echo "${base_uri}/admin/delete?classname=$cls&lodel_id=$id"
  242. done
  243. rm -v $id_list_file >&2
  244. done
  245. rm -v $cls_list_file >&2
  246. }
  247. fetch_all_classes() {
  248. #$1 is intance name
  249. cls_list_file=$($cmktemp)
  250. $curl_raw "$(_base_uri $1)/list_classes" | grep -v Abstract |sed -nE 's/^ *<li> +<a href="show_class([^"]+)".*$/\1/p'|cut -d"=" -f2 > $cls_list_file
  251. if [ -z "$(cat $cls_list_file)" ]
  252. then
  253. echo "Unable to fetch class list for $1" >&2
  254. echo "Request was : $curl_raw '$(_base_uri $1)/list_classes'" >&2
  255. rm $cls_list_file >&2
  256. exit 1
  257. fi
  258. echo $cls_list_file
  259. }
  260. fetch_all_ids() {
  261. # Fetch all ids of a class in an instance and shuffle them
  262. instance_name=$1
  263. classname=$2
  264. idfile=$($cmktemp)
  265. $curl_raw "$(_base_uri $1)/show_class?classname=$2" | sed -nE 's/^.*<li><a href="[^=]+=[^=]+=([0-9]+)".*$/\1/p' |shuf > $idfile
  266. echo $idfile
  267. }
  268. uri_create() {
  269. clsname=$1
  270. echo -n "/admin/create?classname=$1"
  271. }
  272. curl_opt_create_Person() {
  273. #$1 is alias id
  274. #$2 is linked_texts id (comma separated)
  275. echo "field_input_lastname=$(rnd_str_len 10 20)&field_input_firstname=$(rnd_str_len 10 20)&field_input_alias=$1&field_input_linked_texts=$2&classname=Person"
  276. }
  277. curl_opt_create_User() {
  278. echo "field_input_lastname=$(rnd_str_len 10 20)&field_input_firstname=$(rnd_str_len 10 20)&field_input_password=$(rnd_str 50)&field_input_login=$(rnd_str_len 5 20)&classname=User"
  279. }
  280. curl_opt_create_Collection() {
  281. #$1 is publications id (comma separated)
  282. echo "field_input_title=$(rnd_str_len 20 50)&field_input_publications=$1&classname=Collection"
  283. }
  284. curl_opt_create_Publication() {
  285. #$1 collections id comma separated
  286. echo "field_input_collection=$1&classname=Publication"
  287. }
  288. curl_opt_create_Section() {
  289. #$1 childs id (comma separated)
  290. #$2 linked_persons id (comma separated)
  291. echo "field_input_title=$(rnd_str_len 20 50)&field_input_subtitle=$(rnd_str_len 20 50)&field_input_childs=$1&field_input_linked_persons=$2&classname=Section"
  292. }
  293. curl_opt_create_Subsection() {
  294. #$1 childs id (comma separated)
  295. #$2 linked_persons id (comma separated)
  296. #$3 parants id (comma separated)
  297. echo "field_input_title=$(rnd_str_len 20 50)&field_input_subtitle=$(rnd_str_len 20 50)&field_input_childs=$1&field_input_linked_persons=$2&field_input_parent=$3&classname=Subsection"
  298. }
  299. run_bg_with_param() {
  300. #$1 is the function name to run
  301. #$2 is the instance_list filename
  302. #other parameters are given to the function
  303. fun=$1
  304. instance_list=$2
  305. shift;shift
  306. pidlist=$($cmktemp)
  307. for iname in $(cat $instance_list)
  308. do
  309. $fun $iname $@ &
  310. echo $! >> $pidlist
  311. sleep 1
  312. done
  313. for pid in $(cat $pidlist)
  314. do
  315. wait $pid
  316. done
  317. rm -v $pidlist >&2
  318. }
  319. get_queries_with_params() {
  320. #$1 is the function name to run
  321. #$2 is the instance_list filename
  322. #other parameters are given to the function
  323. fun=$1
  324. instance_list=$2
  325. shift;shift
  326. counter=0
  327. for iname in $(cat $instance_list| sort)
  328. do
  329. echo "Running $fun $iname $@" >&2
  330. beg=$(date "+%s")
  331. $fun $iname $@
  332. tsecs=$(expr $(date "+%s") - $beg)
  333. left=$(expr $(cat $instance_list |wc -l) - $counter)
  334. counter=$(expr $counter + 1)
  335. tleft=$(expr $left \* $tsecs)
  336. percent_done=$(echo "2k ${counter}.0 100.0 * $(cat $instance_list |wc -l).0 2k/ f" | dc)
  337. echo -e "Done in ${tsecs}s\t$fun ${percent_done}% done ~$tleft secs" >&2
  338. done | shuf
  339. }
  340. [ "$n_create" -gt 0 ] && get_queries_with_params "mass_creation" $instance_list $n_create
  341. [ "$n_edit" -gt 0 ] && get_queries_with_params "mass_link_edit" $instance_list $n_edit
  342. [ "$n_delete" -gt 0 ] && get_queries_with_params "mass_deletion" $instance_list $n_delete