Delete Postgres Cache

1
2
3
4
#!/bin/bash
sync
echo 1 > /proc/sys/vm/drop_caches
service postgresql-9.3 restart
Posted in Database, PostgreSQL | Comments Off on Delete Postgres Cache

Java Flight Recorder: a profiler that’s already in your JVM

If you’re running anything on the JVM (Java Virtual Machine) in production and you’ve never opened a Flight Recorder file, you’re leaving a free profiler on the table. Java Flight Recorder (JFR) is a low-overhead event recorder built into the JVM itself — no agent, no instrumentation, no extra dependency. You turn it on with a flag, you get back a .jfr file, you open it in JDK Mission Control and it tells you where your CPU time went, what the garbage collector (GC) was doing, which threads were contending on which locks, and which methods allocated the most memory. Originally a commercial JRockit feature, JFR was donated to OpenJDK as JEP 328 and has been free for production use since JDK 11. ☕

What it actually records

JFR is event-based. The JVM and the operating system fire events — GC pauses, thread state changes, exception throws, just-in-time (JIT) compilations, file I/O, socket reads — and JFR writes them to a ring buffer. You can also emit your own custom events from application code. The default profile aims for under 2% overhead, which is the magic number that makes it acceptable to leave running in production.

Quick start: capture a recording at JVM startup

The simplest way to capture a recording is to ask for one when you launch the JVM. Add -XX:StartFlightRecording to your java command:

1
java -XX:StartFlightRecording=duration=60s,filename=myapp.jfr,settings=profile -jar myapp.jar

This records for 60 seconds and writes myapp.jfr to the working directory. Two settings templates ship with the JDK:

  • settings=default — <1% overhead, fine to leave running indefinitely
  • settings=profile — <2% overhead, more sampling detail, what you want for a focused profiling session

For a longer-running “black box” recording that always has the last few hours of data on disk:

1
java -XX:StartFlightRecording=disk=true,maxage=6h,settings=default -jar myapp.jar

Capture a recording on a running JVM

Often you don’t want to restart the process — you want to attach to a JVM that’s already running and capture a slice. That’s what jcmd is for. First, find the process ID (PID):

1
jcmd -l

Then start, dump, and stop a recording on that PID:

1
2
3
4
5
6
7
8
9
10
11
# Start a 2-minute profiling recording on PID 12345
jcmd 12345 JFR.start name=debug settings=profile duration=2m filename=/tmp/debug.jfr

# Check what recordings are active
jcmd 12345 JFR.check

# Dump the current state of an in-progress recording without stopping it
jcmd 12345 JFR.dump name=debug filename=/tmp/snapshot.jfr

# Stop a recording explicitly (otherwise it stops at the duration)
jcmd 12345 JFR.stop name=debug

The JFR.dump trick is the one I reach for most often: keep a continuous low-overhead recording running, and when something interesting happens (a slow request, a memory spike), dump the in-flight buffer to a file for analysis. You get the events leading up to the moment, not just events from when you noticed.

View the result in JDK Mission Control

A .jfr file is a binary log of events — you need a viewer. The canonical one is JDK Mission Control (JMC):

  • Download from Adoptium or jdk.java.net/jmc — it’s a separate download from the JDK itself.
  • Open the .jfr file. JMC’s Automated Analysis Results tab is the one to read first — it scans the recording and surfaces likely problems with traffic-light severity (long GC pauses, lock contention, thread hot spots, allocation pressure).
  • From there, dive into the per-area pages: Java Application for method profiling, Memory for allocations and GC, Threads for contention and parking, Environment for CPU and OS-level events.

If you just want a quick text dump without firing up a graphical interface, the JDK ships a jfr command-line tool:

1
2
jfr summary myapp.jfr           # event counts and recording metadata
jfr print --events CPULoad myapp.jfr   # print all events of a given type

IntelliJ IDEA Ultimate also opens .jfr files directly with a built-in viewer if you’d rather not install JMC.

When to reach for it

