ssdb-cli display request time

ssdb-cli display request time

import thread, re, time, socket;
import getopt, shlex;

try{
	import readline;
}catch(Exception e){
}

function welcome(){
	print ('ssdb (cli) - ssdb command line tool.');
	print ('Copyright (c) 2012 ideawu.com');
	print ('');
	print "'h' or 'help' for help, 'q' to quit.";
	print ('');
}
welcome();

function show_command_help(){
	print '';
	print '* ssdb-cli commands *';
	print '    set a 1';
	print '    get a';
	print '    scan key_start key_end limit';
	print '        scan a z 10';
	print '    zset n a 1';
	print '    zget n a';
	print '    zscan setname key score_start score_end limit';
	print '        zscan n a 1 3 10';
	print '';
}

function usage(){
	print '';
	print 'Usage:';
	print '    ssdb-cli [-h HOST -p PORT]';
	print '';
	print 'Options:';
	print '    -h 127.0.0.1';
	print '        ssdb server hostname/ip address';
	print '    -p 8888';
	print '        ssdb server port';
	print '';
	print 'Examples:';
	print '    ssdb-cli';
	print '    ssdb-cli -p 8888';
	print '    ssdb-cli -h 127.0.0.1 -p 8888';
}

function repr_data(str){
	ret = repr(str);
	if(len(ret) > 0){
		if(ret[0] == '\''){
			ret = ret.replace("\\'", "'");
			ret = ret[1 .. -1];
		}else if(ret[0] == '"'){
			ret = ret.replace('\\"', '"');
			ret = ret[1 .. -1];
		}else{
		}
	}
	return ret;
}

default_opts = {
	'-h' : '127.0.0.1',
	'-p' : '8888',
};

opt_err = false;
try{
	opts, args = getopt.getopt(sys.argv[1 .. ], 'h:p:');
	opts = dict(opts);
}catch(getopt.GetoptError e){
	opts = {};
	opt_err = true;
}
foreach(default_opts as k=>v){
	if(!opts.has_key(k)){
		opts[k] = v;
	}
}

if(opt_err){
	usage();
	sys.exit(0);
}

host = opts['-h'];
port = int(opts['-p']);

sys.path.append('./api/python');
sys.path.append('../api/python');
import SSDB.SSDB;

try{
	link = new SSDB(host, port);
}catch(socket.error e){
	print 'Connection error: ', str(e);
	sys.exit(0);
}

while(true){
	line = '';
	c = sprintf('ssdb %s:%s> ', host, str(port));
	line = raw_input(c);
	if(line == ''){
		continue;
	}
	line = line.strip();
	if(line == 'q' || line == 'quit'){
		print 'bye.';
		break;
	}
	if(line == 'h' || line == 'help'){
		show_command_help();
		continue;
	}

	try{
		ps = shlex.split(line);
	}catch(Exception e){
		print 'error: ', e;
		continue;
	}
	if(len(ps) == 0){
		continue;
	}
	cmd = ps[0];
	args = ps[1 .. ];

	retry = 0;
	max_retry = 5;
	import datetime;
	stime = datetime.datetime.now();
	while(true){
		stime = datetime.datetime.now();
		resp = link.request(cmd, args);
		etime = datetime.datetime.now();
		if(resp.code == 'disconnected'){
			link.close();
			time.sleep(retry);
			retry ++;
			if(retry > max_retry){
				print 'cannot connect to server, give up...';
				break;
			}
			printf('[%d/%d] reconnecting to server... ', retry, max_retry);
			try{
				link = new SSDB(host, port);
				print 'done.';
			}catch(socket.error e){
				print 'Connect error: ', str(e);
				continue;
			}
			print '';
		}else{
			break;
		}
	}

	ts = etime - stime;
	time_consume = ts.seconds + ts.microseconds/1000000.;
	if(!resp.ok()){
		print 'error: ' + resp.code;
		printf('(%.3f sec)\n', time_consume);
	}else{
		switch(cmd){
			case 'get':
			case 'zget':
			case 'hget':
			case 'incr':
			case 'decr':
			case 'zincr':
			case 'zdecr':
			case 'hincr':
			case 'hdecr':
			case 'hsize':
			case 'zsize':
				print repr_data(resp.data);
				printf('(%.3f sec)\n', time_consume);
				break;
			case 'set':
			case 'zset':
			case 'hset':
			case 'del':
			case 'zdel':
			case 'hdel':
				print resp.code;
				printf('(%.3f sec)\n', time_consume);
				break;
			case 'scan':
			case 'rscan':
			case 'hscan':
			case 'hrscan':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 22);
				foreach(resp.data['index'] as k){
					printf('  %-15s : %s\n', repr_data(k), repr_data(resp.data['items'][k]));
				}
				printf('%d result(s) (%.3f sec)\n', len(resp.data['index']), time_consume);
				break;
			case 'zscan':
			case 'zrscan':
				printf('%-15s %s\n', 'key', 'score');
				print ('-' * 22);
				foreach(resp.data['index'] as k){
					score = resp.data['items'][k];
					printf('  %-15s: %s\n', repr_data(repr_data(k)), score);
				}
				printf('%d result(s) (%.3f sec)\n', len(resp.data['index']), time_consume);
				break;
			case 'keys':
			case 'zkeys':
			case 'hkeys':
				printf('  %15s\n', 'key');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				printf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume);
				break;
			case 'hlist':
			case 'zlist':
				printf('  %15s\n', 'name');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				printf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume);
				break;
			case 'multi_get':
			case 'multi_hget':
			case 'multi_zget':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 22);
				foreach(resp.data as k=>v){
					printf('  %-15s : %s\n', repr_data(k), repr_data(v));
				}
				printf('%d result(s) (%.3f sec)\n', len(resp.data['index']), time_consume);
				break;
			default:
				print repr_data(resp.code), repr_data(resp.data);
				printf('(%.3f sec)\n', time_consume);
				break;
		}
	}
}

import thread, re, time, socket;
import getopt, shlex;

try{
	import readline;
}catch(Exception e){
}

function welcome(){
	print ('ssdb (cli) - ssdb command line tool.');
	print ('Copyright (c) 2012 ideawu.com');
	print ('');
	print "'h' or 'help' for help, 'q' to quit.";
	print ('');
}
welcome();

function show_command_help(){
	print '';
	print '* ssdb-cli commands *';
	print '    set a 1';
	print '    get a';
	print '    scan key_start key_end limit';
	print '        scan a z 10';
	print '    zset n a 1';
	print '    zget n a';
	print '    zscan setname key score_start score_end limit';
	print '        zscan n a 1 3 10';
	print '';
}

function usage(){
	print '';
	print 'Usage:';
	print '    ssdb-cli [-h HOST -p PORT]';
	print '';
	print 'Options:';
	print '    -h 127.0.0.1';
	print '        ssdb server hostname/ip address';
	print '    -p 8888';
	print '        ssdb server port';
	print '';
	print 'Examples:';
	print '    ssdb-cli';
	print '    ssdb-cli -p 8888';
	print '    ssdb-cli -h 127.0.0.1 -p 8888';
}

function repr_data(str){
	ret = repr(str);
	if(len(ret) > 0){
		if(ret[0] == '\''){
			ret = ret.replace("\\'", "'");
			ret = ret[1 .. -1];
		}else if(ret[0] == '"'){
			ret = ret.replace('\\"', '"');
			ret = ret[1 .. -1];
		}else{
		}
	}
	return ret;
}

default_opts = {
	'-h' : '127.0.0.1',
	'-p' : '8888',
};

opt_err = false;
try{
	opts, args = getopt.getopt(sys.argv[1 .. ], 'h:p:');
	opts = dict(opts);
}catch(getopt.GetoptError e){
	opts = {};
	opt_err = true;
}
foreach(default_opts as k=>v){
	if(!opts.has_key(k)){
		opts[k] = v;
	}
}

if(opt_err){
	usage();
	sys.exit(0);
}

host = opts['-h'];
port = int(opts['-p']);

sys.path.append('../api/python');
import SSDB.SSDB;

try{
	link = new SSDB(host, port);
}catch(socket.error e){
	print 'Connection error: ', str(e);
	sys.exit(0);
}

while(true){
	line = '';
	c = sprintf('ssdb %s:%s> ', host, str(port));
	line = raw_input(c);
	if(line == ''){
		continue;
	}
	line = line.strip();
	if(line == 'q' || line == 'quit'){
		print 'bye.';
		break;
	}
	if(line == 'h' || line == 'help'){
		show_command_help();
		continue;
	}

	try{
		ps = shlex.split(line);
	}catch(Exception e){
		print 'error: ', e;
		continue;
	}
	if(len(ps) == 0){
		continue;
	}
	cmd = ps[0];
	args = ps[1 .. ];

	retry = 0;
	max_retry = 5;
	while(true){
		resp = link.request(cmd, args);
		if(resp.code == 'disconnected'){
			link.close();
			time.sleep(retry);
			retry ++;
			if(retry > max_retry){
				print 'cannot connect to server, give up...';
				break;
			}
			printf('[%d/%d] reconnecting to server... ', retry, max_retry);
			try{
				link = new SSDB(host, port);
				print 'done.';
			}catch(socket.error e){
				print 'Connect error: ', str(e);
				continue;
			}
			print '';
		}else{
			break;
		}
	}

	if(!resp.ok()){
		print 'error: ' + resp.code;
	}else{
		switch(cmd){
			case 'get':
			case 'zget':
			case 'hget':
			case 'incr':
			case 'decr':
			case 'zincr':
			case 'zdecr':
			case 'hincr':
			case 'hdecr':
			case 'hsize':
			case 'zsize':
				print repr_data(resp.data);
				break;
			case 'set':
			case 'zset':
			case 'hset':
			case 'del':
			case 'zdel':
			case 'hdel':
				print resp.code;
				break;
			case 'scan':
			case 'rscan':
			case 'hscan':
			case 'hrscan':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 22);
				foreach(resp.data['index'] as k){
					printf('  %-15s : %s\n', repr_data(k), repr_data(resp.data['items'][k]));
				}
				printf('%d result(s)\n', len(resp.data['index']));
				break;
			case 'zscan':
			case 'zrscan':
				printf('%-15s %s\n', 'key', 'score');
				print ('-' * 22);
				foreach(resp.data['index'] as k){
					score = resp.data['items'][k];
					printf('  %-15s: %s\n', repr_data(repr_data(k)), score);
				}
				printf('%d result(s)\n', len(resp.data['index']));
				break;
			case 'keys':
			case 'zkeys':
			case 'hkeys':
				printf('  %15s\n', 'key');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				printf('%d result(s)\n', len(resp.data));
				break;
			case 'hlist':
			case 'zlist':
				printf('  %15s\n', 'name');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				printf('%d result(s)\n', len(resp.data));
				break;
			case 'multi_get':
			case 'multi_hget':
			case 'multi_zget':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 22);
				foreach(resp.data as k=>v){
					printf('  %-15s : %s\n', repr_data(k), repr_data(v));
				}
				printf('%d result(s)\n', len(resp.data));
				break;
			default:
				print repr_data(resp.code), repr_data(resp.data);
				break;
		}
	}
}


