7/03/2017

Run OpenGrok using docker

  Thanks to Docker. It makes us to use a lot of web service easier.  In the past, we would like to install OpenGrok, we have to install java, tomcat, etc..
  Now, it is easy to run OpenGrok if you know Docker. The steps are quietly simple, please checkout the below steps:

Step1 : Install Docker
$ apt-get update -qq
$ apt-get install -qqy \
  apt-transport-https \
  ca-certificates \
  curl \
  lxc \
  iptables

$ curl -sSL https://get.docker.com/ | sh
$ usermod -a -G docker  $USER

Step2: Pull the image from my Dockerhub .
$  docker pull tzutalin/opengrok
Alternatively, you can check out my Dockerfile on Github, and build the image from scratch.


Step3: Run the OpenGrok using the below commands. Rember to replace <XXXX> with your source directory.

$ docker run -t -d --name=opengrok -v [Absolute path]:/src -p 8080:8080 tzutalin/opengrok
tzutalin/opengrok container will periodically update the index. So you didn't need to update index by yourself.

Open your browser http://0.0.0.0:8080/source/. The result looks like :


Reference: https://github.com/tzutalin/docker/tree/master/OpenGrok

6/23/2017

手機當行車紀錄器

  前陣子換手機, 又多了一隻Android舊手機, 剛好最近也買了一個車用手機架, 就把我舊手機當行車紀錄器. 但我在google play 上, 都沒有用到喜歡的行車紀錄器app, 因此自己寫花了幾個周末寫了一個可以在背景錄影、記錄移動軌跡、並打開就馬上錄的的行車紀錄器app. 希望能幫助到一些人.
App可以到https://play.google.com/store/apps/details?id=com.dayun.driverecorder&hl=zh_TW 下載
截圖如下:


車用手機架則可以上PCHome買
https://24h.pchome.com.tw/store/DEADCG

6/19/2017

Running Qt GUI apps with Docker

  In the past three weeks, I was playing around Docker and CI/CD pipeline, and I was getting familiar with Docker and its toolbox. In the meanwhile, I tried to dockerize most of my own applications, tools, and algorithms which can run, build, or test inside Docker container.
  Here is one of my projects on Github, it's called labelImg which was written in Python + PyQt. You can follow the below videos or the snippet of the commands to run Python + PyQt GUI application inside the Docker container.

Step1: Clone the source code from Github
$ git clone https://github.com/tzutalin/labelImg.git

Step2: Pull the Docker image which is based on Python + PyQt. You can refer to its Dockerfile.
$ docker pull tzutalin/py2qt4
Step3: Get started with the application and container
docker run -it \
--user $(id -u) \
-e DISPLAY=unix$DISPLAY \
--workdir=$(pwd) \
--volume="/home/$USER:/home/$USER" \
--volume="/etc/group:/etc/group:ro" \
--volume="/etc/passwd:/etc/passwd:ro" \
--volume="/etc/shadow:/etc/shadow:ro" \
--volume="/etc/sudoers.d:/etc/sudoers.d:ro" \
-v /tmp/.X11-unix:/tmp/.X11-unix \
tzutalin/py2qt4
Then, you will see that we can run GUI inside the container.

If you want to get more detailed information, you can check out the following video.

6/05/2017

Create insecure and private docker resistry

Pre-requirements on the host and clients:

Installed Docker and Docker-compose

Host

Create a folder for Docker registry
$ mkdir docker-registry;cd $_;mkdir data
Create a  docker-compose.yml for docker-compose.
registry:
  restart: always
  image: registry:2
  ports:
    - 5000:5000
  environment:
    REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
  volumes:
    - ./data:/data
Get any image from the hub and tag it to point to your registry:
$ docker pull ubuntu && docker tag ubuntu localhost:5000/ubuntu
Then, push it to your registry:
$ docker push localhost:5000/ubuntu

Clients

Because the above setting is an insecure and private registry. You need to add --insecure-registry to /etc/default/docker as below.
DOCKER_OPTS="$DOCKER_OPTS --insecure-registry=HOST:5000"
Afterward, you can pull the image from host server by running the below command
$ docker pull HOST:5000/ubuntu