JFR shines for the questions that a debugger or a print statement can’t answer cheaply:

  • “Why does p99 latency spike every few minutes?” (p99 = the slowest 1% of requests) — look at the GC Pauses view.
  • “Which method is the CPU actually spending time in?” — Method Profiling sampler view.
  • “Why is this app allocating so much?” — Allocation view, grouped by class and stack trace.
  • “Are my threads stuck?” — Thread Park and Java Monitor Wait events.

It’s not a replacement for application performance monitoring (APM) tools like Datadog or New Relic, or for distributed tracing — JFR sees a single JVM, not a whole fleet. But for a deep look at what one process is doing, with overhead low enough to leave it running in production, nothing else in the Java ecosystem comes close. 🚀

Posted in java | Comments Off on Java Flight Recorder: a profiler that’s already in your JVM

Check which database object depends on (has reference to) your table

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT R.TABLE_NAME
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE u
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS FK
    ON U.CONSTRAINT_CATALOG = FK.UNIQUE_CONSTRAINT_CATALOG
    AND U.CONSTRAINT_SCHEMA = FK.UNIQUE_CONSTRAINT_SCHEMA
    AND U.CONSTRAINT_NAME = FK.UNIQUE_CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE R
    ON R.CONSTRAINT_CATALOG = FK.CONSTRAINT_CATALOG
    AND R.CONSTRAINT_SCHEMA = FK.CONSTRAINT_SCHEMA
    AND R.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
WHERE
-- THIS IS WHERE YOUR INTEREST IS (YOUR TABLE)
U.COLUMN_NAME = 'THE_COLUMN_NAME'
AND U.TABLE_CATALOG = 'THE_DB_NAME'
AND U.TABLE_SCHEMA = 'THE_SCHEMA_NAME'
AND U.TABLE_NAME = 'THE_TABLE_NAME'
Posted in Database, PostgreSQL | Comments Off on Check which database object depends on (has reference to) your table

Postgres function to devide-and-conquer (iterate) your big query

Create a postgres function to devide-and-conquer (iterate) your big query

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
TRUNCATE TABLE YOUR_NEW_BIG_TABLE;

DROP FUNCTION IF EXISTS pg_iterator();

CREATE OR REPLACE FUNCTION pg_iterator()
  RETURNS void AS
$BODY$
DECLARE
    vOffsetRecord INT;
    vTotal INT;
    vLimit INT;
    vOffset INT;
BEGIN
   
    -- How many?
    -- select count(*) INTO currentRecord from YOUR_BIG_TABLE; -- 346,879,848
    vTotal := 346879848;
    --  vTotal := 5000;
    vLimit  := 100000;
    vOffset :=0;
   
    RAISE NOTICE 'DEBUG vTotal : %', vTotal;
    RAISE NOTICE 'DEBUG vLimit : %', vLimit;
    RAISE NOTICE 'DEBUG vOffset: %', vOffset;

    LOOP
        IF (vOffset >=  vTotal) THEN
            EXIT;
        END IF;
        EXECUTE format('INSERT INTO YOUR_NEW_BIG_TABLE (id, language, hash) SELECT id, language, hash FROM YOUR_BIG_TABLE ORDER BY id LIMIT %s OFFSET %s;', vLimit, vOffset);
        RAISE NOTICE 'DEBUG vOffset: %', vOffset;
        vOffset := vOffset + vLimit;
    END LOOP;
   
END$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION pg_iterator()
  OWNER TO postgres;

SELECT pg_iterator();
Posted in Database, PostgreSQL | Comments Off on Postgres function to devide-and-conquer (iterate) your big query

Crontab header

1
2
3
4
5
6
# minute (0-59),
# |      hour (0-23),
# |      |       day of the month (1-31),
# |      |       |       month of the year (1-12),
# |      |       |       |       day of the week (0=Sunday 1=Monday 2=Tuesday 3=Wednesday 4=Thursday 5=Friday 6=Saturday).
# |      |       |       |       |       commands
Posted in Bash, Linux | Comments Off on Crontab header