fix importer bug

fix importer bug

function run(link, filename){
	if(!os.path.exists(filename)){
		print 'Error: ' + filename + ' not exists!';
		return;
	}
	total_size = os.path.getsize(filename);
	if(total_size == 0){
		total_size = 1;
	}

	progress = 0;
	read_size = 0;
	fp = open(filename, 'r');
	lineno = 0;
	foreach(fp as line){
		lineno ++;
		read_size += len(line);
		progress_2 = int(float(read_size)/total_size * 100);
		if(progress_2 - progress >= 5 || read_size == total_size){
			progress = progress_2;
			printf("%2d%%\n", progress_2);
		}

		ps = line.strip('\n').split('\t');
		if(len(ps) < 2){
			print 'Error: bad format at line ' + str(lineno) + ', abort!';
			return;
		}
		cmd = ps[0].lower();
		foreach(ps as k=>v){
			ps[k] = str(v).decode('string-escape');
		}

		link.request(cmd, ps[ 1 ..]);
	}
	print 'done.';
}

function run(link, filename){
	if(!os.path.exists(filename)){
		print 'Error: ' + filename + ' not exists!';
		return;
	}
	total_size = os.path.getsize(filename);
	if(total_size == 0){
		total_size = 1;
	}

	progress = 0;
	read_size = 0;
	fp = open(filename, 'r');
	lineno = 0;
	foreach(fp as line){
		lineno ++;
		read_size += len(line);
		progress_2 = int(float(read_size)/total_size * 100);
		if(progress_2 - progress >= 5 || read_size == total_size){
			progress = progress_2;
			printf("%2d%%\n", progress_2);
		}

		ps = line.strip().split('\t');
		if(len(ps) < 2){
			print 'Error: bad format at line ' + str(lineno) + ', abort!';
			return;
		}
		cmd = ps[0].lower();
		foreach(ps as k=>v){
			ps[k] = str(v).decode('string-escape');
		}

		link.request(cmd, ps[ 1 ..]);
	}
	print 'done.';
}


Cleanup. Removing unused code

Cleanup. Removing unused code

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TEMP100.
      *AUTHOR. deps81@gmail.com

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  SENSOR-REC.
           05 SENSOR-ID.
               10 SENSOR-PROT  PIC  X.
               10 SENSOR-NUM   PIC  9(3).
           05 SENSOR-TEMP      PIC +999.9.
           05 SENSOR-HUMID     PIC  999.
           05 SENSOR-TIMESTAMP PIC  9(10).

       01  TMP-TEMP    PIC S999V9.

       01  CHECK-PROTOCOL PIC X(50).
       01  CHECK-MODEL    PIC X(50).
       01  CHECK-ID       PIC 999.
       01  CHECK-TYPE     PIC 9.

       01  TELLSTICK-SENSOR-VARS.
           05 TSV-PROTOCOL     PIC X(50).
           05 TSV-MODEL        PIC X(50).
           05 TSV-DEVICE-ID    PIC 999.
           05 TSV-DATA-TYPE    PIC 9.
           05 TSV-SENSOR-VALUE PIC X(50).
           05 TSV-SENSOR-LEN   PIC 99 VALUE 50.
           05 TSV-TIMESTAMP    USAGE BINARY-LONG UNSIGNED.
           05 TSV-RETURN       PIC S9(4).

       01  TELLSTICK-SENSOR-ITER.
           05 TSI-PROTOCOL     PIC X(50).
           05 TSI-MODEL        PIC X(50).
           05 TSI-ID           USAGE BINARY-CHAR UNSIGNED.
           05 TSI-DATATYPES    USAGE BINARY-LONG UNSIGNED.
           05 TSI-RETURN       USAGE BINARY-CHAR.

       PROCEDURE DIVISION.
           DISPLAY "CONNECTING TO TELLSTICK..."
           CALL "telldusInit".
           DISPLAY "CONNECTING TO DATABASE..."
           CALL "SQLinit".

           PERFORM 200-START-ITERATION.

           CALL "telldusClose".
           CALL "SQLclose".

           STOP RUN.

       200-START-ITERATION.
           DISPLAY "ITERATING SENSORS..."
           MOVE ZERO TO TSI-RETURN.
           PERFORM 201-ITERATE-SENSORS
             UNTIL TSI-RETURN IS NOT EQUAL 0.

           DISPLAY "DONE".

       201-ITERATE-SENSORS.
           MOVE SPACES TO TELLSTICK-SENSOR-ITER.
           CALL "getSensors" USING
               BY REFERENCE TSI-PROTOCOL BY VALUE LENGTH OF TSI-PROTOCOL
               BY REFERENCE TSI-MODEL BY VALUE LENGTH OF TSI-MODEL
               BY REFERENCE TSI-ID
               BY REFERENCE TSI-DATATYPES
               RETURNING TSI-RETURN.

           IF TSI-RETURN IS EQUAL TO 0
      D      DISPLAY "* GOT SENSOR " TSI-ID
             MOVE TSI-PROTOCOL TO CHECK-PROTOCOL
             MOVE TSI-MODEL TO CHECK-MODEL
             MOVE TSI-ID TO CHECK-ID

             MOVE 1 TO CHECK-TYPE
             PERFORM 210-POLLSENSOR

             MOVE TSV-TIMESTAMP TO SENSOR-TIMESTAMP
             MOVE TSI-PROTOCOL(1:1) TO SENSOR-PROT
             MOVE CHECK-ID TO SENSOR-NUM
             MOVE TSV-SENSOR-VALUE TO TMP-TEMP
             MOVE TMP-TEMP TO SENSOR-TEMP

             MOVE 2 TO CHECK-TYPE
             PERFORM 210-POLLSENSOR

             MOVE TSV-SENSOR-VALUE TO SENSOR-HUMID

      D      DISPLAY SENSOR-REC
             PERFORM 400-DATABASE-INSERT
           END-IF.

       210-POLLSENSOR.
      *    Setup call
           MOVE CHECK-ID TO TSV-DEVICE-ID.
           MOVE CHECK-PROTOCOL TO TSV-PROTOCOL.
           MOVE CHECK-MODEL TO TSV-MODEL.
           MOVE SPACE TO TSV-SENSOR-VALUE.
      *    1 = TEMPERATURE, 2 = HUMIDITY
           MOVE CHECK-TYPE TO TSV-DATA-TYPE.

      D    DISPLAY "* POLLING SENSOR '" FUNCTION TRIM(CHECK-PROTOCOL)
      D            "', '" FUNCTION TRIM (CHECK-MODEL)
      D            "', " CHECK-ID " AS " CHECK-TYPE.

           CALL "getSensorValue" USING
               BY REFERENCE TSV-PROTOCOL
               BY REFERENCE TSV-MODEL
               BY VALUE TSV-DEVICE-ID
               BY VALUE TSV-DATA-TYPE
               BY REFERENCE TSV-SENSOR-VALUE
               BY VALUE TSV-SENSOR-LEN
               BY REFERENCE TSV-TIMESTAMP
               RETURNING TSV-RETURN.

       400-DATABASE-INSERT.
           CALL "insertTemperature" USING
              BY REFERENCE SENSOR-ID
              BY REFERENCE SENSOR-TEMP
              BY VALUE SENSOR-HUMID
              BY VALUE SENSOR-TIMESTAMP.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TEMP100.
      *AUTHOR. deps81@gmail.com

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT OUTFILE ASSIGN TO FILENAME
           ORGANIZATION IS LINE SEQUENTIAL.

       DATA DIVISION.
       FILE SECTION.
       FD  OUTFILE.
       01  SENSOR-REC.
           05 SENSOR-ID.
               10 SENSOR-PROT  PIC  X.
               10 SENSOR-NUM   PIC  9(3).
           05 SENSOR-TEMP      PIC +999.9.
           05 SENSOR-HUMID     PIC  999.
           05 SENSOR-TIMESTAMP PIC  9(10).

       WORKING-STORAGE SECTION.
       01  TMP-TEMP    PIC S999V9.

       01  FILENAME.
           05 F-PREFIX PIC X(8) VALUE 'READING_'.
           05 F-YEAR   PIC XXXX.
           05 F-MONTH  PIC XX.
           05 F-DAY    PIC XX.
           05 F_DIVIDE PIC X VALUE '_'.
           05 F-HOUR   PIC XX.
           05 F-MIN    PIC XX.
           05 F-SEC    PIC XX.
           05 F_ENDING PIC X(3) VALUE '.FW'.

       01  CHECK-PROTOCOL PIC X(50).
       01  CHECK-MODEL    PIC X(50).
       01  CHECK-ID       PIC 999.
       01  CHECK-TYPE     PIC 9.

       01  TELLSTICK-SENSOR-VARS.
           05 TSV-PROTOCOL     PIC X(50).
           05 TSV-MODEL        PIC X(50).
           05 TSV-DEVICE-ID    PIC 999.
           05 TSV-DATA-TYPE    PIC 9.
           05 TSV-SENSOR-VALUE PIC X(50).
           05 TSV-SENSOR-LEN   PIC 99 VALUE 50.
           05 TSV-TIMESTAMP    USAGE BINARY-LONG UNSIGNED.
           05 TSV-RETURN       PIC S9(4).

       01  TELLSTICK-SENSOR-ITER.
           05 TSI-PROTOCOL     PIC X(50).
           05 TSI-MODEL        PIC X(50).
           05 TSI-ID           USAGE BINARY-CHAR UNSIGNED.
           05 TSI-DATATYPES    USAGE BINARY-LONG UNSIGNED.
           05 TSI-RETURN       USAGE BINARY-CHAR.

       01  TIMESTAMP.
           05 TS-YEAR  PIC XXXX.
           05 TS-MONTH PIC XX.
           05 TS-DAY   PIC XX.
           05 TS-HOUR  PIC XX.
           05 TS-MIN   PIC XX.
           05 TS-SEC   PIC XX.

       PROCEDURE DIVISION.
           DISPLAY "CONNECTING TO TELLSTICK..."
           CALL "telldusInit".
           DISPLAY "CONNECTING TO DATABASE..."
           CALL "SQLinit".

           PERFORM 200-START-ITERATION.

           CALL "telldusClose".
           CALL "SQLclose".

           STOP RUN.

       200-START-ITERATION.
      *    PERFORM 300-CREATE-FILENAME.
      *    OPEN OUTPUT OUTFILE.
      *    DISPLAY "OUTPUT FILE: " FILENAME.

           DISPLAY "ITERATING SENSORS..."
           MOVE ZERO TO TSI-RETURN.
           PERFORM 201-ITERATE-SENSORS
             UNTIL TSI-RETURN IS NOT EQUAL 0.

      *    CLOSE OUTFILE.
           DISPLAY "DONE".

       201-ITERATE-SENSORS.
           MOVE SPACES TO TELLSTICK-SENSOR-ITER.
           CALL "getSensors" USING
               BY REFERENCE TSI-PROTOCOL BY VALUE LENGTH OF TSI-PROTOCOL
               BY REFERENCE TSI-MODEL BY VALUE LENGTH OF TSI-MODEL
               BY REFERENCE TSI-ID
               BY REFERENCE TSI-DATATYPES
               RETURNING TSI-RETURN.

           IF TSI-RETURN IS EQUAL TO 0
      D      DISPLAY "* GOT SENSOR " TSI-ID
             MOVE TSI-PROTOCOL TO CHECK-PROTOCOL
             MOVE TSI-MODEL TO CHECK-MODEL
             MOVE TSI-ID TO CHECK-ID

             MOVE 1 TO CHECK-TYPE
             PERFORM 210-POLLSENSOR

             MOVE TSV-TIMESTAMP TO SENSOR-TIMESTAMP
             MOVE TSI-PROTOCOL(1:1) TO SENSOR-PROT
             MOVE CHECK-ID TO SENSOR-NUM
             MOVE TSV-SENSOR-VALUE TO TMP-TEMP
             MOVE TMP-TEMP TO SENSOR-TEMP

             MOVE 2 TO CHECK-TYPE
             PERFORM 210-POLLSENSOR

             MOVE TSV-SENSOR-VALUE TO SENSOR-HUMID

      D      DISPLAY SENSOR-REC
             PERFORM 400-DATABASE-INSERT
      *      WRITE SENSOR-REC
           END-IF.

       210-POLLSENSOR.
      *    Setup call
           MOVE CHECK-ID TO TSV-DEVICE-ID.
           MOVE CHECK-PROTOCOL TO TSV-PROTOCOL.
           MOVE CHECK-MODEL TO TSV-MODEL.
           MOVE "" TO TSV-SENSOR-VALUE.
      *    1 = TEMPERATURE, 2 = HUMIDITY
           MOVE CHECK-TYPE TO TSV-DATA-TYPE.

      D    DISPLAY "* POLLING SENSOR '" FUNCTION TRIM(CHECK-PROTOCOL)
      D            "', '" FUNCTION TRIM (CHECK-MODEL)
      D            "', " CHECK-ID " AS " CHECK-TYPE.

           CALL "getSensorValue" USING
               BY REFERENCE TSV-PROTOCOL
               BY REFERENCE TSV-MODEL
               BY VALUE TSV-DEVICE-ID
               BY VALUE TSV-DATA-TYPE
               BY REFERENCE TSV-SENSOR-VALUE
               BY VALUE TSV-SENSOR-LEN
               BY REFERENCE TSV-TIMESTAMP
               RETURNING TSV-RETURN.

       300-CREATE-FILENAME.
           MOVE FUNCTION CURRENT-DATE TO TIMESTAMP.
           MOVE TS-YEAR TO F-YEAR.
           MOVE TS-MONTH TO F-MONTH.
           MOVE TS-DAY TO F-DAY.
           MOVE TS-HOUR TO F-HOUR.
           MOVE TS-MIN TO F-MIN.
           MOVE TS-SEC TO F-SEC.

       400-DATABASE-INSERT.
           CALL "insertTemperature" USING
              BY REFERENCE SENSOR-ID
              BY REFERENCE SENSOR-TEMP
              BY VALUE SENSOR-HUMID
              BY VALUE SENSOR-TIMESTAMP.