5/12/2017

Setup Jenkins on Ubuntu


Installation
wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins

Upgrade

Once installed like this, you can update to the later version of Jenkins (when it comes out) by running the following commands:
sudo apt-get update
sudo apt-get install jenkins

Setting
Add user jenkins to your username group to allow it to read and write the your folder
sudo usermod -a -G YOUR_USERNAME jenkins
If you would like to change the port, you can edit the /etc/default/jenkins to replace the line
HTTP_PORT=8080
by
HTTP_PORT=8880
sudo service jenkins restart 
Then, try to open 0.0.0.0:8880, you will see authentication page. Now, you need to enter the password, you should get /var/libs/jenkins/secrets/ to see the password.


After that, you can go to a configuration page to set up your env variable.
http://localhost:8880/configure

For example, if you are using Android and gradle to build, you should setup ANDROID_HOME, ANDROID_NDK_HOME,  and JAVA_HOME as env variable.
  ANDROID_HOME : /home/darrenl/tools/android-sdk-linux
ANDROID_NDK_HOME
JAVA_HOME = /usr/lib/jvm/java-1.8.0-openjdk-amd64

Extra nice plugins

* Locale Plugin
* Email Extension Plugin
* Role Strategy Plugin

Run Jenkins with Do

Please refer to
https://github.com/tzutalin/docker/tree/master/Jenkins
https://github.com/jenkinsci/docker/blob/master/Dockerfile
https://github.com/maxfields2000/dockerjenkins_tutorial/tree/master/tutorial_07


Other references
Jenkins: Change Workspaces and Build Directory Locations
How to change build periodic
Jenkis pipeline with docker
Use email-plugin
Use email-plugin2
Create a test smtp server 
Simple project which use travis

5/02/2017

flock c/c++ Sample Code


flock() is to apply or remove an advisory lock on an open file. It is available on most of OS, and I have tried it and it can work on Linux and Android OS. It can resolve the problem which muti-processes access the same file.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/file.h>
#include <iostream>

void lockUnLock() {
  int fd, i;
  char path[] = "test.txt";
  fd = open(path, O_WRONLY | O_CREAT);
  if (fd != -1) {
    std::cout << "open file " << path << std::endl;
    std::cout << "Please input a number to lock the file" << path << std::endl;
    scanf("%d", &i);
    if (flock(fd, 2) == 0) {
      std::cout << "The file was locked " << std::endl;
    } else {
      std::cout << "The file was not locked " << std::endl;
    }
    std::cout << "please input a number to unlock the file " << std::endl;
    scanf("%d", &i);
    if (flock(fd, 8) == 0) {
      std::cout << "The file was unlocked. " << std::endl;
    } else {
      std::cout << "The file was no unlocked. " << std::endl;
    }
    close(fd);
  } else {
    std::cout << "Cannot open file " << path << std::endl;
  }
}

int main() {
  lockUnLock();
  return 0;
}

Src code: : https://gist.github.com/tzutalin/ad4277e8ee24392b9ea23765452d6528
Note: You can also use semget/semop to do that, but Android Bionic does not support that..

3/27/2017

JNI Should I call DeleteLocalRef

In JNI, FindClass method returns a local reference.
Sample code:
 jclass arrayListClass = env->FindClass("java/util/ArrayList");
 ....
 env->DeleteLocalRef(arrayListClass);
Is it necessary to call DeleteLocalRef ? In fact, it is unnecessary to call DeleteLocalRef in most of the cases. However, JNI has a limited (but configurable) number of local references available. So, the best practice is to delete if the reference is created in a loop

3/21/2017

C++ Version header template

Make a note for the usage of my version.hpp.
I can not only get the string of version from LIB_VERSION but also get major/minor/patch versions separately.
#pragma once
//  A *string*, LIB_VERSION, in the form "x.y.[z]"
//  where x is the major version number,
//  y is the minor version number,
//  and z is the patch level