Add user in mysql

The classic three-liner for adding a MySQL user, run from a mysql shell connected as root or another account with the CREATE USER privilege. Replace each placeholder with your own value.

1
2
3
CREATE USER 'YOUR_USER_NAME'@'CONNECTING_FROM_WHERE' IDENTIFIED BY 'THIS_USER_PASSWORD';
GRANT ALL PRIVILEGES ON *.* TO 'YOUR_USER_NAME'@'CONNECTING_FROM_WHERE' WITH GRANT OPTION;
FLUSH PRIVILEGES;

The host part — CONNECTING_FROM_WHERE — is the bit most people get wrong on the first try. It tells MySQL which client addresses are allowed to authenticate with this account. Common values:

  • ‘%’ — any host (use sparingly)
  • ‘localhost’ — connecting via a Unix socket on the same box
  • ‘127.0.0.1’ — connecting via TCP loopback (different account from ‘localhost’ — see the gotchas below)
  • ‘10.0.%.%’ — a subnet
  • ‘app-server.example.com’ — a specific hostname

A few useful additions.

Don’t grant ALL ON *.* with GRANT OPTION to an app user. The grant above gives this user everything on every database, plus the ability to hand those privileges to other users. That’s effectively superuser. For an application account you almost always want a much tighter grant — restrict to the one database the app uses, and drop WITH GRANT OPTION:

1
2
CREATE USER 'myapp'@'%' IDENTIFIED BY 'a-strong-password';
GRANT SELECT, INSERT, UPDATE, DELETE ON myappdb.* TO 'myapp'@'%';

Use GRANT ALL ON myappdb.* if your app needs schema changes (DDL) too. Reserve WITH GRANT OPTION for accounts whose actual job is to manage other users — not your application’s connection pool.

FLUSH PRIVILEGES isn’t needed here. One of the longest-running pieces of MySQL folklore. FLUSH PRIVILEGES is only needed when you modify the underlying mysql.user tables directly with INSERT/UPDATE. CREATE USER and GRANT already update the in-memory privilege tables, so the flush is a no-op. Harmless to leave in, but if you’ve been told it’s mandatory — it isn’t.

MySQL 8: the auth plugin changed. MySQL 8.0 made caching_sha2_password the default authentication plugin (it was mysql_native_password in 5.7). Most modern client libraries handle it fine, but older drivers or short-lived containers connecting to MySQL 8 sometimes throw “Plugin caching_sha2_password could not be loaded”. Two ways out: upgrade the client, or fall back to the old plugin per-user:

1
2
CREATE USER 'legacy_app'@'%'
  IDENTIFIED WITH mysql_native_password BY 'a-strong-password';

localhost and 127.0.0.1 are two different host strings. A user defined as ‘foo’@’localhost’ can only connect over the Unix socket. A user defined as ‘foo’@’127.0.0.1’ can only connect over TCP loopback. They’re separate account rows in mysql.user. If you wonder why your app works in mysql but fails from a script that uses –protocol=tcp, this is usually it. Create both rows, or use ‘%’ if you don’t care about the path.

Companion commands you’ll want next.

1
2
3
4
5
6
7
8
9
10
11
-- Change a user's password
ALTER USER 'myapp'@'%' IDENTIFIED BY 'a-new-password';

-- See what a user is allowed to do
SHOW GRANTS FOR 'myapp'@'%';

-- List all users and the host pattern they're tied to
SELECT USER, host FROM mysql.user;

-- Remove a user (drops every host pattern; for one specific host use 'name'@'host')
DROP USER 'myapp'@'%';

And of course: if you’re choosing a database tool today and aren’t already on MySQL, take a look at MariaDB (a drop-in fork that follows similar SQL) or PostgreSQL (different syntax, but a noticeably more featureful default). For an existing MySQL deployment though, the recipe above is still exactly the right one. 🐬

Posted in MySQL | Comments Off on Add user in mysql