Delete SUPPLINK.cbl

Delete SUPPLINK.cbl

Replaced by LINK2SUP.cbl

       PROCESS NODYNAM,RENT,APOST,CICS,TRUNC(OPT)

      *****************************************************************
      * Licensed Materials - Property of IBM
      *
      * SAMPLE
      *
      * Copyright IBM Corp. 2017 All Rights Reserved
      *
      * Government Users Restricted Rights - Use, duplication or
      * disclosure restricted by GSA ADP Schedule Contract with
      * IBM Corp.
      *
      *****************************************************************
      *
      * Simple CICS terminal program to receive a supplier ID from the
      * terminal (if specified, otherwise use Task number), LINK to
      * specified Liberty program, and send results to the terminal.
      *
      * To simplify the code, this program has minimal error-handling
      * logic, except on the LINK to Liberty call itself.
      *
      *****************************************************************

       IDENTIFICATION DIVISION.
       PROGRAM-ID.              SUPPLINK.
       DATE-WRITTEN.            October 2017.
      *
       ENVIRONMENT DIVISION.
      *
       DATA DIVISION.
      *
       WORKING-STORAGE SECTION.
      *
      *    STOCK-PART copybook
           COPY STOKPART REPLACING STOCK-PART BY WS-STOCK-PART.
      *
      *    SUPPLIER copybook
           COPY SUPPLIER REPLACING SUPPLIER BY WS-SUPPLIER.

      *
      *    Working storage definitions
       01  WS-STORAGE.
           03 WS-TERMINAL-INPUT     PIC X(80)         VALUE SPACES.
           03 WS-RECEIVE-LENGTH     PIC 9(4)  COMP    VALUE ZERO.
           03 WS-TRANID             PIC X(4)          VALUE SPACES.
           03 WS-TRANID-LEN         PIC S9(8) COMP-4  VALUE ZERO.
           03 WS-SUPPLIER-TXT       PIC 9(8)  DISPLAY VALUE ZERO.
           03 WS-SUPPLIER-LEN       PIC S9(8) COMP-4  VALUE ZERO.
           03 WS-SUPPLIER-NO        PIC 9(8)  COMP-4  VALUE ZERO.
           03 LINK-RESP             PIC 9(8)  COMP    VALUE ZERO.
           03 LINK-RESP2            PIC 9(8)  COMP    VALUE ZERO.

      *    Message to display for normal completion.
      *    Display Link to Liberty USERID, Supplier ID and name.
       01 RESPONSE-MESSAGE.
          03 FILLER PIC X(13) VALUE 'CICS USERID: '.
          03 RESP-CICS-USERID PIC X(8) DISPLAY.
          03 FILLER PIC X(14) VALUE ' SUPPLIER ID: '.
          03 RESP-SUPPLIER-ID PIC 9(8) DISPLAY.
          03 FILLER PIC X(16) VALUE ' SUPPLIER NAME: '.
          03 RESP-SUPPLIER-NAME PIC X(40).

      *   Error message to display if Link to Liberty fails.
      *   Include slots for target PROGRAM, RESP and RESP2.
       01 ERROR-MESSAGE.
          03 FILLER PIC X(17) VALUE 'ERROR LINKING TO '.
          03 ERROR-PROG PIC X(8) DISPLAY.
          03 FILLER PIC X(7) VALUE '. RESP:'.
          03 ERROR-RESP PIC 9(8) DISPLAY.
          03 FILLER PIC X(7) VALUE ' RESP2:'.
          03 ERROR-RESP2 PIC 9(8) DISPLAY.

      *   Names of various CICS constructs
       77 LIBERTY-CHANNEL PIC X(16) VALUE 'LIBERTY-CHANNEL'.
       77 LIBERTY-PROGRAM PIC X(8)  VALUE 'GETSUPPI'.
       77 CONT-STOCK-PART PIC X(16) VALUE 'STOCK-PART'.
       77 CONT-SUPPLIER   PIC X(16) VALUE 'SUPPLIER'.
       77 CONT-USERID     PIC X(16) VALUE 'USERID'.
      *
      *
       PROCEDURE DIVISION USING DFHEIBLK.
      *
       MAIN-PROCESSING SECTION.

      *    Receive data from terminal
           MOVE LENGTH OF WS-TERMINAL-INPUT TO WS-RECEIVE-LENGTH.
           EXEC CICS RECEIVE INTO(WS-TERMINAL-INPUT)
                     LENGTH(WS-RECEIVE-LENGTH) END-EXEC.

      *    Perform very basic parsing of terminal input data.
           UNSTRING WS-TERMINAL-INPUT DELIMITED BY ALL SPACES INTO
                WS-TRANID       COUNT IN WS-TRANID-LEN
                WS-SUPPLIER-TXT COUNT IN WS-SUPPLIER-LEN
           END-UNSTRING.

      *    This example only needs us to populate the supplier ID
      *    field. Initialize the structure and store our fake supplier
      *    in the STOCK-PART structure.
           MOVE LOW-VALUES TO WS-STOCK-PART.

      *    Check if a valid supplier ID was provided, else use
      *    the CICS task number
           IF WS-SUPPLIER-LEN > 0 AND WS-SUPPLIER-LEN < 9 AND
                WS-SUPPLIER-TXT NUMERIC THEN
              MOVE WS-SUPPLIER-TXT TO WS-SUPPLIER-NO
           ELSE
              MOVE EIBTASKN TO WS-SUPPLIER-NO
           END-IF.

      *    Update the stock part supplier ID
           MOVE WS-SUPPLIER-NO TO SUPPLIER IN WS-STOCK-PART.

      *    Write the stock part to the correct container.
           EXEC CICS PUT CONTAINER(CONT-STOCK-PART)
                     CHANNEL(LIBERTY-CHANNEL)
                     FROM(WS-STOCK-PART) END-EXEC.

      *    Link to Liberty J2EE program passing channel.
           EXEC CICS LINK PROGRAM(LIBERTY-PROGRAM)
                     CHANNEL(LIBERTY-CHANNEL)
                     RESP(LINK-RESP) RESP2(LINK-RESP2) END-EXEC.

      *    Perform basic response checking from LINK, report error.
           IF LINK-RESP NOT EQUAL DFHRESP(NORMAL) THEN

              MOVE LIBERTY-PROGRAM TO ERROR-PROG
              MOVE LINK-RESP TO ERROR-RESP
              MOVE LINK-RESP2 TO ERROR-RESP2

      *       Send the response data to the terminal.
              EXEC CICS SEND TEXT FROM(ERROR-MESSAGE)
                     ERASE FREEKB END-EXEC
      *
      *       Return control to CICS (end transaction).
              EXEC CICS RETURN END-EXEC
           END-IF.

      *    Normal response from LINK so continue...
      *    Get Liberty output container from the channel
           EXEC CICS GET CONTAINER(CONT-SUPPLIER)
                     CHANNEL(LIBERTY-CHANNEL)
                     INTO(WS-SUPPLIER) END-EXEC.

      *    Copy fields from container structure to output message.
           MOVE SUPPLIER-ID IN WS-SUPPLIER TO RESP-SUPPLIER-ID.
           MOVE SUPPLIER-NAME IN WS-SUPPLIER TO RESP-SUPPLIER-NAME.

      *    Copy Liberty USERID from container direct to output message.
           EXEC CICS GET CONTAINER(CONT-USERID)
                     CHANNEL(LIBERTY-CHANNEL)
                     INTO(RESP-CICS-USERID) END-EXEC.

      *    Send the complete response message to the terminal.
           EXEC CICS SEND TEXT FROM(RESPONSE-MESSAGE)
                     ERASE FREEKB END-EXEC.
      *
      *    Return control to CICS (end transaction).
           EXEC CICS RETURN END-EXEC.
      *
           GOBACK.


