|
探究GP系統運作,現將個人對GP系統中的各種Shell的理解解析如下,供參考!
所有說明都依 Topprod GP Server 正式區為例
loadx:資料上傳---------------------------------------------------------------------------
A、loadx 路徑
/u1/topprod/tiptop/ora/bin
B、loadx Shell解析
#!/bin/kshif [ ! $# -eq 3 ] ; then#判斷loadx Shell腳本後面的位置參數個數是否為3個,即loadx後面要帶3個參數echo "Usage: loadx database txtfile \"insert statement\""echo "Ex : loadx ds zx_file.txt \"insert into zx_file(zx01,zx02)\""exitfiFGLRUN=${FGLRUN:=fglrun}; export FGLRUN#判斷環境變數FGLRUN是否曾今有賦值過,如果有則帶入之前的值,如果空則用fglrun$FGLRUN `dirname $0`/../42m/loadx.42m $1 $2 "$3"#執行`dirname $0`/../42m/路徑下的4GL程式loadx#`dirname $0`表示取位置參數$0即loadx Shell的路徑,loadx Shell腳本所在的路徑/u1/topprod/tiptop/ora/bin 再看看/u1/topprod/tiptop/ora/bin路徑下 loadx.4gl的代碼
DATABASE dsMAINDEFINE l_db VARCHAR(40)DEFINE l_file VARCHAR(40)DEFINE l_sql VARCHAR(60)LET l_db=ARG_VAL(1) #l_db=ARG_VAL(1)=$1 資料庫名稱 LET l_file=ARG_VAL(2) #l_file=ARG_VAL(2)=$2 檔案名LET l_sql=ARG_VAL(3) #l_sql=ARG_VAL(3)=$3 sql語句DISPLAY "LOAD FROM ",l_file," ",l_sqlDATABASE l_db #連資料庫l_db=ARG_VAL(1)=$1LOAD FROM l_file l_sql #利用4GL內置命令 LOAD指令END MAIN -------------------- over, loadx資料上傳Shell指令完畢!
unloadx:資料下載--------------------------------------------------------------------------
A、unloadx 路徑
/u1/topprod/tiptop/ora/bin
B、unloadx Shell解析
#!/bin/kshif [ ! $# -eq 3 ] ; thenecho "Usage: unloadx database txtfile \"select statement\""echo "Ex : unloadx ds zx_file.txt \"select * from zx_file where zx01 matches 't*'\""exitfiFGLRUN=${FGLRUN:=fglrun}; export FGLRUN$FGLRUN `dirname $0`/../42m/unloadx.42m $1 $2 "$3" 再看看/u1/topprod/tiptop/ora/bin路徑下 unloadx.4gl的代碼
DATABASE dsMAINDEFINE l_db VARCHAR(40)DEFINE l_file VARCHAR(40)DEFINE l_sql VARCHAR(600)LET l_db=ARG_VAL(1)LET l_file=ARG_VAL(2)LET l_sql=ARG_VAL(3)DISPLAY "UNLOAD TO ",l_file," ",l_sqlDATABASE l_dbUNLOAD TO l_file l_sqlEND MAIN ------------------- over, unloadx資料下载Shell指令完畢!
createdb:創建Tiptop GP用戶資料庫--------------------------------------------------
A、createdb 路徑
/u1/topprod/tiptop/ora/bin
B、createdb Shell解析
#!/bin/ksh#BUG-520096#Modify: 06/12/18 FUN-6C0038 By alexstar#Modify: 06/12/18 FUN-730039 By alexstar#Modify: 07/10/16 EXT-7A0101 By alexstar#Modify: 08/02/25 EXT-820095 By alexstar Catch last line to avoid repetition#Modify: 08/02/25 FUN-820063 By alexstar AP DB separate environment#Modify: 08/04/14 EXT-840070 By JOEY:temptables#Modify: 09/01/15 CHI-910026 By alexstar If db creatation failed,remove the setting of FGLPROFILE#Modify: 09/02/03 CHI-920013 By alexstar #Modify: 09/03/02 MOD-930001 By alexstar "i" can't be used on certain AIX version#Modify: 10/09/20 FUN-A90053 By yuge77 fixed fglprofile replace original contents#Modify: 10/12/29 TQC-AC0394 By ELLE default PASSWORD_LIFE_TIME unlimited#Modify: 10/12/30 FUN-AC0100 By ELLE exp direct=N#Modify: 11/03/14 TQC-B30118 By ELLE $ans1 -> "$ans1"#TQC-AC0394fun_chkdbtype(){echo "select version from PRODUCT_COMPONENT_VERSION where upper(product) like '%ORACLE%';" > select.sqlsqlplus system/systdb32@$ORACLE_SID < select.sql > version.listdbtype=`cat version.list|grep '11.2'|wc -l`if [ "$dbtype" = 0 ] ; thenecho "10g"elseecho "11g"echo "$ans2"|dbprofile.sh $1firm -rf select.sqlrm -rf version.list}#CHI-910026---start---fun_chkdb() #定義函數fun_chkdb檢查創建資料庫是否成功,操作$FGLPROFILE文件#$FGLPROFILE文件中記錄了GP所有的用戶資料庫信息及連接oracle的指定驅動,4GL中的ds與schema指令都將查這個文件進行資料庫的連接{echo "exit"|sqlplus $1/"$ans1"@$ORACLE_SID|grep -iq errorif [ "$?" -eq 0 ];then#如果創建用戶不成功,則刪除之前$FGLPROFILE文件有加過的該用戶的一些信息ex $FGLPROFILE <<%%#開啟行編輯器編輯$FGLPROFILE文件,即/u1/genero.run/etc/fglprofile.prodg/$1\.source =/.,.+5 d#全文搜索匹配 $1.source = 模式的字段,刪除從該字段所在的行及下麵的5行,因為每新增一個用戶$FGLPROFILE文件中都將新增5行信息及1行空白#ex命令選項 g/:全文,/後面跟者RegExp正則運算式、\:轉義符、d:刪除操作、.:表示當前行、+5:參照的行數+5行w #保存修改過的/u1/genero.run/etc/fglprofile.prod文件q #退出ex行編輯器%%echo "******************************************"echo "Error: [ DB: $1 creation failed! ]"echo "******************************************"exitelseecho "\n=========================================="echo "DB: [ $1 creation succesfully! ]"echo "=========================================="exitfi}#CHI-910026---end---if [ "$1" = "" ] ; then#如果createdb沒有傳任何位置參數則提示如下38-46的信息echo "Usage: $0 dbname [1|2|3|4]"#$0表示createdb的路徑及名稱GP中值為/u1/toptest/tiptop/ora/bin/createdbecho "===========For ds schema has not been altered yet============"echo "Ex1 : $0 ds1 1 -----> create database only"echo "============================================================="echo "===============For ds schema had been altered================"echo "Ex2 : $0 ds2 2 -----> create table schema(from ds user)"echo "Ex3 : $0 ds3 3 -----> create table schema with ds demo data"echo "Ex4 : $0 ds4 4 -----> create table schema with data(non-ds)"echo "============================================================="exitfians1=t #搞個局部變數ansl初始值=tans1a=f #再搞個局部變數ansla初始值=fwhile [ $ans1 != $ans1a ] #只要ansl的值與ansla值不相等即前後兩次密碼不一樣就一直迴圈做dodoecho "\n accept the password of user $1 : \c"#\n先換行再顯示信息accept the password of user $1 :,信息顯示完\c不換行stty -echo #關閉終端回顯,即用戶輸入新建資料庫密碼終端上看不到輸入的密碼信息read ans1 #等待用戶輸入新建資料庫密碼,將輸入的密碼保留在變數ansl中stty echo #打開終端回顯,即用戶在終端上輸入信息又可以即時看到信息了echo "\n Re-enter the password of user $1 : \c"#同上,只是再一次要求用戶輸入密碼#一下處理要求用戶輸入ds資料庫的密碼stty -echoread ans1astty echodoneecho "\n"ans3=tans3a=fwhile [ $ans3 != $ans3a ]doecho "\n accept the password of user ds : \c"stty -echoread ans3stty echoecho "\n Re-enter the password of user ds : \c"stty -echoread ans3astty echodoneecho "\n"#一下處理要求用戶輸入管理員system帳號的密碼ans2=tans2a=fwhile [ $ans2 != $ans2a ]doecho "\n accept the password of user system : \c"stty -echoread ans2stty echoecho "\n Re-enter the password of user system : \c"stty -echoread ans2astty echodoneecho "\n"#一下處理同上要求用戶輸入管理員sys帳號的密碼ans4=tans4a=fwhile [ $ans4 != $ans4a ]doecho "\n accept the password of user sys : \c"stty -echoread ans4stty echoecho "\n Re-enter the password of user sys : \c"stty -echoread ans4astty echodoneecho "\n"#下麵處理從all_users視圖中找是否已經存在預創建的用戶名稱的資料庫db=`echo $1|tr 'a-z' 'A-Z'`#將$1新建資料庫的名字重定向給tr,tr將所有的小寫字符換成大寫字符ex - <<%% #啟動ex行編輯器aselect 'database:',username from all_users where username='$db';#將該條語句保存至createdb.sql文件中.w! createdb.sqlq%%sqlplus system/$ans2@$ORACLE_SID < createdb.sql > createdb.tmp2#登錄system用戶 執行createdb.sql 將執行結果寫入到createdb.tmp2中db2=`grep 'database:' createdb.tmp2|cut -d ' ' -f2`#在createdb.tmp2中查找datebase:字段,將結果重定向給cut,cut取出用戶名rm -f createdb.tmp2 createdb.sql#暴力刪除createdb.sql與createdb.tmp2文件if [ "$db" = "$db2" ]#如果$db的值=$db2的值,表示資料庫中已經存在該用戶,無法創建,提示如下信息thenecho " "echo "\n\033[7m $db database already exists \033[0m" echo " "exitfians=$2 #搞一變數,賦值為createdb Shell的位置參數$2if [ "$2" = "" ] #如果$2為空,表示創建新的資料庫,則提示如下信息做交互thenecho ''echo "Create new TIPTOP database: $1"echo ''echo "===========For ds schema has not been altered yet============"echo '(1) Create DB User Only'echo ''echo "=============For ds schema had been altered=================="echo '(2) Create DB User with all table schema and basic parameter data'echo ''echo '(3) Create DB User with all table schema and DS demo data'echo ''echo '(4) Create DB User(From NON-DS USER) with all table schema and data'echo ''echo 'Please input your choice.........[ 1/2/3/4 0:Quit ]: \c'read ans #用戶如入選項0/1/2/3/4 賦值給變數ansif [ "$ans" = "0" ] #用戶選擇0,則退出creaedb shell腳本thenexitfifi#FUN-730039 "=" -> " = "#CHI-910026---start--- change a to i,remove null column,add space #MOD-930001 i to a#FUN-A90053 add a empty line below 'a'#一下處理:創建一臨時文件createdb.pro,寫入下麵的內容,待會這些內容要寫入FGLPROFILE文件中ex - <<%%adbi.database.${1}.source = "$ORACLE_SID" ## DVM320#ORACLE服務,即正式區/測試區/標准區dbi.database.${1}.username = "$1" ## DVM320#新創建的用戶資料庫名稱dbi.database.${1}.password = "$ans1" ## DVM320#新創建的用戶資料庫密碼dbi.database.${1}.schema = "$1" ## DVM320#新創建的用戶資料庫表空間dbi.database.${1}.ora.prefetch.rows = 1 # Add by Raymon 02/02/01.w! createdb.proq%%#一下處理:將之前創建好的createdb.pro內容寫入$FGLPROFILE即/u1/genero.run/etc/fglprofile.prod文件中#FUN-A90053-----start#ex $FGLPROFILE <<%%#g/$1\.source =/.,.+5 d#g/ds2\.source#-1#r createdb.pro#w#q#%%#rm -f createdb.proex $FGLPROFILE <<%%$ #跳到$FGLPROFILE文件的最後一行r createdb.pro #將之前創建好的createdb.pro內容寫入$FGLPROFILE文件末尾wq%%rm -f createdb.pro #做完后暴力刪除臨時文件createdb.pro#FUN-A90053-----end#CHI-910026---end---dbpass=`grep ds.password $FGLPROFILE|cut -d \" -f2|sed 's/ //g'|tail -1` #EXT-7A0101 #EXT-820095case $ans in #case分支處理用戶之前選擇的1/2/3/41) cd $TOP/ora/work #如果選擇1,則跳到/u1/topprod/tiptop/ora/work路徑下#EXT-7A0101 ---start---ex - <<%% #一下處理:查詢資料庫的DEFAULT_TEMP_TABLESPACE屬性的值aselect property_value from database_propertieswhere property_name like ('DEFAULT_TEMP_TABLESPACE');.w! /tmp/temp_sql.txtq%%#sqlplus ds/${dbpass}@$ORACLE_SID < /tmp/temp_sql.txt > /tmp/tmp.txt 2>&1 #FUN-820063sqlplus system/$ans2@$ORACLE_SID < /tmp/temp_sql.txt > /tmp/tmp.txt 2>&1 #FUN-820063#2>&1 表示如果有錯誤錯誤輸出到標注輸出即終端上ex -s /tmp/tmp.txt <<%% #處理/tmp/tmp.txt將結果寫入/tmp/tmp_value.txt文件中1/--1,. d2.,$ d.w! /tmp/tmp_value.txtq%%temp_value=`head /tmp/tmp_value.txt` #將/tmp/tmp_value.txt首行信息賦給temp_value變數\rm /tmp/temp_sql.txt #+-* 0 /*刪除/tmp/temp_sql.txt、/tmp/tmp.txt、/tmp/tmp_value.txt 這3個臨時文件\rm /tmp/tmp.txt\rm /tmp/tmp_value.txt#EXT-7A0101 ---end---#一下處理:創建臨時文件createdb.sql,其中寫入下麵ex編輯器處理的內容ex - <<%%aconn system/$ans2@$ORACLE_SID;create user $1 identified by "$ans1" #創建用戶與密碼 default tablespace dbs1 #默認表空間為dbs1-主要存放TIPTOP用戶和數據,數據文件dbs1-01.dbf ... temporary tablespace $temp_value; #臨時表空間為TEMP - 數據文件temp01.dbf... grant create session,create table to $1; #為創建的用戶授權 grant resource to $1; grant create synonym to $1; conn sys/$ans4@$ORACLE_SID as sysdba;grant select on sys.v_\$session to $1;.w! createdb.sqlq%%sqlplus system/$ans2@$ORACLE_SID < createdb.sql rm -f createdb.sql #SQL語句執行完后刪除掉臨時文件createdb.sqlfun_chkdbtype $1 # TQC-AC0394 #調用fun_chkdb函數,檢查是否SQL執行成功及對fglprofile.prod文件的操作fun_chkdb $1 #CHI-910026;; #case 1)結束 相當與C中的break語句#以上過程可知道選擇1,則只是創建了一個空的用戶,沒有任何表及數據資料導入2) cd $TOP/ora/work #如果選擇2,則跳到/u1/topprod/tiptop/ora/work路徑下#up_priv ds/$ans3#exp ds/$ans3@$ORACLE_SID owner=ds rows=n file=ds.dmp direct=y log=exp_ds.log #FUN-6C0038exp ds/$ans3@$ORACLE_SID owner=ds rows=n file=ds.dmp log=exp_ds.log #FUN-AC0100#oracle的exp命令匯出資料# 用戶/ 密碼 @服務即測/正式區 預匯出的用戶 是否匯出數據 匯出文件名 是否將數據直接讀入匯出緩存中 記錄匯出過程中的文件名#EXT-7A0101 ---start---#一下處理過程類似 同選擇條件1過程類似,創建用戶并授權ex - <<%%aselect property_value from database_propertieswhere property_name like ('DEFAULT_TEMP_TABLESPACE');.w! /tmp/temp_sql.txtq%%#sqlplus ds/${dbpass}@$ORACLE_SID < /tmp/temp_sql.txt > /tmp/tmp.txt 2>&1 #FUN-820063sqlplus system/$ans2@$ORACLE_SID < /tmp/temp_sql.txt > /tmp/tmp.txt 2>&1 #CHI-920013 ex -s /tmp/tmp.txt <<%%1/--1,. d2.,$ d.w! /tmp/tmp_value.txtq%%temp_value=`head /tmp/tmp_value.txt`\rm /tmp/temp_sql.txt\rm /tmp/tmp.txt\rm /tmp/tmp_value.txt#EXT-7A0101 ---end---ex - <<%%aconn system/$ans2@$ORACLE_SID;create user $1 identified by "$ans1" default tablespace dbs1 temporary tablespace $temp_value; grant create session,create table to $1; grant resource to $1; grant create synonym to $1; conn sys/$ans4@$ORACLE_SID as sysdba;grant select on sys.v_\$session to $1;exit; .w! createdb.sqlq%%sqlplus system/$ans2@$ORACLE_SID < createdb.sql imp system/$ans2@$ORACLE_SID fromuser=ds touser=$1 file=ds.dmp log=imp_$1.log #FUN-6C0038#將從ds用戶匯出的表結構匯入至新創建的用戶資料庫中sqlplus $1/$ans1@$ORACLE_SID < synonym.sql #執行/u1/topprod/tiptop/ora/work/synonym.sql,該SQL主要創建TIPTOP中的同義詞 rm -f createdb.sql ds.dmp #暴力刪除臨時文件createdb.sql及數據文件ds.dmp#### Load tiptop system parameters #####clear #終端清屏#一下for迴圈:將ds資料庫這些表中的數據導入到新創建用戶相應的表中for f in aaz_file apz_file aza_file azi_file bxz_file bgz_file ccz_file cpa_file cpr_file faa_file nmz_file oaz_file ooz_file qcz_file rmz_file sma_file mmd_file{ex - <<%%a #loadpara.sql文件新增下麵行insert的內容insert into ${f} select * from ds.${f};.w! loadpara.sqlq%%echo 'Load data ... 'echo $fsqlplus $1/$ans1@$ORACLE_SID <loadpara.sql#切換oracle連接用戶為剛才新創建的用戶并用該用戶執行loadpara.sqlrm loadpara.sql}fun_chkdbtype $1 # TQC-AC0394fun_chkdb $1 #CHI-910026;;#以上過程可知道選擇2,會創建一個用戶,且該用戶含TIPTOP表結構但是沒有任何數據資料除了一些參數資料3) cd $TOP/ora/work #如果選擇3,則跳到/u1/topprod/tiptop/ora/work路徑下#up_priv ds/$ans3#exp ds/$ans3@$ORACLE_SID owner=ds file=ds.dmp direct=y log=exp_ds.log #FUN-6C0038exp ds/$ans3@$ORACLE_SID owner=ds file=ds.dmp log=exp_ds.log #FUN-AC0100#此處exp沒有選項rows=n,則默認rows=y。所以會匯出所有的數據資料#EXT-7A0101 ---start---#一下過程完全與選擇選項2相同,不再做解釋ex - <<%%aselect property_value from database_propertieswhere property_name like ('DEFAULT_TEMP_TABLESPACE');.w! /tmp/temp_sql.txtq%%#sqlplus ds/${dbpass}@$ORACLE_SID < /tmp/temp_sql.txt > /tmp/tmp.txt 2>&1 #FUN-820063sqlplus system/$ans2@$ORACLE_SID < /tmp/temp_sql.txt > /tmp/tmp.txt 2>&1 #CHI-920013 ex -s /tmp/tmp.txt <<%%1/--1,. d2.,$ d.w! /tmp/tmp_value.txtq%%temp_value=`head /tmp/tmp_value.txt`\rm /tmp/temp_sql.txt\rm /tmp/tmp.txt\rm /tmp/tmp_value.txt#EXT-7A0101 ---end---ex - <<%%aconn system/$ans2@$ORACLE_SID;create user $1 identified by "$ans1" default tablespace dbs1 temporary tablespace $temp_value; grant create session,create table to $1; grant resource to $1; grant create synonym to $1; conn sys/$ans4@$ORACLE_SID as sysdba;grant select on sys.v_\$session to $1;exit; .w! createdb.sqlq%%sqlplus system/$ans2@$ORACLE_SID < createdb.sql imp system/$ans2@$ORACLE_SID fromuser=ds touser=$1 file=ds.dmp log=imp_$1.log #FUN-6C0038 sqlplus $1/$ans1@$ORACLE_SID < synonym.sql #synonym.sql文件 是一個創建同義詞的SQL文件rm -f createdb.sql ds.dmp#同義詞創建語法:先刪除原表 drop 表A, 再創建同義詞表A create synonym 表A for 資料庫名.表Afun_chkdbtype $1 # TQC-AC0394fun_chkdb $1 #CHI-910026;;#以上過程可知道選擇3,會創建一個用戶,且該用戶含TIPTOP表結構並且導入了ds資料庫中的數據4) echo "\n 請輸入欲複製的資料庫(NON-DS USER): \c"#如果選擇4,則顯示這行的信息:表示要創建的新的用戶為複製一個非ds資料庫read source #從終端等待用戶輸入欲複製的資料庫名稱db=`echo $source|tr 'a-z' 'A-Z'` #將用戶終端輸入的source值全部變為大寫,轉化后的結果值賦給變數dbex - <<%% #啟動ex行編輯器將sql語句寫入createdb.sql文件中的首行aselect 'database:',username from all_users where username='$db';.w! createdb.sqlq%%#system用戶連接oracle執行createdb.sql中的sql將結果重定向至created.temp2文件中sqlplus system/$ans2@$ORACLE_SID < createdb.sql > createdb.tmp2 db2=`grep 'database:' createdb.tmp2|cut -d ' ' -f2`#查oracle中是否有欲要拿來做數據複製的資料庫名稱rm -f createdb.tmp2 createdb.sqlif [ "$db" != "$db2" ] #如果沒有該資料庫則提下麵的信息于終端thenecho " "echo "\n\033[7m $db database is not exists \033[0m" echo " "exit #且退出createdb這個shell腳本程式fi#一下處理:如果欲拿來做複製的資料庫存在則要求用戶輸入該資料庫的密碼保存至ans5變數中ans5=t ans5a=fwhile [ $ans5 != $ans5a ]doecho "\n accept the password of user $source : \c"stty -echoread ans5stty echoecho "\n Re-enter the password of user $source : \c"stty -echoread ans5astty echodoneecho "\n"#下麵的處理邏輯:與選擇選項3過程完全一樣,只是oracle exp匯出資料數據時改變2個選項而已,owner=${source} file=${source}.dmp#owner即欲匯出資料的來源改成了用戶自己輸入的資料庫名稱,選項3則默認的是dscd $TOP/ora/work#up_priv $source/$ans5#exp $source/$ans5@$ORACLE_SID owner=${source} file=${source}.dmp direct=y log=exp_${source}.log #FUN-6C0038exp $source/$ans5@$ORACLE_SID owner=${source} file=${source}.dmp log=exp_${source}.log #FUN-AC0100#EXT-7A0101 ---start---ex - <<%%aselect property_value from database_propertieswhere property_name like ('DEFAULT_TEMP_TABLESPACE');.w! /tmp/temp_sql.txtq%%#sqlplus ds/${dbpass}@$ORACLE_SID < /tmp/temp_sql.txt > /tmp/tmp.txt 2>&1 #FUN-820063sqlplus system/$ans2@$ORACLE_SID < /tmp/temp_sql.txt > /tmp/tmp.txt 2>&1 #CHI-920013 ex -s /tmp/tmp.txt <<%%1/--1,. d2.,$ d.w! /tmp/tmp_value.txtq%%temp_value=`head /tmp/tmp_value.txt`\rm /tmp/temp_sql.txt\rm /tmp/tmp.txt\rm /tmp/tmp_value.txt#EXT-7A0101 ---end---ex - <<%%aconn system/$ans2@$ORACLE_SID;create user $1 identified by "$ans1" default tablespace dbs1 temporary tablespace $temp_value; grant create session,create table to $1; grant resource to $1; grant create synonym to $1; conn sys/$ans4@$ORACLE_SID as sysdba;grant select on sys.v_\$session to $1;exit; .w! createdb.sqlq%%sqlplus system/$ans2@$ORACLE_SID < createdb.sql imp system/$ans2@$ORACLE_SID fromuser=$source touser=$1 file=${source}.dmp log=imp_$1.log #FUN-6C0038rm -f createdb.sql ${source}.dmpfun_chkdbtype $1 # TQC-AC0394fun_chkdb $1 #CHI-910026;;#以上過程可知道選擇4,會創建一個用戶,且該用戶含user決定來源的欲複製的資料庫中的數據*) #選擇的選項不是1、2、3、4則提示如下信息,退出createdb Shell腳本程式echo "No such choice!" #CHI-910026fun_chkdb $1 #CHI-910026exit;;esac ---- over,createdb創建tiptopGP資料庫Shell指令完畢!
與GP資料庫操作有關的指令loadx unloadx createdb就介紹到這裡!
轉載請注明CSDN李藝輝博客專欄http://blog.csdn.net/yihuiworld |
|