Using grep as highlighter

1
$ grep --color -E '^|pattern1|pattern2' file name
Posted in Bash, Linux | Comments Off on Using grep as highlighter

TCL programming

A reusable expect dispatcher I kept around for running the same kind of operation across a list of servers — untar an index, restart a service, patch a config file. The trick is that the script reads the first command-line argument and dispatches to a same-named proc, so one script holds many small ops:

1
2
3
./script.exp UntarLuceneindexes
./script.exp stopLuceneServices
./script.exp startLuceneServices

That’s the $functionName line at the bottom — it literally calls whatever proc name you passed in. Crude, but very handy when you’re iterating on a runbook.

The script below assumes you’ve set up SSH keys so ssh root@host connects without a password prompt. That keeps secrets out of the script and the shell history.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/expect -f
# Expect dispatcher. Beware: whitespace matters in Tcl.

# Multi-line comments use a set / curly-brace trick:

# set comment {
#     your multi-line comment

# }

# ---------------------------------------------------

# Function definitions
# ---------------------------------------------------

if {[llength $argv] == 0} {
    send_user "Usage: script.exp FUNCTION_NAME\n"
    send_user "Example: script.exp UntarLuceneindexes\n"
    exit 1
}
set functionName [lindex $argv 0]

# Servers used by the Lucene-related procs.

set aLuceneServers {your_server_1 your_server_2 your_server_3}

proc printPass {} {
    send_user "\n\[PASS\]\n"
}

proc printFail {} {
    send_user "\n\[FAIL\]\n"
    exit 1
}

proc simpleTest {} {
    set aProductionServers {your_server_1 your_server_2 your_server_3 your_server_4 your_server_5 your_server_6}
    foreach host $aProductionServers {
        send_user "Processing ... '$host'\n"
        set timeout 60
        spawn ssh root@$host

        send "hostname\r"
        expect $host

        send "uptime\r"
        expect "load average"

        send "exit\r"
    }
}

proc UntarLuceneindexes {} {
    global aLuceneServers
    set sCurrentLuceneTar "index2_20151009.tar.bz2"
    foreach host $aLuceneServers {
        send_user "\n================================================\n"
        send_user "Processing ... '$host'\n"
        send_user "================================================\n"
        set timeout 60
        spawn ssh root@$host

        send "hostname\r"
        expect $host

        send "su - path\r"
        send "pwd\r"
        expect "/home/path"

        send "ls $sCurrentLuceneTar | wc -l\r"
        expect "1"

        send "tar -xjvf $sCurrentLuceneTar &\r"
        send "sleep 2\r"
        send "ps aux | grep index2 | grep tar | wc -l\r"
        send "disown %1\r"
        expect "1"

        send_user "Done processing ... '$host'\n"
    }
}

proc updateDBRef {} {
    set apathServers {your_server_6}
    set newDB "some_db_20150925"
    foreach host $apathServers {
        send_user "\n================================================\n"
        send_user "Processing ... '$host'\n"
        send_user "================================================\n"
        set timeout 60
        spawn ssh root@$host

        send "hostname\r"
        expect $host

        send "su - path\r"
        send "pwd\r"
        expect "/home/path"

        set propsFile "/home/path/path-current/SomeConfig.properties"
        send "grep -v 'com.somecompany.setting.server.db.pathdb2.url=' $propsFile > $propsFile.new\r"
        send "echo 'com.somecompany.setting.server.db.pathdb2.url=jdbc:postgresql://127.0.0.1:5432/$newDB' >> $propsFile.new\r"
        send "mv $propsFile.new $propsFile\r"

        send_user "Done processing ... '$host'\n"
    }
}

proc stopLuceneServices {} {
    global aLuceneServers
    foreach host $aLuceneServers {
        send_user "\n================================================\n"
        send_user "Processing ... '$host'\n"
        send_user "================================================\n"
        set timeout 60
        spawn ssh root@$host

        send "hostname\r"
        expect $host

        send "service lucene stop\r"
        expect {
            "stopped PID"           { printPass }
            "lucene is not running" { printPass }
            timeout                 { printFail }
        }

        send_user "Done processing ... '$host'\n"
    }
}