update

update

function show_version(link){
	try{
		resp = link.request('info', []);
		if(resp.code == 'ok'){
			sys.stderr.write(resp.data[0] + ' ' + resp.data[2] + '\n\n');
		}else{
			sys.stderr.write(resp.message + '\n');
			if(resp.code == 'noauth'){
				//
			}else{
				sys.exit(0);
			}
		}
	}catch(Exception e){
		sys.stderr.write('Unexpected error: ' + str(e) + '\n');
		sys.exit(0);
	}
}

function dbsize(link){
	resp = link.request('info', []);
	foreach(resp.data as k=>v){
		if(v != 'leveldb.stats'){
			continue;
		}
		s = resp.data[k + 1];
		lines = s.strip().split('\n');
		lines = lines[ 3 ..];
		size = 0;
		foreach(lines as line){
			ps = line.split();
			size += int(ps[2]);
		}
		return size;
	}
	return 0;
}

class SSDB_iterator_base
{
	public link;
	public finish = false;
	public batch = 2;
	public index = [];
	public key = '';
	public val = '';
	public end = '';

	function init(link){
		this.link = link;
	}

	function seek(s){
		this.key = s;
	}

	function set_range(s, e=''){
		this.key = s;
		this.end = e;
	}
}

class SSDB_kv_scan extends SSDB_iterator_base
{
	public items = [];

	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('scan', [this.key, this.end, this.batch]);
			if(len(resp.data['index']) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data['index'];
			this.items = resp.data['items'];
		}
		this.key = this.index.pop(0);
		this.val = this.items[this.key];
		return true;
	}
}

/*
scan = new SSDB_kv_scan();
while(kvs.next()){
	print scan.key, scan.val;
}
*/

class SSDB_hash_list extends SSDB_iterator_base
{
	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('hlist', [this.key, this.end, this.batch]);
			if(len(resp.data) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data;
		}
		this.key = this.index.pop(0);
		return true;
	}
}

class SSDB_zset_list extends SSDB_iterator_base
{
	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('zlist', [this.key, this.end, this.batch]);
			if(len(resp.data) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data;
		}
		this.key = this.index.pop(0);
		return true;
	}
}

/*
kvs = new SSDB_zset_list();
while(kvs.next()){
	print kvs.name;
}
*/

class SSDB_queue_list extends SSDB_iterator_base
{
	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('qlist', [this.key, this.end, this.batch]);
			if(len(resp.data) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data;
		}
		this.key = this.index.pop(0);
		return true;
	}
}

class SSDB_hash_scan extends SSDB_iterator_base
{
	public name = '';
	public items = [];

	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('hscan', [this.name, this.key, '', this.batch]);
			if(len(resp.data['index']) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data['index'];
			this.items = resp.data['items'];
		}
		this.key = this.index.pop(0);
		this.val = this.items[this.key];
		return true;
	}
}

/*
scan = new SSDB_hash_scan('n');
while(scan.next()){
	print scan.key, scan.val;
}
*/

class SSDB_zset_scan extends SSDB_iterator_base
{
	public name = '';
	public items = [];

	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('zscan', [this.name, this.key, this.val, '', this.batch]);
			if(len(resp.data['index']) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data['index'];
			this.items = resp.data['items'];
		}
		this.key = this.index.pop(0);
		this.val = this.items[this.key];
		return true;
	}
}

/*
scan = new SSDB_zset_scan('n');
while(scan.next()){
	print scan.key, scan.val;
}
*/

class SSDB_queue_scan extends SSDB_iterator_base
{
	public items = [];
	public offset = 0;

	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('qrange', [this.name, this.offset, this.batch]);
			if(len(resp.data) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data;
		}
		this.key = this.offset;
		this.val = this.index.pop(0);
		this.offset += 1;
		return true;
	}
}

/*
scan = new SSDB_queue_scan('q');
while(scan.next()){
	print scan.item;
}
*/

function show_version(link){
	try{
		resp = link.request('info', []);
		if(resp.code == 'ok'){
			sys.stderr.write(resp.data[0] + ' ' + resp.data[2] + '\n\n');
		}else{
			sys.stderr.write(resp.message + '\n');
			sys.exit(0);
		}
	}catch(Exception e){
		sys.stderr.write('Unexpected error: ' + str(e) + '\n');
		sys.exit(0);
	}
}

function dbsize(link){
	resp = link.request('info', []);
	foreach(resp.data as k=>v){
		if(v != 'leveldb.stats'){
			continue;
		}
		s = resp.data[k + 1];
		lines = s.strip().split('\n');
		lines = lines[ 3 ..];
		size = 0;
		foreach(lines as line){
			ps = line.split();
			size += int(ps[2]);
		}
		return size;
	}
	return 0;
}

class SSDB_iterator_base
{
	public link;
	public finish = false;
	public batch = 2;
	public index = [];
	public key = '';
	public val = '';
	public end = '';

	function init(link){
		this.link = link;
	}

	function seek(s){
		this.key = s;
	}

	function set_range(s, e=''){
		this.key = s;
		this.end = e;
	}
}

class SSDB_kv_scan extends SSDB_iterator_base
{
	public items = [];

	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('scan', [this.key, this.end, this.batch]);
			if(len(resp.data['index']) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data['index'];
			this.items = resp.data['items'];
		}
		this.key = this.index.pop(0);
		this.val = this.items[this.key];
		return true;
	}
}

/*
scan = new SSDB_kv_scan();
while(kvs.next()){
	print scan.key, scan.val;
}
*/

class SSDB_hash_list extends SSDB_iterator_base
{
	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('hlist', [this.key, this.end, this.batch]);
			if(len(resp.data) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data;
		}
		this.key = this.index.pop(0);
		return true;
	}
}

class SSDB_zset_list extends SSDB_iterator_base
{
	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('zlist', [this.key, this.end, this.batch]);
			if(len(resp.data) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data;
		}
		this.key = this.index.pop(0);
		return true;
	}
}

/*
kvs = new SSDB_zset_list();
while(kvs.next()){
	print kvs.name;
}
*/

class SSDB_queue_list extends SSDB_iterator_base
{
	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('qlist', [this.key, this.end, this.batch]);
			if(len(resp.data) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data;
		}
		this.key = this.index.pop(0);
		return true;
	}
}

class SSDB_hash_scan extends SSDB_iterator_base
{
	public name = '';
	public items = [];

	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('hscan', [this.name, this.key, '', this.batch]);
			if(len(resp.data['index']) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data['index'];
			this.items = resp.data['items'];
		}
		this.key = this.index.pop(0);
		this.val = this.items[this.key];
		return true;
	}
}

/*
scan = new SSDB_hash_scan('n');
while(scan.next()){
	print scan.key, scan.val;
}
*/

class SSDB_zset_scan extends SSDB_iterator_base
{
	public name = '';
	public items = [];

	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('zscan', [this.name, this.key, this.val, '', this.batch]);
			if(len(resp.data['index']) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data['index'];
			this.items = resp.data['items'];
		}
		this.key = this.index.pop(0);
		this.val = this.items[this.key];
		return true;
	}
}

/*
scan = new SSDB_zset_scan('n');
while(scan.next()){
	print scan.key, scan.val;
}
*/

class SSDB_queue_scan extends SSDB_iterator_base
{
	public items = [];
	public offset = 0;

	function init(link){
	}

	function next(){
		if(this.finish){
			return false;
		}
		if(len(this.index) == 0){
			resp = this.link.request('qrange', [this.name, this.offset, this.batch]);
			if(len(resp.data) == 0){
				this.finish = true;
				return false;
			}
			this.index = resp.data;
		}
		this.key = this.offset;
		this.val = this.index.pop(0);
		this.offset += 1;
		return true;
	}
}

