Monday, October 17, 2016

VNC Viewer

I recently built a desktop for development in my company’s CORP network. By using VNC, I can access the same Gnome session even from home. Just simply connect to VPN, and start a vnc viewer, I can resume what I do at office.
I have a CentOS 6 on my development desktop. I installed RPM pacakages: vnc-server. (TODO: Details about setting up VNC server.)
I tried TigerVNC Viewer, but it was really bad, especially F8 menu key because I use Eclipse, F8 is used a lot when you are debugging. And there is not a pop-up menu bar like VirtualBox when you are in full-screen mode.
RealVNC satisfies all my requirements about VNC:
  • A menu bar
  • Better configuration UI on Windows 7
  • I can write a script to start VNC viewer
    through SSH tunnel make the viewer goes into full-screen mode on my secondary display automatically.
In CORP network, just click the VNC button on Windows’ taskbard, type the password, the viewer is in full-screen mode on my secondary display.
set -e

shutdown() {
  if [ -n "$tunnel_pid" ]; then
    kill $tunnel_pid

trap shutdown EXIT

ssh -N -L 5902:localhost:5902 mydev.desktop &

~/apps/bin/VNC-Viewer-5.2.1-Windows-64bit.exe \
  --Monitor='\\.\Display2' \
  --FullScreen=1 \
I also installed cygwin on Windows so that I could use OpenSSH. The script can clean up the SSH tunnel once the script quits.
At home, the network connection is slow. And that script will fail because RealVNC gets timeout. I didn’t find how to make RealVNC wait for a longer time. I just simply run SSH tunnel and viewer separately in different screens of GNU Screen in a Cygwin terminal.
I chose JPEG encode for better performance when I at home.

Sunday, October 9, 2016

Don't set limit nofile to unlimited

After I set nofile to unlimited in /etc/security/limits.d/90-nproc.conf like this,
*          hard    nproc     unlimited
*          hard    nofile    unlimited

*          soft    nproc     unlimited
*          soft    nofile    unlimited
I could not boot into Gnome on my VM running CentOS 6.8 any more. Even I could switch to a terminal using ctrl-alt-F2, I seemed not be able to log in. I reboot the VM using a live-cd ISO. Then mount the file system, after setting to 32K as below, reboot it, the problem was fixed.
*          -    nproc     unlimited
*          -    nofile    32768
# find out the logical volume of the hard drive
fdisk -l

# mount the logical volume
mkdir /mnt/hd
mount /dev/mapper/Volume-lv_root /mnt/hd
vi /mnt/hd/etc/security/limits.d/90-nproc.conf

Monday, September 12, 2016

Gradle show dependencies of the specified configuration

I record the method here in case I forget how to show the dependencies for ONLY one configuration like runtime again.
  • Show dependencies for one configuration ONLY: ./gradlew dependencies --configuration runtime
  • Show a task’s arguments: ./gradlew help --task dependencies

Record Request and Reponse of HTTP Samplers in JMeter

  • Add “Simple Data Writer”
  • Give the file name like “result.xml”
  • Click Configure button.
  • Check the radio buttons for
    • Save As XML
    • Save URL
    • Save Response Data (XML)
  • Start the jmeter test
  • Check the XML file
  • If you stop jmeter, then start another run, the requests and responses in the new run will be appended to the XML file.
<httpSample t="17" lt="17" ts="1473705874608" s="true" lb="Profile Request" rc="200" rm="OK" tn="Profile (year) 1-1" dt="text" by="253" ng="1" na="2">
  <responseData class="java.lang.String">...</responseData>

Friday, September 9, 2016

Make Spark read Teradata directly.

Spark SQL supports read JDBC resource, but the paragraph in the latest 2.0 document is not really helpful:
The JDBC driver class must be visible to the primordial class loader on the client session and on all executors. This is because Java’s DriverManager class does a security check that results in it ignoring all drivers not visible to the primordial class loader when one goes to open a connection. One convenient way to do this is to modify on all worker nodes to include your driver JARs.
I wrote this blog to explain how to run against Teradata database:
  • in spark-shell and YARN-cluster mode
  • spark-submit and YARN-cluster mode

spark-shell and YARN mode

--conf spark.executor.extraClassPath=./tdgssconfig- \
--driver-class-path $LIB_DIR/tdgssconfig-$LIB_DIR/terajdbc4- \
  • for executor.extraClassPath, the path is the current directory ./, which is where YARN starts the executor.
  • for --driver-class-path, “$LIB_DIR” is the directory where those jdbc driver jars live, it is on the host where you run spark-shell.

spark-submit and YARN-cluster mode

--conf spark.executor.extraClassPath=./tdgssconfig- \
--driver-class-path ./tdgssconfig- \
--jars $LIB_DIR/tdgssconfig-,$LIB_DIR/terajdbc4-,<other jars>


Two differences:
  • In spark-shell, you don’t have to put Terdata jdbc driver jars in --jars, because --driver-class-path already does. If you put them in --jars, it doesn’t hurt. But in spark-submit, you have to add them in --jars.
  • In spark-submit, --driver-class-path uses the current directory ./, not $LIB_IDR in spark-shell.
Lost? Here is why:
  • When you run spark-submit with YARN-cluster mode , the Spark app driver actually runs in a YARN container, not where you type “spark-submit”.
    • --jars makes teradata jdbc driver jars copied to the container directory where the Spark app driver (YARN appMaster) runs.
    • --driver-class-path just declares you need teradata jdbc driver jars. Be the Spark app driver runs in a YARN container, this argument tells the spark app driver JVM where to find the jdbc jars. Because the jars are copied into the YARN container’s directory, to the JVM of spark app driver, the container directory is the current directory.
    • spark-submit actually cand not find the jdbc jars in ./ in --driver-class-path, so the jdbc jars won’t be copied to the YARN container. That is why you have to use --jars to tell spark where to find those jars and ship them to the container.
  • In spark-shell, the spark app driver is started on the host where you type “spark-shell”. So you need to give the full path in --driver-class-path

Friday, May 27, 2016

Bring back google-chrome after upgrading to CentOS 6.8 and Chrome 51.

I don’t know which one is root cause: upgrading to CenOS 6.8 or Chrome 51. I used on to install Google chrome on my CentOS 6 VirtualBox VM. It worked very well until this upgrade. If I ran google-chrome, the window popped up, but it is almost black.
I use the following command to investigate this problem
google-chrome --disable-plugins --disable-extensions --user-data-dir=/tmp/chrome-user-dir --enable-logging --log-level=0
  • disable all plugins and extensions
  • use a new user dir
  • enable logs
Also checking the chrome process --type=gpu-process as parameter
$ ps -ef | grep chrome
bwang  1358  1284  1 10:58 pts/6    00:00:00 /opt/google/chrome/chrome --enable-features=... --disable-features=... --type=gpu-process --channel=1284.0.1688276239 --enable-logging --log-level=0 --window-depth=24 --user-data-dir=/tmp/chrome-user-dir --supports-dual-gpus=false --gpu-driver-bug-workarounds=4,54 --gpu-vendor-id=0x80ee --gpu-device-id=0xbeef --gpu-driver-vendor=Chromium --gpu-driver-version=1.9 --user-data-dir=/tmp/chrome-user-dir --enable-logging --log-level=0 --v8-natives-passed-by-fd --v8-snapshot-passed-by-fd
The log file /tmp/chrome-user-dir/chrome_debug.log shows
[2945:2945:0527/] [.CommandBufferContext.DisplayCompositor-0x3d53365d63c0]GL ERROR :GL_INVALID_ENUM : glTexImage2D: <- error from previous GL command
[23:23:0527/] MessageAttachmentSet destroyed with unconsumed descriptors: 0/1
[2945:2945:0527/] [.CommandBufferContext.CompositorWorker-0x3d53365d6280]GL ERROR :GL_INVALID_ENUM : GLES2DecoderImpl::DoBindTexImage2DCHROMIUM: <- error from previous GL command
[2945:2945:0527/] [.CommandBufferContext.CompositorWorker-0x3d53365d6280]GL ERROR :GL_INVALID_VALUE : ScopedTextureBinder::dtor: <- error from previous GL command
Looks like google-chrome use gpu for acceleration. So the solution is simple google-chrome --disable-gpu brings back chrome on my CentOS 6.8 VM.

Wednesday, May 18, 2016

How to create .epub and .mobi version of Gradle User Guide?

Gradle User Guide is written using docbook, and gradle build already have single HTML and pdf built. But I really want to load it into my kindle. Because docbook supports converting docbook to epub and epub3, I want to build it by myself.
You need to install docbook-xsl. On cygwin, I installed 1.77.1-1
$ cygcheck -c | grep docbook
build-docbook-catalog        1.5-2              OK
docbook-xsl                  1.77.1-1           OK

$ cygcheck -l docbook-xsl | grep epub
You’d better to read epub3/README, which describes the steps how to build a epub eBook from docbook. The command looks like this:
 xsltproc --stringparam base.dir ebook/OEBPS/ --xinclude /usr/share/sgml/docbook/xsl-stylesheets/epub3/chunk.xsl ../gradle/subprojects/docs/build/src/userguide.xml
One thing you need to pay more attention, you must have the last slash of ebook/OEBPS/. The above command will generate mimetype and META-INF in the directory ebook.
$ ls ebook
META-INF/  mimetype  OEBPS/
If you don’t append “/“, the command will create a directory ebook/OEBPS..
To build Gradle User Guide using docbook to epub, you need to do as follows:
  • You need to add cols="?" to <tgroup in the xml files in ~/gradle/subprojects/docs/src/docs/userguide. Otherwise, you will encounter the error Error: CALS tables must specify the number of columns. You can search the xml file using <tgroup> and cols="3" or cols="4".
    grep -R '<tgroup' ~/gradle/subprojects/docs/src/docs/userguide
  • You need to make build docs:userguide first. Because the document has a lot of sample codes, they are only added when you do a build. If you use userguide.xml in gradle/subprojects/docs/src/docs/userguide/userguid.xml, you won’t see the sample codes in the ebook.
  • After xlstproc, just run zip -r -X ../gradle-user-guide.epub mimetype META-INF OEBPS in ebook.
  • If you want .mobi for Kindle, convert the epub file in Calibre.