proc startLuceneServices {} {
    global aLuceneServers
    foreach host $aLuceneServers {
        send_user "\n================================================\n"
        send_user "Processing ... '$host'\n"
        send_user "================================================\n"
        set timeout 60
        spawn ssh root@$host

        send "hostname\r"
        expect $host

        send "service lucene start\r"
        expect {
            "started PID" { printPass }
            timeout       { printFail }
        }

        send_user "Done processing ... '$host'\n"
    }
}

# ---------------------------------------------------

# Run
# ---------------------------------------------------

set timeout 60
log_file -noappend expect.log  ;# default is append; -noappend overwrites

$functionName

Tcl or Expect? The post title says Tcl, but almost every interesting line above — spawn, expect, send, send_user, log_file, the #!/usr/bin/expect -f shebang — comes from Expect, an extension that sits on top of Tcl and lets you drive interactive programs (SSH, telnet, vendor CLIs) by pattern-matching on their output. Pure Tcl is the language; Expect is what makes a script like this one possible. 🤖

Use SSH keys, not expect-and-send-password. The original version of this script had blocks like expect “*assword: “ followed by send “YOUR_SERVER_PASSWORD\r”. That works, but it puts a plaintext password in your script and your shell history. The cleaner answer is SSH keypair auth — the script above assumes that’s already set up, so the password block disappears entirely. Reserve the expect-and-send-password pattern for the cases where it’s truly unavoidable: old network gear, vendor CLIs, devices that don’t accept keys.

You don’t always need Expect. If all you need is to run the same shell command across a list of servers, plain SSH in a loop is simpler and easier to debug:

1
2
3
for host in your_server_1 your_server_2 your_server_3; do
  ssh "$host" "service lucene stop"
done

For larger fleets, parallel-ssh (pssh) or ansible -m shell -a “…” mygroup are usually saner. Expect earns its keep when you have to navigate an interactive prompt that doesn’t accept piped commands — confirm dialogs, paged output, vendor consoles. 💡

Posted in Linux, TCL/Expect | Comments Off on TCL programming

Simple unit test is bash file

Consider the following 3 files:

1. shellTestFramework.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#!/bin/bash
# Copyright (c) Ronald Pringadi

# Before each Test
function setUpTest(){
    #"Please overwrite this function on your unit test. Something that need to be done before each test"
    return 0;
}

function tearDownTest(){
    #"Please overwrite this function on your unit test. Something that need to be done after each test"
    return 0;
}


# Helping assertion
function assertEqual(){
    if [ "$1" == "$2" ]; then
        echo "`caller 0`. PASS"
    else
        echo "`caller 0`. FAIL. $1!=$2"
    fi
}

# Helping assertion
function assertNotEqual(){
    if [ "$1" != "$2" ]; then
        echo "`caller 0`. PASS"
    else
        echo "`caller 0`. FAIL. $1==$2"
    fi
}

# To run all test.
# Will run 'setUpTest()' before each test.
# Will run 'tearDownTest()' after each test.
function runAllTest(){
    array=($(compgen -A function |grep -i test))
    for i in "${array[@]}"
    do
       if [ "$i" != "setUpTest" ] && [ "$i" != "runAllTest" ] && [ "$i" != "tearDownTest" ]; then
        echo "`setUpTest`"
        echo "`$i`"
        echo "`tearDownTest`"
       fi
    done
}

2. osdetector.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/bin/bash
# Copyright (c) Ronald Pringadi