/*
scan = new SSDB_queue_scan('q');
while(scan.next()){
	print scan.item;
}
*/


どうもACCEPTによる入力データの自動トリミング機能が末尾の改行の有無関係なく1文字削るらしい

       *>
       *> 結果 https://paiza.jp/poh/joshibato/tsubame/result/b4aa954c
       *>
       IDENTIFICATION DIVISION.
       PROGRAM-ID. Answer.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       REPOSITORY.
              FUNCTION ALL INTRINSIC.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
              01 Answer-Values.
                     05 n    PIC 9(3).
                     05 n1   PIC 9(3).
                     05 n10  PIC 9(3).
                     05 r    PIC 9(3) VALUE Is 0.
                     05 d    PIC Z(3).
       PROCEDURE DIVISION.
       MainRoutine SECTION.
       000-Main.
              ACCEPT n.
              MOVE n TO n10.
              DIVIDE 10 INTO n10.
              MULTIPLY 10 BY n10.
              MOVE n TO n1.
              SUBTRACT n10 FROM n1.
              DIVIDE 10 INTO n10.
              ADD n n1 n10 TO r.
              MOVE r TO d.
              DISPLAY TRIM(d).
       END PROGRAM Answer.

       *>
       *> 結果 https://paiza.jp/poh/joshibato/tsubame/result/cbf8cf08
       *>
       IDENTIFICATION DIVISION.
       PROGRAM-ID. Answer.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       REPOSITORY.
              FUNCTION ALL INTRINSIC.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
              01 Answer-Values.
                     05 x    PIC X(10).
                     05 n    PIC 9(10).
                     05 n1   PIC 9(10).
                     05 n10  PIC 9(10).
                     05 r    PIC 9(10) VALUE Is 0.
                     05 r2   PIC 9(2).
                     05 r3   PIC 9(3).
       PROCEDURE DIVISION.
       MainRoutine SECTION.
       000-Main.
              ACCEPT x.
              MOVE x TO n.
              MOVE n TO n10.
              DIVIDE 10 INTO n10.
              MULTIPLY 10 BY n10.
              MOVE n TO n1.
              SUBTRACT n10 FROM n1.
              DIVIDE 10 INTO n10.
              ADD n n1 n10 TO r.
              IF NUMVAL(r) < 100 THEN
                     MOVE NUMVAL(r) TO r2
                     DISPLAY r2
              ELSE
                     MOVE NUMVAL(r) TO r3
                     DISPLAY r3
              END-IF.
       END PROGRAM Answer.


Update fizzbuzz.cob

Update fizzbuzz.cob

Update comment for installing COBOL via Linux

000005* To install: install open-cobol (apt-get install open-cobol or brew install open-cobol)
000010* To run: cobc fizzbuzz.cob
000020* Resource: http://opencobol.add1tocobol.com/

PROGRAM-ID
FOREACH I IN 1..100
	IF i % 5 IS 0 AND i % 3 IS 0
		DISPLAY "fizzbuzz"
	ELSE-IF i % 3
		DISPLAY "fizz"
	ELSE-IF i % 5
		DISPLAY "buzz"
	ELSE
		DISPLAY i
	END-IF.
END-FOREACH.

000005* To install: install open-cobol (sudo-apt get open-cobol or brew install open-cobol)
000010* To run: cobc fizzbuzz.cob
000020* Resource: http://opencobol.add1tocobol.com/

PROGRAM-ID
FOREACH I IN 1..100
	IF i % 5 IS 0 AND i % 3 IS 0
		DISPLAY "fizzbuzz"
	ELSE-IF i % 3
		DISPLAY "fizz"
	ELSE-IF i % 5
		DISPLAY "buzz"
	ELSE
		DISPLAY i
	END-IF.
END-FOREACH.


Removed debug displays from factorization

      * Copyright 2015 Dennis Decker Jensen
       program-id. prob0003.
       author. Dennis Decker Jensen.
      * Date: 27 June 2015.
      * Purpose: Calculate prime factors.
      * Tectonics: cobc -x -g -debug -fdebugging-line prob0003
       data division.
       working-storage section.
      *01  target constant as 15485864.
      *01  target constant as 315.
       01  argument pic x(20).
       01  n        pic 9(20).
       01  i        pic 9(11).
       01  factor   pic z(19)9.

       procedure division.
       arguments.
           accept argument from command-line.
           move function numval(argument) to n.
           if function numval(argument) is not positive
               display "Error: Expected number argument > 1" upon syserr
               stop run.
       pre.
      *    move target to n.
           move n to factor.
           display function trim(factor leading)
               ":" space with no advancing.
       main.
           move 2 to i.
           perform factors.
           perform factors varying i from 3 by 2 until i * i > n.
       last-factor.
           if n is greater than 1
               move n to factor
               display function trim(factor leading)
           else
               display space.

           stop run.
       factors.
           perform one-factor until function mod(n, i) is not zero.
       one-factor.
      *    display "i:" space i
      *    display "n:" space n
           move i to factor
           display function trim(factor leading)
                   space with no advancing
           divide n by i giving n.
       end program prob0003.

      * Copyright 2015 Dennis Decker Jensen
       program-id. prob0003.
       author. Dennis Decker Jensen.
      * Date: 27 June 2015.
      * Purpose: Calculate prime factors.
      * Tectonics: cobc -x -g -debug -fdebugging-line prob0003
       data division.
       working-storage section.
      *01  target constant as 15485864.
      *01  target constant as 315.
       01  argument pic x(20).
       01  n        pic 9(20).
       01  i        pic 9(11).
       01  factor   pic z(19)9.

       procedure division.
       arguments.
           accept argument from command-line.
           move function numval(argument) to n.
           if function numval(argument) is not positive
               display "Error: Expected number argument > 1" upon syserr
               stop run.
       pre.
      *    move target to n.
           move n to factor.
           display function trim(factor leading)
               ":" space with no advancing.
       main.
           move 2 to i.
           perform factors.
           perform factors varying i from 3 by 2 until i * i > n.
       last-factor.
           if n is greater than 1
               move n to factor
               display function trim(factor leading)
           else
               display space.

           stop run.
       factors.
           perform one-factor until function mod(n, i) is not zero.
       one-factor.
           display "i:" space i
           display "n:" space n
           move i to factor
           display function trim(factor leading)
                   space with no advancing
           divide n by i giving n.
       end program prob0003.


さて、テストケースを通らない原因を追求しないといけないな

さて、テストケースを通らない原因を追求しないといけないな

       *>
       *> 結果 https://paiza.jp/poh/joshibato/rio/result/6957daab
       *>
       IDENTIFICATION DIVISION.
       PROGRAM-ID. Answer.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       REPOSITORY.
              FUNCTION ALL INTRINSIC.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
              01 Answer-Values.
                     05 n          PIC 9(2).  *> 05 である必要はなく 02 n PIC 9(2). でもよいらしい
                     05 i          PIC 9(2).
                     05 w          PIC 9(4)V9(20) VALUE 0.0. *> 9(4)V9(20)は計算用 9(4).9(20)だと文字出力用？
                     05 c          PIC 9(4)V9(20) VALUE 0.0.
                     05 wc         PIC 9(4)V9(20).
                     05 ans        PIC 9(4)V9(20).
                     05 x1         PIC 9(4)V9(20).
                     05 x2         PIC 9(4)V9(20).
                     05 dsp        PIC Z(4).        *> Zは表示用,9での上位桁の0をスペースに置き換える
                     05 tas.
                            10 t   PIC 9(2). *> tが1桁と分かっているので文字数決め打ち分割
                            10 s   PIC 9(3). *> sは3桁までなので
       PROCEDURE DIVISION.
       MainRoutine SECTION.
       000-Main.
              ACCEPT n.
              PERFORM WITH TEST AFTER VARYING i FROM 1 BY 1 UNTIL i = n
                     ACCEPT tas
                     IF NUMVAL(t) = 1 THEN
                            ADD NUMVAL(s) TO w
                     END-IF
                     IF NUMVAL(t) = 2 THEN *> 流石にELSEネストはキツイ
                            ADD NUMVAL(s) TO c
                     END-IF
                     IF NUMVAL(t) = 3 THEN
                        MOVE w TO wc
                        ADD c TO wc

                        MOVE w TO x1
                        MULTIPLY wc BY x1
                        MOVE NUMVAL(s) TO x2
                        MULTIPLY w BY x2
                        ADD x2 TO x1
                        DIVIDE wc INTO x1
                        MOVE x1 TO w

                        MOVE c TO x1
                        MULTIPLY wc BY x1
                        MOVE NUMVAL(s) TO x2
                        MULTIPLY c BY x2
                        ADD x2 TO x1
                        DIVIDE wc INTO x1
                        MOVE x1 TO c

                     END-IF
              END-PERFORM.

              MOVE w TO wc.
              ADD c TO wc.

              MOVE 100 TO ans.
              MULTIPLY c BY ans.
              DIVIDE wc INTO ans.

              MOVE ans TO dsp.
              DISPLAY TRIM(dsp).
       END PROGRAM Answer.

       *>
       *> 結果 https://paiza.jp/poh/joshibato/rio/result/c515c89e
       *>
       IDENTIFICATION DIVISION.
       PROGRAM-ID. Answer.
       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       REPOSITORY.
              FUNCTION ALL INTRINSIC.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
              01 Answer-Values.
                     05 n          PIC 9(2).  *> 05 である必要はなく 02 n PIC 9(2). でもよいらしい
                     05 i          PIC 9(2).
                     05 w          PIC 9(4)V9(20) VALUE 0.0. *> 9(4)V9(20)は計算用 9(4).9(20)だと文字出力用？
                     05 c          PIC 9(4)V9(20) VALUE 0.0.
                     05 wc         PIC 9(4)V9(20).
                     05 ans        PIC 9(4)V9(20).
                     05 x1         PIC 9(4)V9(20).
                     05 x2         PIC 9(4)V9(20).
                     05 dsp        PIC Z(4).        *> Zは表示用,9での上位桁の0をスペースに置き換える
                     05 tas.
                            10 T   PIC 9(2). *> tが1桁と分かっているので文字数決め打ち分割
                            10 S   PIC 9(3). *> sは3桁までなので
       PROCEDURE DIVISION.
       MainRoutine SECTION.
       000-Main.
              ACCEPT n.
              PERFORM WITH TEST AFTER VARYING i FROM 1 BY 1 UNTIL i = n
                     ACCEPT tas
                     IF NUMVAL(t) = 1 THEN
                            ADD NUMVAL(s) TO w
                     END-IF
                     IF NUMVAL(t) = 2 THEN *> 流石にELSEネストはキツイ
                            ADD NUMVAL(s) TO c
                     END-IF
                     IF NUMVAL(t) = 3 THEN
                        MOVE w TO wc
                        ADD c TO wc

                        MOVE w TO x1
                        MULTIPLY wc BY x1
                        MOVE NUMVAL(s) TO x2
                        MULTIPLY w BY x2
                        ADD x2 TO x1
                        DIVIDE wc INTO x1
                        MOVE x1 TO w

                        MOVE c TO x1
                        MULTIPLY wc BY x1
                        MOVE NUMVAL(s) TO x2
                        MULTIPLY c BY x2
                        ADD x2 TO x1
                        DIVIDE wc INTO x1
                        MOVE x1 TO c

                     END-IF
              END-PERFORM.

              MOVE w TO wc.
              ADD c TO wc.

              MOVE 100 TO ans.
              MULTIPLY c BY ans.
              DIVIDE wc INTO ans.

              MOVE ans TO dsp.
              DISPLAY TRIM(dsp).
       END PROGRAM Answer.