#define LIB_VERSION_MAJOR    0
#define LIB_VERSION_MINOR    4
#define LIB_VERSION_PATCH    12

#define AUX_STR_EXP(__A)     #__A
#define AUX_STR(__A)         AUX_STR_EXP(__A)

#define LIB_VERSION          AUX_STR(LIB_VERSION_MAJOR) "."
        \ AUX_STR(LIB_VERSION_MINOR) "." 
        \ AUX_STR(LIB_VERSION_PATCH)
  

Besides, I wrote a python script to update the patch.
REG_VERSION_LINE = r"ASUS_VISION_LIB_VERSION_PATCH.  +([0-9:]+)"

def changeSoVersion(versionFile):
    # Read in the file
    filedata = None
    with open(versionFile, 'r') as file:
        filedata = file.read()
        matches = re.finditer(REG_VERSION_LINE, filedata)
        for matchNum, match in enumerate(matches):
            oldVersion = match.group(1)
            newVersion = str(int(match.group(1)) + 1)
            print oldVersion
            print newVersion
            if len(oldVersion) > 0 and len(newVersion) > 0:
                filedata = filedata.replace(oldVersion, newVersion)

    # Write the file out again
    with open(versionFile, 'w') as file:
        file.write(filedata)
  

3/03/2017

什麼是 closed-form solution and numerical solution

最近正在學解決multivariate analysis和optimalization問題, 遇到一個英文名詞close-form solution. close-form solution中文文獻稱閉合解. 白來來說就是給予一些觀察到的資料, 然後問題可以用函數和數學運算來表示, 這樣的方程式就是close-form solution or numerical solution, 差別在於一個是exact, 一個是approximate. 舉例來說, 在Linear regression中的 Least square equation就是close-form solution, Non-linear regression是numerical solution.

2/05/2017

[Interview type questions] Task sequence arragnement

Given a task sequence and the cool down time(k), rearrange the task sequence such that the execution time is minimal.
Solution:
 public static void main(String[] args) {
  char[] task = findBestTaskArrangement(String.valueOf("AAABBB").toCharArray(), 2);
  System.out.println(task);
  System.out.println("Total time: " + computeTatalTaskTime(task, 2));
  // ABABAB
  // Total time:8
 }
 
 public static char[] findBestTaskArrangement(char[] tasks, int k) {
  int n = tasks.length;
  Map<Character, Integer> map = new HashMap<>();
  for (char task : tasks) {
   map.put(task, map.getOrDefault(task, 0) + 1);
  }

  PriorityQueue<Task> queue = new PriorityQueue<>(new Comparator<Task>() {

   @Override
   public int compare(Task a, Task b) {
    return b.frequency - a.frequency;
   }
  });

  for (Map.Entry<Character, Integer> entry : map.entrySet()) {
   queue.offer(new Task(entry.getKey(), entry.getValue()));
  }
  
  tasks = new char[n];
  int i = 0;
  while (!queue.isEmpty()) {
   int c = 0;
   List<Task> nextRoundTask = new ArrayList<>();
   while(c++ < k && !queue.isEmpty()) {
    Task task = queue.poll();
    task.frequency--;
    // Locate the next empty slot
    tasks[i++] = task.id;
    if (task.frequency > 0)
     nextRoundTask.add(task);
   }
   for (Task task : nextRoundTask) {
    queue.offer(task);
   }
  }

  return tasks;
 }

 // helper class
 public static class Task {
  char id;
  int frequency;

  Task(char i, int f) {
   id = i;
   frequency = f;
  }
 }

 public static int computeTatalTaskTime(char[] tasks, int k) {
  HashMap<Character, Integer> taskLastTimeMap = new HashMap<>();
  int currTime = 0;
  for (char task : tasks) {
   if (taskLastTimeMap.containsKey(task)) {
    int exceptedTime = taskLastTimeMap.get(task) + k + 1;
    if (exceptedTime > currTime) {
     currTime = exceptedTime;
    } else
     currTime++;
   } else {
    currTime++;
   }
   taskLastTimeMap.put(task, currTime);
  }
  return currTime;
 }