# Returns String ("ubuntu", "censtos", "redhat", "unknown")
function detectAnyOS(){
    OS="unknown"
   
    DETECT="ubuntu"
    if [ `detectSpecificOS "$DETECT"` -eq 1 ] ; then
        echo $DETECT
        return 0
    fi
   
    DETECT="centos"
    if [ `detectSpecificOS "$DETECT"` -eq 1 ] ; then
        echo $DETECT
        return 0
    fi
   
    DETECT="Red Hat"
    if [ `detectSpecificOS "$DETECT"` -eq 1 ] ; then
        echo "redhat"
        return 0
    fi
   
    DETECT="RHEL"
    if [ `detectSpecificOS "$DETECT"` -eq 1 ] ; then
        echo "redhat"
        return 0
    fi
}

# Input String ("ubuntu", "Centos", "RedHat")
# Returns String "1"=found, "0"=not found
function detectSpecificOS(){
    DETECT=$1
    IS_FOUND=`cat /etc/*-release |grep -i "$DETECT"|wc -l`
    if [ $IS_FOUND -gt 0 ]; then
        echo "1"
    else
        echo "0"
    fi
}

# Returns String ("6", "5.5", "4")
function detectOSVersion(){
    # Works for ubuntu
    VERSION=`cat /etc/*-release |grep 'DISTRIB_RELEASE='|grep -o '[0-9|.]\+'|head -1`
    if [ "$VERSION" != "" ]; then
        echo $VERSION
        return 0
    fi
   
    # Works for Centos
    VERSION=`cat /etc/*-release |grep ' release '|grep -o '[0-9|.]\+'|head -1`
    if [ "$VERSION" != "" ]; then
        echo $VERSION
        return 0
    fi
   
    # Final resort
    VERSION=`cat /etc/*-release |grep -i 'ubuntu\|red hat\|centos'| grep -o '\ [0-9|.]\+'|head -1`
    if [ "$VERSION" != "" ]; then
        echo $VERSION
        return 0
    fi
   
}


# Returns String ("6", "5", "4")
function detectOSMajorVersion(){
    VERSION=`detectOSVersion`
    MAJOR_VERSION=`echo "$VERSION" |grep -o '[0-9]\+'|head -1`
    echo "$MAJOR_VERSION"
}

# Input String OS  ("ubuntu", "Centos", "RedHat")
# Input String OSVersion name
# Returns String "1"=supported, "0"=not supported
function isOSSupported(){
    SUPPORTED="0"
    OS=`echo "$1"| tr '[:upper:]' '[:lower:]'`
    VERSION="$2"
    MAJOR_VERSION=`echo "$VERSION" |grep -o '[0-9]\+'|head -1`
    if [ "$OS" == "ubuntu" ]; then
        if [ "$MAJOR_VERSION" == "12" ] || [ "$MAJOR_VERSION" == "13" ] || [ "$MAJOR_VERSION" == "14" ]; then
            SUPPORTED="1"
        fi
    fi
    if [ "$OS" == "red hat" ] || [ "$OS" == "redhat" ] || [ "$OS" == "centos" ]; then
        if [ "$MAJOR_VERSION" == "6" ]; then
            SUPPORTED="1"
        fi
    fi
    echo $SUPPORTED
}

3. osdetector.test.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/bin/bash
# Copyright (c) Ronald Pringadi
my_dir="$(dirname "$0")"
source "$my_dir/osdetector.sh"
source "$my_dir/shellTestFramework.sh"


# Before each Test
function setupTest(){
    RELEASE_CONTENT="Ubuntu 14.04.3 LTS"
    echo "$RELEASE_CONTENT">/etc/test-release
}

function adetectSpecificOSTest(){
    DETECT="Ubuntu"
    RESULT=`detectSpecificOS $DETECT`
    assertEqual "$RESULT" "1"
   
    DETECT="Centos"
    RESULT=`detectSpecificOS $DETECT`
    assertEqual "$RESULT" "0"
}


function detectAnyOSTest(){
    RESULT=`detectAnyOS`
    assertEqual "$RESULT" "ubuntu"
    assertNotEqual "$RESULT" "centos"
}