fix ssdb-cli typo

fix ssdb-cli typo

import thread, re, time, socket;
import getopt, shlex;
import datetime;

try{
	import readline;
}catch(Exception e){
}

function welcome(){
	sys.stderr.write('ssdb (cli) - ssdb command line tool.\n');
	sys.stderr.write('Copyright (c) 2012-2014 ideawu.com\n');
	sys.stderr.write('\n');
	sys.stderr.write("'h' or 'help' for help, 'q' to quit.\n");
	sys.stderr.write('\n');
}

function show_command_help(){
	print '';
	print '# Display ssdb-server status';
	print '	info';
	print '# KEY-VALUE COMMANDS';
	print '	set key value';
	print '	setx key value ttl';
	print '	get key';
	print '	del key';
	print '	list key_start key_end limit';
	print '	keys key_start key_end limit';
	print '	scan key_start key_end limit';
	print '# MAP(HASHMAP) COMMANDS';
	print '	hset name key value';
	print '	hget name key';
	print '	hdel name key';
	print '	hclear name';
	print '	hlist name_start name_end limit';
	print '	hkeys name key_start key_end limit';
	print '	hscan name key_start key_end limit';
	print '# ZSET(SORTED SET) COMMANDS';
	print '	zset name key score';
	print '	zget name key';
	print '	zdel name key';
	print '	zclear name';
	print '	zlist name_start name_end limit';
	print '	zkeys name key_start score_start score_end limit';
	print '	zscan name key_start score_start score_end limit';
	print '# FLUSH DATABASE';
	print '	flushdb';
	print '	flushdb kv';
	print '	flushdb hash';
	print '	flushdb zset';
	print '';
	print '# EXAMPLES';
	print '	scan "" "" 10';
	print '	scan aa "" 10';
	print '	hlist "" "" 10';
	print '	hscan h "" "" 10';
	print '	hscan h aa "" 10';
	print '	zlist "" "" 10';
	print '	zscan z "" "" "" 10';
	print '	zscan z "" 1 100 10';
	print '';
	print 'press \'q\' and Enter to quit.';
	print '';
}

function usage(){
	print '';
	print 'Usage:';
	print '	ssdb-cli [-h] [HOST] [-p] [PORT]';
	print '';
	print 'Options:';
	print '	-h 127.0.0.1';
	print '		ssdb server hostname/ip address';
	print '	-p 8888';
	print '		ssdb server port';
	print '';
	print 'Examples:';
	print '	ssdb-cli';
	print '	ssdb-cli 8888';
	print '	ssdb-cli 127.0.0.1 8888';
	print '	ssdb-cli -h 127.0.0.1 -p 8888';
}

function repr_data(str){
	ret = repr(str);
	if(len(ret) > 0){
		if(ret[0] == '\''){
			ret = ret.replace("\\'", "'");
			ret = ret[1 .. -1];
		}else if(ret[0] == '"'){
			ret = ret.replace('\\"', '"');
			ret = ret[1 .. -1];
		}else{
		}
	}
	ret = ret.replace("\\\\", "\\");
	return ret;
}

function hclear(link, hname, verbose=true){
	ret = 0;
	num = 0;
	batch = 1000;
	last_count = 0;

	r = link.request('hclear', [hname]);
	try{
		ret = r.data;
	}catch(Exception e){
	}
	return ret;
}

function zclear(link, zname, verbose=true){
	ret = 0;
	num = 0;
	batch = 1000;
	last_count = 0;

	r = link.request('zclear', [zname]);
	try{
		ret = r.data;
	}catch(Exception e){
	}
	return ret;
}

function flushdb(link, data_type){
	printf('\n');
	printf('============================ DANGER! ============================\n');
	printf('This operation is DANGEROUS and is not recoverable, if you\n');
	printf('really want to flush the whole db(delete ALL data in ssdb server),\n');
	printf('input \'yes\' and press Enter, or just press Enter to cancel\n');
	printf('=================================================================\n');
	printf('\n');
	printf('> flushdb? ');

	line = sys.stdin.readline().strip();
	if(line != 'yes'){
		printf('Operation cancelled.\n\n');
		return;
	}

	print 'Begin to flushdb...\n';

	batch = 1000;

	d_kv = 0;
	if(data_type == '' || data_type == 'kv'){
		while(true){
			resp = link.request('keys', ['', '', batch]);
			if(len(resp.data) == 0){
				break;
			}
			d_kv += len(resp.data);
			link.request('multi_del', resp.data);
			printf('delete[kv  ] %d key(s).\n', d_kv);
		}
	}

	d_hash = 0;
	d_hkeys = 0;
	if(data_type == '' || data_type == 'hash'){
		while(true){
			resp = link.request('hlist', ['', '', batch]);
			if(len(resp.data) == 0){
				break;
			}
			last_num = 0;
			foreach(resp.data as hname){
				d_hash += 1;
				deleted_num = hclear(link, hname, false);
				d_hkeys += deleted_num;
				if(d_hkeys - last_num >= batch){
					last_num = d_hkeys;
					printf('delete[hash] %d hash(s), %d key(s).\n', d_hash, d_hkeys);
				}
			}
			if(d_hkeys - last_num >= batch){
				printf('delete[hash] %d hash(s), %d key(s).\n', d_hash, d_hkeys);
			}
		}
		printf('delete[hash] %d hash(s), %d key(s).\n', d_hash, d_hkeys);
	}

	d_zset = 0;
	d_zkeys = 0;
	if(data_type == '' || data_type == 'zset'){
		while(true){
			resp = link.request('zlist', ['', '', batch]);
			if(len(resp.data) == 0){
				break;
			}
			last_num = 0;
			foreach(resp.data as zname){
				d_zset += 1;
				deleted_num = zclear(link, zname, false);
				d_zkeys += deleted_num;
				if(d_zkeys - last_num >= batch){
					last_num = d_zkeys;
					printf('delete[zset] %d zset(s), %d key(s).\n', d_zset, d_zkeys);
				}
			}
			if(d_zkeys - last_num >= batch){
				printf('delete[zset] %d zset(s), %d key(s).\n', d_zset, d_zkeys);
			}
		}
		printf('delete[zset] %d zset(s), %d key(s).\n', d_zset, d_zkeys);
	}

	printf('\n');
	printf('===== flushdb stats =====\n');
	if(data_type == '' || data_type == 'kv'){
		printf('[kv]   %8d key(s).\n', d_kv);
	}
	if(data_type == '' || data_type == 'hash'){
		printf('[hash] %8d hash(s), %8d key(s).\n', d_hash, d_hkeys);
	}
	if(data_type == '' || data_type == 'zset'){
		printf('[zset] %8d zset(s), %8d key(s).\n', d_zset, d_zkeys);
	}
	printf('\n');

	printf('clear binlog\n');
	link.request('clear_binlog');
	printf('\n');

	printf('compacting...\n');
	link.request('compact');
	printf('done.\n');
	printf('\n');
}

function timespan(stime){
	etime = datetime.datetime.now();
	ts = etime - stime;
	time_consume = ts.seconds + ts.microseconds/1000000.;
	return time_consume;
}

host = '';
port = '';
opt = '';
args = [];
foreach(sys.argv[1 ..] as arg){
	if(opt == '' && arg.startswith('-')){
		opt = arg;
	}else{
		switch(opt){
			case '-h':
				host = arg;
				opt = '';
				break;
			case '-p':
				port = arg;
				opt = '';
				break;
			default:
				args.append(arg);
				break;
		}
	}
}

if(host == ''){
	host = '127.0.0.1';
	foreach(args as arg){
		if(!re.match('^[0-9]+$', args[0])){
			host = arg;
			break;
		}
	}
}
if(port == ''){
	port = '8888';
	foreach(args as arg){
		if(re.match('^[0-9]+$', args[0])){
			port = arg;
			break;
		}
	}
}

try{
	port = int(port);
}catch(Exception e){
	print 'Invalid argument port: ', port;
	usage();
	sys.exit(0);
}

sys.path.append('./api/python');
sys.path.append('../api/python');
import SSDB.SSDB;

try{
	link = new SSDB(host, port);
}catch(socket.error e){
	printf('Failed to connect to: %s:%d\n', host, port);
	print 'Connection error: ', str(e);
	sys.exit(0);
}
welcome();

try{
	resp = link.request('info', []);
	print 'ssdb-server version: ' + resp.data[2] + '\n';
}catch(Exception e){
}

