├── .gitignore ├── LICENSE ├── README.md ├── src └── inspector │ ├── README.md │ └── standalone.cc └── tools ├── README.md ├── drawInspects.sh └── runInspector.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | build 31 | *.jpeg 32 | *.jpg 33 | *.eps 34 | *.inspect 35 | *.plot 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 FlashSQL-SKKU 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ForestDB-Analyzer 2 | - To analyze the IO characteristics of ForetDB, FDB analyzer will distinguish what pages are being written. 3 | 4 | # Requirments 5 | - Latest version of `ForestDB @Couchbase/ForestDB` 6 | 7 | # HOW TO USE 8 | Please refer to `README.md` files of each utilities inside src/util_name folder 9 | -------------------------------------------------------------------------------- /src/inspector/README.md: -------------------------------------------------------------------------------- 1 | # ForestDB Block Inspector 2 | Block inspector analyzes a type of a block. 3 | Inputs are outputs of `blktrace` 4 | 5 | ## HOW TO BUILD 6 | 7 | Only works on Linux platforms. There is an dependency on forestdb source. 8 | You may need to modify the codes of inspector related to your forestdb version. 9 | 10 | - Use preferable c++ compiler to compile sourcode. 11 | - For standalone fdb-inspector, compile `standalone.cc` file with header file directory options. 12 | (e.g. g++ -I/home/me/forestdb/include) 13 | - Header file directories are /your/fdb/home/include, 14 | /your/fdb/home/src, /your/fdb/home/utils 15 | 16 | ## HOW TO RUN 17 | Let's assume that binary file is `fdb-analyzer` 18 | 19 | Run the binary with blktrace before running your forestdb benchmark on background. 20 | `blktrace` and `fdb-analyzer` should be run as a root previlege. 21 | ``` 22 | $> sudo btrace /dev/sdc 2>&1 | 23 | sudo ./fdb-analyzer -d /dev/sdc -m 0 -b 4096 &> trace & 24 | $> ./runBenchamrk.sh 25 | ``` 26 | 27 | After the benchmark finished, kill `blktrace` or `fdb-analyzer`. 28 | ``` 29 | $> sudo killall -15 btrace blktrace 30 | $> sudo killall fdb-analyzer 31 | ``` 32 | 33 | ### Options 34 | - `d`: Specify your device name (You must always use this option) 35 | - `b`: Specify your forestdb's block size in bytes (default: 4096) 36 | - `m`: Specify what metadata your forestdb uses (default: 0) 37 | - `0`: BLK_MARKER is used 38 | - `1`: document metadata structure is used (since MAGIC_02 version of forestdb) 39 | 40 | ## RESULTS 41 | `fdb-analyzer` prints below informations. 42 | - Output of `blktrace` itself 43 | - For write requests, what forestdb block types are written 44 | - `DBHEADER`, `BNODE`, `DOC`, `SUPERBLOCK (SB)` 45 | - `Unknown` for the others 46 | 47 | At the end of the benchmark, `fdb-analyzer` prints 48 | - Total block count for each forestdb block types 49 | - Ratio of each forestdb block types 50 | -------------------------------------------------------------------------------- /src/inspector/standalone.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Standalone ForestDB block inspector 3 | * - Latest forestdb source codes are needed. 4 | * 5 | * written by Gihwan oh 6 | */ 7 | 8 | /** 9 | * "src/common.h" header file of forestdb contains types of block marker 10 | * and docblk_meta structure. 11 | */ 12 | 13 | #define __GNU_SOURCE 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace std; 26 | 27 | #define SUCCESS 0x00 28 | #define UNKNOWN_ERROR 0x01 29 | #define UNKNOWN_ARG 0x02 30 | #define DEV_NOT_FOUND 0x04 31 | 32 | void print_usage(char* name) { 33 | fprintf(stderr, "Usage: %s options\n", name); 34 | fprintf(stderr, "-b blocksize: block size of target forestdb (default: 4096)\n"); 35 | fprintf(stderr, "-m meta: 0 - use BLK_MARKER, 1 - use DOCBLK_META\n"); 36 | fprintf(stderr, " (default: 0)\n"); 37 | fprintf(stderr, "-d devname: Device name which contains target forestdb\n"); 38 | fprintf(stderr, " (/dev/sdxx must be used)\n"); 39 | } 40 | 41 | /** 42 | * Use printf("%" PRIu64 "\n", blocksize); to print uint64_t variables. 43 | */ 44 | struct config { 45 | int marker; 46 | uint64_t blocksize; 47 | char* devname; 48 | }; 49 | 50 | struct config global_config; 51 | 52 | void init_config(void) { 53 | global_config.marker = 0; 54 | global_config.blocksize = 0; 55 | global_config.devname = (char*)malloc(sizeof(char) * 512); 56 | } 57 | 58 | void destroy_config(void) { 59 | free(global_config.devname); 60 | } 61 | 62 | int verify_config(void) { 63 | if (0 >= strlen(global_config.devname)) { 64 | return DEV_NOT_FOUND; 65 | } 66 | 67 | if (0 >= global_config.blocksize) { 68 | global_config.blocksize = 4096; 69 | } 70 | 71 | if (0 != global_config.marker && 1 != global_config.marker) { 72 | global_config.marker = 0; 73 | } 74 | 75 | /* print options */ 76 | fprintf(stderr, "====== Configurations ======\n"); 77 | fprintf(stderr, "Blocksize: %" PRIu64 " bytes\n", global_config.blocksize); 78 | fprintf(stderr, "Device name: %s\n", global_config.devname); 79 | fprintf(stderr, "Marker: %d\n", global_config.marker); 80 | fprintf(stderr, "============================\n"); 81 | return SUCCESS; 82 | } 83 | 84 | /** 85 | * extern int optind, opterr, optopt; 86 | * extern char *optarg; 87 | */ 88 | int parse_opt(int argc, char* argv[]) { 89 | const char *opt = "b:d:m:"; 90 | char option; 91 | 92 | optind = 1; 93 | while ( -1 != (option = getopt(argc, argv, opt)) ) { 94 | switch (option) { 95 | case 'b' : 96 | global_config.blocksize = atoll(optarg); 97 | break; 98 | case 'd' : 99 | strcpy(global_config.devname, optarg); 100 | break; 101 | case 'm' : 102 | global_config.marker = atoi(optarg); 103 | break; 104 | default: 105 | return UNKNOWN_ARG; 106 | }; // switch (option) 107 | }; // while ( getopt() ) 108 | return SUCCESS; 109 | } 110 | 111 | /** 112 | * Block marker of forestdb 113 | * (commit version is 671823e363615f37439f3ddaaeb730018a3db0a4) 114 | */ 115 | #define BLK_MARKER_BNODE (0xff) 116 | #define BLK_MARKER_DBHEADER (0xee) 117 | #define BLK_MARKER_DOC (0xdd) 118 | #define BLK_MARKER_SB (0xcc) // superblock 119 | #define BLK_MARKER_SIZE (1) 120 | 121 | enum fdb_blk_types { 122 | DOC = 0, /* document */ 123 | BNODE, /* index node */ 124 | DBHEADER, /* db header */ 125 | SB, /* superblock */ 126 | BLK_TYPE_END 127 | }; 128 | 129 | char fdb_blk_names[BLK_TYPE_END + 2][16] = { 130 | "Document", 131 | "Index", 132 | "Header", 133 | "Superblock", 134 | "Not FDB", 135 | "Total Writes" 136 | }; 137 | 138 | uint64_t type_cnt[BLK_TYPE_END + 2]; //this includes total count 139 | 140 | 141 | void print_count(void) { 142 | uint64_t total = type_cnt[BLK_TYPE_END+1]; 143 | uint64_t fdb_total = 144 | total - type_cnt[BLK_TYPE_END]; 145 | 146 | fprintf(stderr, "\n======== Statistics =========\n"); 147 | for (int i = 0 ;i < BLK_TYPE_END + 2;i++) { 148 | fprintf(stderr, "TYPE %s: %" PRIu64 149 | " pages, %.4Lf%% of FDB, %.4Lf%% of Total\n", 150 | fdb_blk_names[i], type_cnt[i], 151 | (long double)type_cnt[i] / fdb_total * 100, 152 | (long double)type_cnt[i] / total * 100); 153 | } 154 | fprintf(stderr, "=============================\n"); 155 | } 156 | 157 | int do_inspect(string& appname) { 158 | int dev; 159 | int blocksize = global_config.blocksize; 160 | int metasize = 161 | (global_config.marker == 0? 162 | BLK_MARKER_SIZE: 1); 163 | int idx = 0; 164 | uint64_t offset, bytes; 165 | char *block; 166 | char tline[128]; 167 | unsigned char blk_type; 168 | string line, output; 169 | string *lists; 170 | char scanbuf[1024]; 171 | 172 | 173 | if ( 0 >= (dev = open(global_config.devname, O_RDONLY | O_LARGEFILE))) { 174 | fprintf(stderr, "Errno: %d, %s\n", errno, strerror(errno)); 175 | return DEV_NOT_FOUND; 176 | } // open device 177 | 178 | memset(type_cnt, 0, sizeof(type_cnt)); 179 | lists = new string[16]; 180 | block = (char*)malloc(sizeof(char) * blocksize); 181 | 182 | while ( fgets(tline, sizeof(tline)-1, stdin) ) { 183 | line = string(tline); 184 | 185 | istringstream is(line); /* prepare tokenizing */ 186 | idx = 0; 187 | 188 | /* get tokens */ 189 | while ( idx < 16 && is >> lists[idx++] ); 190 | 191 | if ( idx < 14 && idx > 10 && lists[10].substr(1, appname.size()) == appname ) { 192 | /* Skip for the I/O issued by this inspector */ 193 | continue; 194 | } 195 | if ( idx > 10 && 196 | (lists[5][0] == 'D' && (lists[6][0] == 'W' || lists[6][0] == 'R')) || 197 | (lists[5][0] == 'I' && lists[6][0] == 'F')) { 198 | /* get offset and num sectors */ 199 | offset = atoll(lists[7].c_str()) * 512; 200 | bytes = atoll(lists[9].c_str()) * 512; 201 | 202 | lists[9] = string("8"); 203 | /* inspect a block */ 204 | while ( blocksize <= bytes && 0 < bytes ) { 205 | pread(dev, block, blocksize, offset); 206 | 207 | if (global_config.marker) { 208 | } else { 209 | blk_type = *(block + blocksize - metasize); 210 | } // if marker 211 | 212 | switch (blk_type) { 213 | case BLK_MARKER_BNODE: 214 | output = string("BNODE"); 215 | type_cnt[BNODE]++; 216 | break; 217 | case BLK_MARKER_DBHEADER: 218 | output = string("DBHEADER"); 219 | type_cnt[DBHEADER]++; 220 | break; 221 | case BLK_MARKER_DOC: 222 | output = string("DOC"); 223 | type_cnt[DOC]++; 224 | break; 225 | case BLK_MARKER_SB: 226 | output = string("SB"); 227 | type_cnt[SB]++; 228 | break; 229 | default: 230 | output = string("NOT_FDB"); 231 | type_cnt[BLK_TYPE_END]++; 232 | break; 233 | }; //switch blk_type 234 | type_cnt[BLK_TYPE_END+1]++; 235 | 236 | //new offset for separation 237 | sprintf(scanbuf, "%"PRIu64, offset); 238 | lists[7] = string(scanbuf); 239 | 240 | // Next offset 241 | offset += blocksize; 242 | bytes -= blocksize; 243 | for (int k = 0 ;k < idx;k++) { 244 | if (lists[k] == string("00") ) { 245 | continue; 246 | } 247 | cout << lists[k] << " "; 248 | } // print 249 | cout << output << endl; ; 250 | 251 | /* print only once for FWFS */ 252 | if (lists[6][0] == 'F') { 253 | break; 254 | } // FWFS 255 | } // while (blocksize <= bytes && 0 < bytes) 256 | } else { 257 | cout << line; 258 | } // if D W 259 | } //while ( fgets() ) 260 | 261 | print_count(); 262 | 263 | delete[] lists; 264 | free(block); 265 | return SUCCESS; 266 | } 267 | void handle_signal(int num) { 268 | printf("== signal %d caught ==\n", num); 269 | //print_count(); 270 | } 271 | void set_signal(void) { 272 | signal(SIGINT, handle_signal); 273 | signal(SIGTERM, handle_signal); 274 | } 275 | 276 | int main(int argc, char *argv[]) { 277 | int rv; 278 | string appname; 279 | 280 | init_config(); 281 | 282 | if( SUCCESS != (rv = parse_opt(argc, argv)) ) { 283 | print_usage(argv[0]); 284 | goto exit; 285 | } //parse options 286 | 287 | if( SUCCESS != (rv = verify_config()) ) { 288 | print_usage(argv[0]); 289 | goto exit; 290 | } // verify configs 291 | 292 | set_signal(); 293 | 294 | appname = string(basename(argv[0])); 295 | 296 | rv = do_inspect(appname); 297 | 298 | exit: 299 | destroy_config(); 300 | return rv; 301 | } 302 | -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # Tools for Inspector 2 | For running and finalize the `forestdb inspector`, this tools would be useful to 3 | __summarize and understand__ the result of the inspecteor. 4 | All of the scripts are based on `python, shell script` and some of them are 5 | implemented using `C/C++` language. 6 | 7 | ## Run inspector easily 8 | 9 | 10 | ## Draw results of inpector 11 | `drawInspects.sh` script draws the results of `forestdb inspector` using `GNUplot`. 12 | -------------------------------------------------------------------------------- /tools/drawInspects.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # usage of this script 4 | # print usage of this script 5 | usage() { 6 | echo " 7 | USAGE: $0 [option lists] 8 | 9 | Options: 10 | --set-xcol | --set-ycol [num] 11 | Column number of the input file to be used as X or Y axis 12 | 13 | -w | --set-width [num] 14 | Width of the output image for JPEG type 15 | 16 | -l | --set-height {num] 17 | Height of the output image for JPEG type 18 | 19 | --set-x-start | --set-y-start [num] 20 | Start point for xrange or yrange 21 | 22 | --set-x-end | --set-y-end [num] 23 | End point for xrang eor yrange 24 | 25 | --set-output-dir [path] 26 | Set output image's directory 27 | 28 | -o | --set-output-file [path] 29 | Set output image's name or full path 30 | 31 | -t | --set-image-type [jpeg | eps | ps] 32 | Set output image's type 33 | 34 | --set-xlabel | --set-ylabel [name] 35 | Set name of the x or y label 36 | 37 | --set-separator [separator] 38 | Set separator to be used as parsing the input file 39 | 40 | --set-point-size [num] 41 | Set point size of the image 42 | 43 | -f | --file [path] 44 | Set file path for input file 45 | 46 | -h | --help 47 | Show this usage messages 48 | " 49 | } 50 | 51 | # comments for variables 52 | : ' 53 | FDB_INSPECT_HOME= # Home directory where the fdb inspector is installed 54 | FDB_INSPECT_RESULT= # Result files of fdb inspector 55 | PLOT_IMAGE_DIR= # OUTPUT directory for plotted image 56 | PLOT_X_START= # begin of xrange 57 | PLOT_X_END= # end of xrange 58 | PLOT_Y_START= # begin of yrange 59 | PLOT_Y_END= # end of yrange 60 | PLOT_SIZE_WIDTH= # width of output image 61 | PLOT_SIZE_HEIGHT= # height of output image 62 | PLOT_IMAGE_TYPE= # image type of output image 63 | PLOT_GRAPH_TYPE= # graph type of output image 64 | PLOT_XLABLE= # xlabel of image 65 | PLOT_YLABEL= # ylabel of image 66 | ' # comments for variables 67 | 68 | 69 | RETURN_ON_SUCCESS=0 70 | RETURN_ON_ERROR=1 71 | RETURN_ON_INVALID_ARGS=2 72 | RETURN_ON_COMMAND_NOT_FOUND=3 73 | 74 | : ' 75 | Additional functions for plotting the graph using gnuplot. 76 | From here it would be hard to read. Refactoring would be in a year. 77 | ' 78 | 79 | # Set variables for this script 80 | set_default() { 81 | PLOT_SIZE_WIDTH="1960"; 82 | PLOT_SIZE_HEIGHT="1024"; 83 | PLOT_SIZE_POINT="0.2"; 84 | PLOT_SEPARATOR=" "; 85 | PLOT_IMAGE_TYPE="jpeg"; 86 | PLOT_XLABEL="Timestamp (second)"; 87 | PLOT_YLABEL="Logical Sector Number"; 88 | FDB_INSPECT_RESULT="./result.inspect"; 89 | PLOT_Y_START=""; 90 | PLOT_Y_END=""; 91 | PLOT_X_END=""; 92 | PLOT_X_START=""; 93 | PLOT_X_COLUMN=4; 94 | PLOT_Y_COLUMN=8; 95 | } 96 | 97 | args_sanity_check() { 98 | echo "Arguments sanity check" 99 | return ${RETURN_ON_SUCCESS} 100 | } 101 | 102 | set_plot_style() { 103 | 104 | # set image options 105 | DEFAULT_SCRIPT=" 106 | set xlabel \"${PLOT_XLABEL}\"; 107 | set ylabel \"${PLOT_YLABEL}\"; 108 | set xrange [${PLOT_X_START}:${PLOT_X_END}]; 109 | set yrange [${PLOT_Y_START}:${PLOT_Y_END}]; 110 | set pointsize ${PLOT_SIZE_POINT}; 111 | set datafile separator \"${PLOT_SEPARATOR}\"; 112 | set output \"${PLOT_OUTPUT_FILE}.${PLOT_IMAGE_TYPE}\"; " 113 | 114 | case "${PLOT_IMAGE_TYPE}" in 115 | "eps" ) 116 | PLOT_TYPE="set terminal postscript eps;" 117 | ;; 118 | "ps" ) 119 | PLOT_TYPE="set terminal postscript enhanced color;" 120 | ;; 121 | "jpg"|"jpeg") # default type is jpeg 122 | PLOT_TYPE="set te jpeg giant size ${PLOT_SIZE_WIDTH},${PLOT_SIZE_HEIGHT};" 123 | ;; 124 | *) 125 | echo "Set your image type" 126 | exit 3 127 | ;; 128 | esac 129 | 130 | # set style options 131 | PLOT_STYLE="" # initialize 132 | for i in `seq 10` 133 | do 134 | 135 | PLOT_STYLE="${PLOT_STYLE} 136 | set style line ${i} lc ${i}; " 137 | 138 | done 139 | PLOT_STYLE="${PLOT_TYPE} 140 | ${DEFAULT_SCRIPT} 141 | ${PLOT_STYLE} 142 | " 143 | } 144 | 145 | 146 | # create plot script for GNUPLOT 147 | set_plot_script() { 148 | PLOT_VARIABLES=("NOT_FDB" "DOC" "BNODE" "DBHEADER" "SB" ) 149 | PLOT_SCRIPT="plot " # initialize 150 | 151 | for i in `seq ${#PLOT_VARIABLES[@]}` 152 | do 153 | ptype=${PLOT_VARIABLES[$((i-1))]}; 154 | if [ ${i} -ne 1 ] 155 | then 156 | PLOT_SCRIPT="${PLOT_SCRIPT}, "; 157 | fi 158 | PLOT_SCRIPT="${PLOT_SCRIPT} \"< grep ${ptype} ${FDB_INSPECT_RESULT}\" u ${PLOT_X_COLUMN}:${PLOT_Y_COLUMN} ls ${i} ti \"${ptype}\"" 159 | done 160 | PLOT_SCRIPT="${PLOT_SCRIPT};" 161 | } 162 | 163 | plot() { 164 | echo "Plot basic type graph" ; 165 | SCRIPT_FILE=./inspect.plot 166 | 167 | set_plot_script; # set gnuplot script 168 | set_plot_style; # set line or point style 169 | 170 | echo "${PLOT_STYLE} ${PLOT_SCRIPT}" | tee ${SCRIPT_FILE} 171 | gnuplot ${SCRIPT_FILE} 172 | 173 | return $?; # return gnuplot's return value 174 | } 175 | 176 | 177 | set_args() { 178 | echo "Set arguments" ; 179 | set_default; 180 | 181 | while getopts ":-:o:f:t:hw:l:" opt $@ 182 | do 183 | echo "OPTION is ${opt}${OPTARG}" 184 | case ${opt} in 185 | -) 186 | IFS='=' read -ra token <<< "${OPTARG}" 187 | if [ ${#token[@]} -gt 1 ] 188 | then 189 | option=${token[0]} 190 | ARGS=${token[1]} 191 | else 192 | shift $((OPTIND-1)) 193 | option=${OPTARG} 194 | ARGS=${1} 195 | OPTIND=2 196 | fi 197 | case ${option} in 198 | set-xcol) 199 | PLOT_X_COLUMN=${ARGS} 200 | ;; 201 | set-ycol) 202 | PLOT_Y_COLUMN=${ARGS} 203 | ;; 204 | set-width) 205 | PLOT_SIZE_WIDTH=${ARGS} 206 | ;; 207 | set-height) 208 | PLOT_SIZE_HEIGHT=${ARGS} 209 | ;; 210 | set-x-start) 211 | PLOT_X_START=${ARGS} 212 | ;; 213 | set-y-start) 214 | PLOT_Y_START=${ARGS} 215 | ;; 216 | set-x-end) 217 | PLOT_X_END=${ARGS} 218 | ;; 219 | set-y-end) 220 | PLOT_Y_END=${ARGS} 221 | ;; 222 | set-output-dir) 223 | PLOT_IMAGE_DIR=${ARGS} 224 | ;; 225 | set-image-type) 226 | PLOT_IMAGE_TYPE=${ARGS} 227 | ;; 228 | set-xlabel) 229 | PLOT_XLABEL=${ARGS} 230 | ;; 231 | set-ylabel) 232 | PLOT_YLABEL=${ARGS} 233 | ;; 234 | set-separator) 235 | PLOT_SEPARATOR=${ARGS} 236 | ;; 237 | set-point-size) 238 | PLOT_SIZE_POINT=${ARGS} 239 | ;; 240 | set-output-file) 241 | PLOT_OUTPUT_FILE=${ARGS} 242 | ;; 243 | file) 244 | FDB_INSPECT_RESULT=${ARGS} 245 | ;; 246 | help|*) 247 | echo "You used ${opt} ${OPTARG}" 248 | usage 249 | exit 250 | ;; 251 | esac 252 | ;; 253 | f) 254 | FDB_INSPECT_RESULT="${OPTARG}" 255 | ;; 256 | w) 257 | PLOT_SIZE_WIDTH=${OPTARG} 258 | ;; 259 | l) 260 | PLOT_SIZE_HEIGHT=${OPTARG} 261 | ;; 262 | o) 263 | PLOT_OUTPUT_FILE=${OPTARG} 264 | ;; 265 | t) 266 | PLOT_IMAGE_TYPE=${OPTARG} 267 | ;; 268 | "?") 269 | if [ -n ${OPTARG} ] 270 | then 271 | echo "You used ${opt} ${OPTARG}" 272 | usage 273 | exit 1; 274 | else 275 | echo "You used ${opt} ${OPTARG}" 276 | fi 277 | ;; 278 | h|*) 279 | echo "You used ${opt} ${OPTARG}" 280 | usage 281 | exit 1; 282 | ;; 283 | esac 284 | done 285 | 286 | if [ -z "${PLOT_OUTPUT_FILE}" ] 287 | then 288 | PLOT_OUTPUT_FILE=$(basename ${FDB_INSPECT_RESULT}) 289 | fi 290 | 291 | args_sanity_check; 292 | return $? 293 | } 294 | 295 | # starting point of this script 296 | main() { 297 | set_args $@; 298 | ret_val=$?; 299 | 300 | if [ ${ret_val} -ne ${RETURN_ON_SUCCESS} ] || ! [ -f ${FDB_INSPECT_RESULT} ] 301 | then 302 | usage; 303 | return ${ret_val} 304 | fi 305 | 306 | plot; 307 | 308 | return $? 309 | } 310 | 311 | # call main() function instead of processing in a nature 312 | main $@ 313 | 314 | echo "return val is $?" 315 | 316 | 317 | 318 | -------------------------------------------------------------------------------- /tools/runInspector.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script uses GNU library utility like enhanced `getopt`. 4 | # Only tested on `Ubuntu 15.04 and 14.04` with `bash`. 5 | # If you are running on differen platform, you may need to 6 | # modify this script. Otherwise, you will face errors. 7 | 8 | 9 | usage() { 10 | cnt=$((cnt+1)) 11 | main 12 | } 13 | 14 | dev="" # device to inspect 15 | 16 | set_opts() { 17 | echo a 18 | } 19 | 20 | main() { 21 | set_opts $@ 22 | } 23 | 24 | main $* 25 | 26 | # get basename: $(basename "$0") 27 | --------------------------------------------------------------------------------