function detectOSAndOsVersionTest(){   
    RELEASE_CONTENT="Ubuntu 14.04.3 LTS"
    echo "$RELEASE_CONTENT" > /etc/test-release
    RESULT=`detectOSVersion`
    assertEqual "$RESULT" "14.04.3"
    RESULT=`detectOSMajorVersion`
    assertEqual "$RESULT" "14"
    RESULT=`detectAnyOS`
    assertEqual "$RESULT" "ubuntu"
   
    RELEASE_CONTENT="CentOS release 6.6 (Final)"
    echo "$RELEASE_CONTENT" > /etc/test-release
    RESULT=`detectOSVersion`
    assertEqual "$RESULT" "6.6"
    RESULT=`detectOSMajorVersion`
    assertEqual "$RESULT" "6"
    RESULT=`detectAnyOS`
    assertEqual "$RESULT" "centos"
   
    RELEASE_CONTENT="CentOS Linux release 7.1.1503 (Core)"
    echo "$RELEASE_CONTENT" > /etc/test-release
    RESULT=`detectOSVersion`
    assertEqual "$RESULT" "7.1.1503"
    RESULT=`detectOSMajorVersion`
    assertEqual "$RESULT" "7"
    RESULT=`detectAnyOS`
    assertEqual "$RESULT" "centos"
   
    RELEASE_CONTENT="Red Hat Enterprise Linux Server release 6.3 (Santiago)"
    echo "$RELEASE_CONTENT" > /etc/test-release
    echo "$RELEASE_CONTENT" >> /etc/test-release
    RESULT=`detectOSVersion`
    assertEqual "$RESULT" "6.3"
    RESULT=`detectOSMajorVersion`
    assertEqual "$RESULT" "6"
    RESULT=`detectAnyOS`
    assertEqual "$RESULT" "redhat"
}

function isOSSupportedTest(){  
   
    RESULT=`isOSSupported "ubuntu" "11"`
    assertEqual "$RESULT" "0"
   
    RESULT=`isOSSupported "ubuntu" "12"`
    assertEqual "$RESULT" "1"
   
    RESULT=`isOSSupported "ubuntu" "13"`
    assertEqual "$RESULT" "1"
   
    RESULT=`isOSSupported "ubuntu" "14"`
    assertEqual "$RESULT" "1"
   
    RESULT=`isOSSupported "ubuntu" "15"`
    assertEqual "$RESULT" "0"
       
    RESULT=`isOSSupported "redhat" "5"`
    assertEqual "$RESULT" "0"
   
    RESULT=`isOSSupported "redhat" "6"`
    assertEqual "$RESULT" "1"
   
    RESULT=`isOSSupported "redhat" "7"`
    assertEqual "$RESULT" "0"
   
    RESULT=`isOSSupported "red hat" "5"`
    assertEqual "$RESULT" "0"
   
    RESULT=`isOSSupported "red hat" "6"`
    assertEqual "$RESULT" "1"
   
    RESULT=`isOSSupported "red hat" "7"`
    assertEqual "$RESULT" "0"
       
    RESULT=`isOSSupported "centos" "5"`
    assertEqual "$RESULT" "0"
   
    RESULT=`isOSSupported "centos" "6"`
    assertEqual "$RESULT" "1"
   
    RESULT=`isOSSupported "centos" "7"`
    assertEqual "$RESULT" "0"
   
    RESULT=`isOSSupported "Fedora" "50"`
    assertEqual "$RESULT" "0"
   
}


runAllTest
Posted in Bash | Comments Off on Simple unit test is bash file

Multithreading in Java using ThreadPoolExecutor

ThreadWorker is your custom class.

1
2
3
4
5
6
7
8
9
try {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(MAX_THREAD_SIZE);
for (int i = 1; i Random randomGenerator = new Random();
executor.submit(new ThreadWorker("worker" + i, randomGenerator.nextInt(10)));
LOG.info(i);
}
} catch (Exception e) {
LOG.error("Hmm something is not right.", e);
}
Posted in java | Comments Off on Multithreading in Java using ThreadPoolExecutor