while(true){
	line = '';
	c = sprintf('ssdb %s:%s> ', host, str(port));
	b = sys.stdout;
	sys.stdout = sys.stderr;
	try{
		line = raw_input(c);
	}catch(Exception e){
		break;
	}
	sys.stdout = b;

	if(line == ''){
		continue;
	}
	line = line.strip();
	if(line == 'q' || line == 'quit'){
		print 'bye.';
		break;
	}
	if(line == 'h' || line == 'help'){
		show_command_help();
		continue;
	}

	try{
		ps = shlex.split(line);
	}catch(Exception e){
		print 'error: ', e;
		continue;
	}
	if(len(ps) == 0){
		continue;
	}
	cmd = ps[0].lower();
	args = ps[1 .. ];

	try{
		if(cmd == 'flushdb'){
			stime = datetime.datetime.now();
			if(len(args) == 0){
				flushdb(link, '');
			}else{
				flushdb(link, args[0]);
			}
			sys.stderr.write(sprintf('(%.3f sec)\n', timespan(stime)));
			continue;
		}
	}catch(Exception e){
		sys.stderr.write("error! - " + str(e) + "\n");
		continue;
	}

	retry = 0;
	max_retry = 5;
	stime = datetime.datetime.now();
	while(true){
		stime = datetime.datetime.now();
		resp = link.request(cmd, args);
		if(resp.code == 'disconnected'){
			link.close();
			time.sleep(retry);
			retry ++;
			if(retry > max_retry){
				print 'cannot connect to server, give up...';
				break;
			}
			printf('[%d/%d] reconnecting to server... ', retry, max_retry);
			try{
				link = new SSDB(host, port);
				print 'done.';
			}catch(socket.error e){
				print 'Connect error: ', str(e);
				continue;
			}
			print '';
		}else{
			break;
		}
	}

	time_consume = timespan(stime);
	if(!resp.ok()){
		if(resp.not_found()){
			print 'not_found';
		}else{
			print 'error: ' + resp.code;
		}
		sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
	}else{
		switch(cmd){
			case 'exists':
			case 'hexists':
			case 'zexists':
				if(resp.data == true){
					printf('true\n');
				}else{
					printf('false\n');
				}
				sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
				break;
			case 'multi_exists':
			case 'multi_hexists':
			case 'multi_zexists':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 25);
				foreach(resp.data as k=>v){
					if(v == true){
						s = 'true';
					}else{
						s = 'false';
					}
					printf('  %-15s : %s\n', repr_data(k), s);
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'getset':
			case 'setnx':
			case 'get':
			case 'zget':
			case 'hget':
			case 'qfront':
			case 'qback':
			case 'qget':
			case 'qpop':
			case 'qpop_front':
			case 'qpop_back':
			case 'incr':
			case 'decr':
			case 'zincr':
			case 'zdecr':
			case 'hincr':
			case 'hdecr':
			case 'hsize':
			case 'zsize':
			case 'qsize':
			case 'zrank':
			case 'zrrank':
			case 'zsum':
			case 'zcount':
			case 'zavg':
			case 'zremrangebyrank':
			case 'zremrangebyscore':
			case 'zavg':
			case 'multi_del':
			case 'multi_hdel':
			case 'multi_zdel':
			case 'hclear':
			case 'zclear':
			case 'qclear':
			case 'qpush':
			case 'qpush_front':
			case 'qpush_back':
				print repr_data(resp.data);
				sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
				break;
			case 'set':
			case 'setx':
			case 'zset':
			case 'hset':
			case 'del':
			case 'zdel':
			case 'hdel':
				print resp.code;
				sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
				break;
			case 'scan':
			case 'rscan':
			case 'hgetall':
			case 'hscan':
			case 'hrscan':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 25);
				foreach(resp.data['index'] as k){
					printf('  %-15s : %s\n', repr_data(k), repr_data(resp.data['items'][k]));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data['index']), time_consume));
				break;
			case 'zscan':
			case 'zrscan':
			case 'zrange':
			case 'zrrange':
				printf('%-15s %s\n', 'key', 'score');
				print ('-' * 25);
				foreach(resp.data['index'] as k){
					score = resp.data['items'][k];
					printf('  %-15s: %s\n', repr_data(repr_data(k)), score);
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data['index']), time_consume));
				break;
			case 'keys':
			case 'list':
			case 'zkeys':
			case 'hkeys':
				printf('  %15s\n', 'key');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'hvals':
				printf('  %15s\n', 'value');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'hlist':
			case 'zlist':
			case 'qlist':
			case 'qslice':
			case 'qrange':
				printf('  %15s\n', 'name');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'multi_get':
			case 'multi_hget':
			case 'multi_zget':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 25);
				foreach(resp.data as k=>v){
					printf('  %-15s : %s\n', repr_data(k), repr_data(v));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'info':
				is_val = false;
				for(i=1; i<len(resp.data); i++){
					s = resp.data[i];
					if(is_val){
						s = '    ' + s.replace('\n', '\n    ');
					}
					print s;
					is_val = !is_val;
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'key_range':
				if(len(resp.data) != 6){
					print 'error!';
				}else{
					for(i=0; i<len(resp.data); i++){
						resp.data[i] = repr_data(resp.data[i]);
						if(resp.data[i] == ''){
							resp.data[i] = '""';
						}
					}
					klen = 0;
					vlen = 0;
					for(i=0; i<len(resp.data); i+=2){
						klen = max(len(resp.data[i]), klen);
						vlen = max(len(resp.data[i+1]), vlen);
					}
					printf('	kv   :  %-*s  -  %-*s\n', klen, resp.data[0], vlen, resp.data[1]);
					printf('	hash :  %-*s  -  %-*s\n', klen, resp.data[2], vlen, resp.data[3]);
					printf('	zset :  %-*s  -  %-*s\n', klen, resp.data[4], vlen, resp.data[5]);
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			default:
				print repr_data(resp.code), repr_data(resp.data);
				sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
				break;
		}
	}
}

import thread, re, time, socket;
import getopt, shlex;
import datetime;

try{
	import readline;
}catch(Exception e){
}

function welcome(){
	sys.stderr.write('ssdb (cli) - ssdb command line tool.\n');
	sys.stderr.write('Copyright (c) 2012-2014 ideawu.com\n');
	sys.stderr.write('\n');
	sys.stderr.write("'h' or 'help' for help, 'q' to quit.\n");
	sys.stderr.write('\n');
}

function show_command_help(){
	print '';
	print '# Display ssdb-server status';
	print '	info';
	print '# KEY-VALUE COMMANDS';
	print '	set key value';
	print '	setx key value ttl';
	print '	get key';
	print '	del key';
	print '	list key_start key_end limit';
	print '	keys key_start key_end limit';
	print '	scan key_start key_end limit';
	print '# MAP(HASHMAP) COMMANDS';
	print '	hset name key value';
	print '	hget name key';
	print '	hdel name key';
	print '	hclear name';
	print '	hlist name_start name_end limit';
	print '	hkeys name key_start key_end limit';
	print '	hscan name key_start key_end limit';
	print '# ZSET(SORTED SET) COMMANDS';
	print '	zset name key score';
	print '	zget name key';
	print '	zdel name key';
	print '	zclear name';
	print '	zlist name_start name_end limit';
	print '	zkeys name key_start score_start score_end limit';
	print '	zscan name key_start score_start score_end limit';
	print '# FLUSH DATABASE';
	print '	flushdb';
	print '	flushdb kv';
	print '	flushdb hash';
	print '	flushdb zset';
	print '';
	print '# EXAMPLES';
	print '	scan "" "" 10';
	print '	scan aa "" 10';
	print '	hlist "" "" 10';
	print '	hscan h "" "" 10';
	print '	hscan h aa "" 10';
	print '	zlist "" "" 10';
	print '	zscan z "" "" "" 10';
	print '	zscan z "" 1 100 10';
	print '';
	print 'press \'q\' and Enter to quit.';
	print '';
}

function usage(){
	print '';
	print 'Usage:';
	print '	ssdb-cli [-h] [HOST] [-p] [PORT]';
	print '';
	print 'Options:';
	print '	-h 127.0.0.1';
	print '		ssdb server hostname/ip address';
	print '	-p 8888';
	print '		ssdb server port';
	print '';
	print 'Examples:';
	print '	ssdb-cli';
	print '	ssdb-cli 8888';
	print '	ssdb-cli 127.0.0.1 8888';
	print '	ssdb-cli -h 127.0.0.1 -p 8888';
}

function repr_data(str){
	ret = repr(str);
	if(len(ret) > 0){
		if(ret[0] == '\''){
			ret = ret.replace("\\'", "'");
			ret = ret[1 .. -1];
		}else if(ret[0] == '"'){
			ret = ret.replace('\\"', '"');
			ret = ret[1 .. -1];
		}else{
		}
	}
	ret = ret.replace("\\\\", "\\");
	return ret;
}

function hclear(link, hname, verbose=true){
	ret = 0;
	num = 0;
	batch = 1000;
	last_count = 0;

	r = link.request('hclear', [hname]);
	try{
		ret = r.data;
	}catch(Exception e){
	}
	return ret;
}

function zclear(link, zname, verbose=true){
	ret = 0;
	num = 0;
	batch = 1000;
	last_count = 0;

	r = link.request('zclear', [zname]);
	try{
		ret = r.data;
	}catch(Exception e){
	}
	return ret;
}

function flushdb(link, data_type){
	printf('\n');
	printf('============================ DANGER! ============================\n');
	printf('This operation is DANGEROUS and is not recoverable, if you\n');
	printf('realy want to flush the whole db(delete ALL data in ssdb server),\n');
	printf('input \'yes\' and press Enter, or just press Enter to cancel\n');
	printf('=================================================================\n');
	printf('\n');
	printf('> flushdb? ');

	line = sys.stdin.readline().strip();
	if(line != 'yes'){
		printf('Operation cancelled.\n\n');
		return;
	}

	print 'Begin to flushdb...\n';

	batch = 1000;

	d_kv = 0;
	if(data_type == '' || data_type == 'kv'){
		while(true){
			resp = link.request('keys', ['', '', batch]);
			if(len(resp.data) == 0){
				break;
			}
			d_kv += len(resp.data);
			link.request('multi_del', resp.data);
			printf('delete[kv  ] %d key(s).\n', d_kv);
		}
	}

	d_hash = 0;
	d_hkeys = 0;
	if(data_type == '' || data_type == 'hash'){
		while(true){
			resp = link.request('hlist', ['', '', batch]);
			if(len(resp.data) == 0){
				break;
			}
			last_num = 0;
			foreach(resp.data as hname){
				d_hash += 1;
				deleted_num = hclear(link, hname, false);
				d_hkeys += deleted_num;
				if(d_hkeys - last_num >= batch){
					last_num = d_hkeys;
					printf('delete[hash] %d hash(s), %d key(s).\n', d_hash, d_hkeys);
				}
			}
			if(d_hkeys - last_num >= batch){
				printf('delete[hash] %d hash(s), %d key(s).\n', d_hash, d_hkeys);
			}
		}
		printf('delete[hash] %d hash(s), %d key(s).\n', d_hash, d_hkeys);
	}

	d_zset = 0;
	d_zkeys = 0;
	if(data_type == '' || data_type == 'zset'){
		while(true){
			resp = link.request('zlist', ['', '', batch]);
			if(len(resp.data) == 0){
				break;
			}
			last_num = 0;
			foreach(resp.data as zname){
				d_zset += 1;
				deleted_num = zclear(link, zname, false);
				d_zkeys += deleted_num;
				if(d_zkeys - last_num >= batch){
					last_num = d_zkeys;
					printf('delete[zset] %d zset(s), %d key(s).\n', d_zset, d_zkeys);
				}
			}
			if(d_zkeys - last_num >= batch){
				printf('delete[zset] %d zset(s), %d key(s).\n', d_zset, d_zkeys);
			}
		}
		printf('delete[zset] %d zset(s), %d key(s).\n', d_zset, d_zkeys);
	}

	printf('\n');
	printf('===== flushdb stats =====\n');
	if(data_type == '' || data_type == 'kv'){
		printf('[kv]   %8d key(s).\n', d_kv);
	}
	if(data_type == '' || data_type == 'hash'){
		printf('[hash] %8d hash(s), %8d key(s).\n', d_hash, d_hkeys);
	}
	if(data_type == '' || data_type == 'zset'){
		printf('[zset] %8d zset(s), %8d key(s).\n', d_zset, d_zkeys);
	}
	printf('\n');

	printf('clear binlog\n');
	link.request('clear_binlog');
	printf('\n');

	printf('compacting...\n');
	link.request('compact');
	printf('done.\n');
	printf('\n');
}

function timespan(stime){
	etime = datetime.datetime.now();
	ts = etime - stime;
	time_consume = ts.seconds + ts.microseconds/1000000.;
	return time_consume;
}

host = '';
port = '';
opt = '';
args = [];
foreach(sys.argv[1 ..] as arg){
	if(opt == '' && arg.startswith('-')){
		opt = arg;
	}else{
		switch(opt){
			case '-h':
				host = arg;
				opt = '';
				break;
			case '-p':
				port = arg;
				opt = '';
				break;
			default:
				args.append(arg);
				break;
		}
	}
}

if(host == ''){
	host = '127.0.0.1';
	foreach(args as arg){
		if(!re.match('^[0-9]+$', args[0])){
			host = arg;
			break;
		}
	}
}
if(port == ''){
	port = '8888';
	foreach(args as arg){
		if(re.match('^[0-9]+$', args[0])){
			port = arg;
			break;
		}
	}
}

try{
	port = int(port);
}catch(Exception e){
	print 'Invalid argument port: ', port;
	usage();
	sys.exit(0);
}

sys.path.append('./api/python');
sys.path.append('../api/python');
import SSDB.SSDB;

try{
	link = new SSDB(host, port);
}catch(socket.error e){
	printf('Failed to connect to: %s:%d\n', host, port);
	print 'Connection error: ', str(e);
	sys.exit(0);
}
welcome();

try{
	resp = link.request('info', []);
	print 'ssdb-server version: ' + resp.data[2] + '\n';
}catch(Exception e){
}

while(true){
	line = '';
	c = sprintf('ssdb %s:%s> ', host, str(port));
	b = sys.stdout;
	sys.stdout = sys.stderr;
	try{
		line = raw_input(c);
	}catch(Exception e){
		break;
	}
	sys.stdout = b;

	if(line == ''){
		continue;
	}
	line = line.strip();
	if(line == 'q' || line == 'quit'){
		print 'bye.';
		break;
	}
	if(line == 'h' || line == 'help'){
		show_command_help();
		continue;
	}

	try{
		ps = shlex.split(line);
	}catch(Exception e){
		print 'error: ', e;
		continue;
	}
	if(len(ps) == 0){
		continue;
	}
	cmd = ps[0].lower();
	args = ps[1 .. ];

	try{
		if(cmd == 'flushdb'){
			stime = datetime.datetime.now();
			if(len(args) == 0){
				flushdb(link, '');
			}else{
				flushdb(link, args[0]);
			}
			sys.stderr.write(sprintf('(%.3f sec)\n', timespan(stime)));
			continue;
		}
	}catch(Exception e){
		sys.stderr.write("error! - " + str(e) + "\n");
		continue;
	}

	retry = 0;
	max_retry = 5;
	stime = datetime.datetime.now();
	while(true){
		stime = datetime.datetime.now();
		resp = link.request(cmd, args);
		if(resp.code == 'disconnected'){
			link.close();
			time.sleep(retry);
			retry ++;
			if(retry > max_retry){
				print 'cannot connect to server, give up...';
				break;
			}
			printf('[%d/%d] reconnecting to server... ', retry, max_retry);
			try{
				link = new SSDB(host, port);
				print 'done.';
			}catch(socket.error e){
				print 'Connect error: ', str(e);
				continue;
			}
			print '';
		}else{
			break;
		}
	}

	time_consume = timespan(stime);
	if(!resp.ok()){
		if(resp.not_found()){
			print 'not_found';
		}else{
			print 'error: ' + resp.code;
		}
		sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
	}else{
		switch(cmd){
			case 'exists':
			case 'hexists':
			case 'zexists':
				if(resp.data == true){
					printf('true\n');
				}else{
					printf('false\n');
				}
				sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
				break;
			case 'multi_exists':
			case 'multi_hexists':
			case 'multi_zexists':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 25);
				foreach(resp.data as k=>v){
					if(v == true){
						s = 'true';
					}else{
						s = 'false';
					}
					printf('  %-15s : %s\n', repr_data(k), s);
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'getset':
			case 'setnx':
			case 'get':
			case 'zget':
			case 'hget':
			case 'qfront':
			case 'qback':
			case 'qget':
			case 'qpop':
			case 'qpop_front':
			case 'qpop_back':
			case 'incr':
			case 'decr':
			case 'zincr':
			case 'zdecr':
			case 'hincr':
			case 'hdecr':
			case 'hsize':
			case 'zsize':
			case 'qsize':
			case 'zrank':
			case 'zrrank':
			case 'zsum':
			case 'zcount':
			case 'zavg':
			case 'zremrangebyrank':
			case 'zremrangebyscore':
			case 'zavg':
			case 'multi_del':
			case 'multi_hdel':
			case 'multi_zdel':
			case 'hclear':
			case 'zclear':
			case 'qclear':
			case 'qpush':
			case 'qpush_front':
			case 'qpush_back':
				print repr_data(resp.data);
				sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
				break;
			case 'set':
			case 'setx':
			case 'zset':
			case 'hset':
			case 'del':
			case 'zdel':
			case 'hdel':
				print resp.code;
				sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
				break;
			case 'scan':
			case 'rscan':
			case 'hgetall':
			case 'hscan':
			case 'hrscan':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 25);
				foreach(resp.data['index'] as k){
					printf('  %-15s : %s\n', repr_data(k), repr_data(resp.data['items'][k]));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data['index']), time_consume));
				break;
			case 'zscan':
			case 'zrscan':
			case 'zrange':
			case 'zrrange':
				printf('%-15s %s\n', 'key', 'score');
				print ('-' * 25);
				foreach(resp.data['index'] as k){
					score = resp.data['items'][k];
					printf('  %-15s: %s\n', repr_data(repr_data(k)), score);
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data['index']), time_consume));
				break;
			case 'keys':
			case 'list':
			case 'zkeys':
			case 'hkeys':
				printf('  %15s\n', 'key');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'hvals':
				printf('  %15s\n', 'value');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'hlist':
			case 'zlist':
			case 'qlist':
			case 'qslice':
			case 'qrange':
				printf('  %15s\n', 'name');
				print ('-' * 17);
				foreach(resp.data as k){
					printf('  %15s\n', repr_data(k));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'multi_get':
			case 'multi_hget':
			case 'multi_zget':
				printf('%-15s %s\n', 'key', 'value');
				print ('-' * 25);
				foreach(resp.data as k=>v){
					printf('  %-15s : %s\n', repr_data(k), repr_data(v));
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'info':
				is_val = false;
				for(i=1; i<len(resp.data); i++){
					s = resp.data[i];
					if(is_val){
						s = '    ' + s.replace('\n', '\n    ');
					}
					print s;
					is_val = !is_val;
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			case 'key_range':
				if(len(resp.data) != 6){
					print 'error!';
				}else{
					for(i=0; i<len(resp.data); i++){
						resp.data[i] = repr_data(resp.data[i]);
						if(resp.data[i] == ''){
							resp.data[i] = '""';
						}
					}
					klen = 0;
					vlen = 0;
					for(i=0; i<len(resp.data); i+=2){
						klen = max(len(resp.data[i]), klen);
						vlen = max(len(resp.data[i+1]), vlen);
					}
					printf('	kv   :  %-*s  -  %-*s\n', klen, resp.data[0], vlen, resp.data[1]);
					printf('	hash :  %-*s  -  %-*s\n', klen, resp.data[2], vlen, resp.data[3]);
					printf('	zset :  %-*s  -  %-*s\n', klen, resp.data[4], vlen, resp.data[5]);
				}
				sys.stderr.write(sprintf('%d result(s) (%.3f sec)\n', len(resp.data), time_consume));
				break;
			default:
				print repr_data(resp.code), repr_data(resp.data);
				sys.stderr.write(sprintf('(%.3f sec)\n', time_consume));
				break;
		}
	}
}