Wednesday, March 18, 2015

Fixing Error: Could not find a suitable provider in Puppet

I'm quite new to Puppet and I had a Puppet script which configures a MySQL database working fine on a Puppet learning VM on VirtualBox. This issue happened when I installed a and setup Puppet on a server of my own. I kept seeing the following error and it was driving me crazy for some time.

[hesxxxxxxx@xxxxxxpocx ~]$ sudo puppet apply --verbose --noop /etc/puppet/manifests/site.pp 
Info: Loading facts
Info: Loading facts
Info: Loading facts
Warning: Config file /etc/puppet/hiera.yaml not found, using Hiera defaults
Notice: Compiled catalog for xxxxxxxxxxxxxxxxxxx in environment production in 0.99 seconds
Warning: The package type's allow_virtual parameter will be changing its default value from false to true in a future release. If you do not want to allow virtual packages, please explicitly set allow_virtual to false.
   (at /usr/lib/ruby/site_ruby/1.8/puppet/type/package.rb:430:in `default')
Info: Applying configuration version '1426611197'
Notice: /Stage[main]/Mysql::Server::Install/Package[mysql-server]/ensure: current_value absent, should be present (noop)
Notice: /Stage[main]/Mysql::Server::Install/Exec[mysql_install_db]/returns: current_value notrun, should be 0 (noop)
Notice: Class[Mysql::Server::Install]: Would have triggered 'refresh' from 2 events
Notice: /Stage[main]/Mysql::Server::Config/File[mysql-config-file]/content: current_value {md5}8ace886bbe7e274448bc8bea16d3ead6, should be {md5}d0d209eb5ed544658b3f1a72274bc3ed (noop)
Notice: /Stage[main]/Mysql::Server::Config/File[/etc/my.cnf.d]/ensure: current_value absent, should be directory (noop)
Notice: Class[Mysql::Server::Config]: Would have triggered 'refresh' from 2 events
Notice: /Stage[main]/Mysql::Server::Service/Service[mysqld]/ensure: current_value stopped, should be running (noop)
Info: /Stage[main]/Mysql::Server::Service/Service[mysqld]: Unscheduling refresh on Service[mysqld]
Notice: /Stage[main]/Mysql::Server::Service/File[/var/log/mysqld.log]/ensure: current_value absent, should be present (noop)
Notice: Class[Mysql::Server::Service]: Would have triggered 'refresh' from 2 events
Error: Could not prefetch mysql_grant provider 'mysql': Command mysql is missing
Notice: /Stage[main]/Main/Node[default]/Mysql_grant[m_user@localhost/lvm.*]: Dependency Mysql_user[m_user@localhost] has failures: true
Warning: /Stage[main]/Main/Node[default]/Mysql_grant[m_user@localhost/lvm.*]: Skipping because of failed dependencies
Notice: Stage[main]: Would have triggered 'refresh' from 3 events
Error: Could not find a suitable provider for mysql_user
Error: Could not find a suitable provider for mysql_database

The issue was I was running puppet with —noop mode. When my Puppet tries to configure the mysql setup it gives errors because it didn’t have a mysql setup to configure since I had —noop. Removing this did the trick.

Although this is trivial, I thought of blogging this because someone might find this useful when facing the same issue as I did.


Monday, February 2, 2015

Resolving EACCES error when using Angular with Yeoman

In one of my earlier posts, I discussed installing NodeJS, NPM and Yeoman. Although the setup was good to start off my initial work, it was not was giving me the following error when trying to install Angular generator. Following post describe how to resolve this error.

heshans@15mbp-08077.local:~/Dev/projects/myYoApp$yo

     _-----_
    |       |    .------------------------------------------.
    |--(o)--|    | Update available: 1.4.5 (current: 1.3.3) |
   `---------´   |     Run npm install -g yo to update.     |
    ( _´U`_ )    '------------------------------------------'
    /___A___\    
     |  ~  |     
   __'.___.'__   
 ´   `  |° ´ Y ` 

? 'Allo Heshan! What would you like to do? Install a generator
? Search NPM for generators: angular
? Here's what I found. Install one? angular
npm ERR! Darwin 14.0.0
npm ERR! argv "node" "/usr/local/bin/npm" "install" "-g" "generator-angular"
npm ERR! node v0.10.33
npm ERR! npm  v2.1.11
npm ERR! path /Users/heshans/.node/lib/node_modules/generator-angular/CHANGELOG.md
npm ERR! code EACCES
npm ERR! errno 3

npm ERR! Error: EACCES, unlink '/Users/heshans/.node/lib/node_modules/generator-angular/CHANGELOG.md'
npm ERR!  { [Error: EACCES, unlink '/Users/heshans/.node/lib/node_modules/generator-angular/CHANGELOG.md']
npm ERR!   errno: 3,
npm ERR!   code: 'EACCES',
npm ERR!   path: '/Users/heshans/.node/lib/node_modules/generator-angular/CHANGELOG.md' }
npm ERR! 
npm ERR! Please try running this command again as root/Administrator.
npm ERR! error rolling back Error: EACCES, unlink '/Users/heshans/.node/lib/node_modules/generator-angular/CHANGELOG.md'
npm ERR! error rolling back  { [Error: EACCES, unlink '/Users/heshans/.node/lib/node_modules/generator-angular/CHANGELOG.md']
npm ERR! error rolling back   errno: 3,
npm ERR! error rolling back   code: 'EACCES',
npm ERR! error rolling back   path: '/Users/heshans/.node/lib/node_modules/generator-angular/CHANGELOG.md' }

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/heshans/Dev/projects/myYoApp/npm-debug.log

It was due to a permission error in my setup. I tried giving my user the permission to access those files but it still didn't resolve the issue. Then I decided to remove my existing NodeJS and NPM installations. Then I used the following script by isaacs with slight modifications. It worked like a charm. Then I was able to successfully install AngularJS generator to Yeoman.

PS : Also make sure that you have updated your PATH variable in your ~/.bash_profile file.
export PATH=$HOME/local/bin:~/.node/bin:$PATH

Tuesday, December 9, 2014

Install the Yeoman toolset

1. Prerequisite: Node.js and NPM should be installed in the system.

2. Install Yeoman tools
heshans@15mbp-08077.local:~/Dev$npm install --global yo bower grunt-cli

3. Check installed versions.
heshans@15mbp-08077.local:~/Dev$yo --version && bower --version && grunt --version

1.3.3

1.3.12

grunt-cli v0.1.13

Install Node.js and NPM on Mac OSX

I’m using Homebrew for the installation. If you don't have it installed, please install it.

1. Install node
heshans@15mbp-08077.local:~/Dev$brew install node

2. Check installed versions.
heshans@15mbp-08077.local:~/Dev$node -v

v0.10.33

heshans@15mbp-08077.local:~/Dev$npm -v

2.1.8

3. Update Homebrew.
heshans@15mbp-08077.local:~/Dev$brew update 

Already up-to-date.

4. Upgrade Node.
heshans@15mbp-08077.local:~/Dev$brew upgrade node

Wednesday, October 15, 2014

How to find which method called the current method at runtime


I’m using the following helper class to find which method called the current method (at runtime.)

import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;

public class TraceHelper {
    private volatile static Method m;
    private static Throwable t;

    public TraceHelper() {
        try {
            m = Throwable.class.getDeclaredMethod("getStackTraceElement", int.class);
            AccessController.doPrivileged(
                    new PrivilegedAction() {
                        public Object run() {
                            m.setAccessible(true);
                            return null;
                        }
                    }
            );
            t = new Throwable();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getMethodName(final int depth, boolean useNew) {
        return getMethod(depth, t != null && !useNew ? t : new Throwable());
    }

    public String getMethod(final int depth, Throwable t) {
        try {
            StackTraceElement element = (StackTraceElement) m.invoke(t, depth + 1);
            return element.getClassName() + "$" + element.getMethodName();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
Then I use the following code inside my aspect to get the name of the method which called my current (executing) method.
String previousMethodName = new TraceHelper().getMethodName(2, false);

Include/exclude sources when using aspect-maven-plugin


AspectJ mavn plugin will add all .java and .aj files in the project source directories by default. By using <include/> and <exclude/> tags, you can add filtering on top of that. 


            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.5</version>
                <configuration>
                    <complianceLevel>1.7</complianceLevel>
                    <source>1.7</source>
                    <target>1.7</target>

                    <sources>
                        <source>
                            <!--<basedir>src/main/java</basedir>-->
                            <!--<includes>-->
                                <!--<include>**/TransationAspect.java</include>-->
                            <!--</includes>-->
                            <excludes>
                                <exclude>**/DcXferHandler.java</exclude>
                                <!--<exclude>**/ChunkingSqlSerActor.java</exclude>-->
                            </excludes>
                        </source>
                    </sources>
                </configuration>
                <executions>
                    <execution>
                        <!--<phase>process-sources</phase>-->
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

Tuesday, October 14, 2014

Stackmap frame errors when building the aspectj project with Java 1.7


I had a project which used aspectj and it was building fine with Java 1.6. When I updated it to Java 1.7 I saw the following error.

[INFO] Molva the Destroyer Aspects ....................... FAILURE [2.324s]
[INFO] Molva The Destroyer Client ........................ SKIPPED
[INFO] Molva The Destroyer Parent ........................ SKIPPED
[INFO] Molva The Destroyer Distribution .................. SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.424s
[INFO] Finished at: Tue Oct 14 11:16:19 PDT 2014
[INFO] Final Memory: 12M/310M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.1:java (default) on project molva-the-destroyer-aspects: An exception occured while executing the Java class. Expecting a stackmap frame at branch target 30
[ERROR] Exception Details:
[ERROR] Location:
[ERROR] com/concur/puma/molva/aspects/TestTarget.main([Ljava/lang/String;)V @12: invokestatic
[ERROR] Reason:
[ERROR] Expected stackmap frame at this location.
[ERROR] Bytecode:
[ERROR] 0000000: 2a4d b200 5e01 012c b800 644e b800 c62d
[ERROR] 0000010: b600 ca2c 2db8 00bb 2db8 00bf 57b1 3a04
[ERROR] 0000020: b800 c62d 1904 b600 ce19 04bf
[ERROR] Exception Handler Table:
[ERROR] bci [12, 30] => handler: 30
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

My maven configuration looked like below.
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.5</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>org.perf4j</groupId>
            <artifactId>perf4j</artifactId>
            <version>0.9.16</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.2</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>com.concur.puma.molva.aspects.TestTarget</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

Fix 

The default compliance level for aspectj-maven-plugin is 1.4 according to http://mojo.codehaus.org/aspectj-maven-plugin/compile-mojo.html#complianceLevel. Since I did not have that tag specified, the build was using the default value. Once I inserted the tag into the configuration, the build was successful.

Compile aspectj project containing Java 1.7 Source


Following maven configuration let’s you compile a project with Java 1.7 source.
<dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <!--<version>1.6.5</version>-->
            <version>1.8.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <complianceLevel>1.7</complianceLevel>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
                <executions>
                    <execution>
                        <!--<phase>process-sources</phase>-->
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Tuesday, September 23, 2014

Jmeter plugins for Apache Jmeter

I came across Jmeter-plugins project today and tried it out. It has a nice set of addons to support/complement existing functionality of Jmeter.

Thursday, March 27, 2014

Installing R on Mac OS X

1) Install Homebrew in your system.

2) Download and install XQuartz (Homebrew does not package XQuartz and it is needed for step 3. Therefore install XQuartz.)

3) Install Fortran and R.
heshans@15mbp-08077:/tmp$ brew update

heshans@15mbp-08077:/tmp$ brew tap homebrew/science

heshans@15mbp-08077:/tmp$ brew install gfortran r 

4) Verify the installation by running R.
heshans@15mbp-08077:/tmp$ R

R version 3.0.3 (2014-03-06) -- "Warm Puppy"
Copyright (C) 2014 The R Foundation for Statistical Computing
Platform: x86_64-apple-darwin13.1.0 (64-bit)

R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.

  Natural language support but running in an English locale

R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.

Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.

Tuesday, March 25, 2014

Custom Log Formatter

Following is the source for a custom log formatter.

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.LogRecord;

public class CustomFormatter extends Formatter {

    private static final DateFormat df = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss.SSS");

    public String format(LogRecord record) {
        StringBuilder builder = new StringBuilder(1000);
        builder.append(df.format(new Date(record.getMillis()))).append(" - ");
        builder.append("[").append(record.getSourceClassName()).append(".");
        builder.append(record.getSourceMethodName()).append("] - ");
        builder.append("").append(record.getLevel()).append(" - ");
        builder.append(formatMessage(record));
        builder.append("\n");
        return builder.toString();
    }

    public String getHead(Handler h) {
        return super.getHead(h);
    }

    public String getTail(Handler h) {
        return super.getTail(h);
    }
}

Following is the way how the log messages will turn up in your log file.

25/03/2014 08:46:17.770 - [com.company.util.memcache.EntityThreadTask.setDataToMemcache] - INFO - thread05 compositekey set time : 5 ms
25/03/2014 08:46:17.781 - [com.company.util.memcache.EntityThreadTask.setDataToMemcache] - INFO - thread03 compositekey set time : 11 ms
25/03/2014 08:46:17.783 - [com.company.util.memcache.EntityThreadTask.setDataToMemcache] - INFO - thread05 compositekey set time : 12 ms
25/03/2014 08:46:17.785 - [com.company.util.memcache.EntityThreadTask.setDataToMemcache] - INFO - thread03 compositekey set time : 4 ms
25/03/2014 08:46:17.787 - [com.company.util.memcache.EntityThreadTask.setDataToMemcache] - INFO - thread05 compositekey set time : 4 ms

Monday, March 10, 2014

Fixing BSFException: unable to load language: java

I was using JMeter to execute BeanShell scripts that I have written and came across this exception. I had to waste sometime to find out what was the exact issue. Although I copied the BSF jar to the JMeter lib directory, it was not sufficient. When I added the bsh-bsf-2.0b4.jar, the script started running successfully. 

I thought someone else might find this tip useful, therefore blogging it.

Thursday, March 6, 2014

Fixing java.lang.ClassNotFoundException: org.apache.bsf.engines.java.JavaEngine

When using JMeter’s Java request sampler, I started seeing the below error.
2014/03/06 09:46:39 ERROR - org.apache.bsf.BSFManager: Exception : java.lang.ClassNotFoundException: org.apache.bsf.engines.java.JavaEngine
 at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
 at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
 at org.apache.bsf.BSFManager.loadScriptingEngine(BSFManager.java:693)
 at org.apache.jmeter.util.BSFTestElement.processFileOrScript(BSFTestElement.java:98)
 at org.apache.jmeter.visualizers.BSFListener.sampleOccurred(BSFListener.java:51)
 at org.apache.jmeter.threads.ListenerNotifier.notifyListeners(ListenerNotifier.java:84)
 at org.apache.jmeter.threads.JMeterThread.notifyListeners(JMeterThread.java:783)
 at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:443)
        at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:257)

Following steps will resolve this issue.

1. Remove existing bsf jar from the jmeter/lib directory
heshans@15mbp-08077:~/Dev/tools$ rm apache-jmeter-2.11/lib/bsf-2.4.0.jar

2. Download and extract BSF http://wi.wu-wien.ac.at/rgf/rexx/bsf4rexx/current/BSF4Rexx_install.zip.

3. Copy the following two jars to the jmeter/lib directory.
heshans@15mbp-08077:~/Dev/tools$ cp bsf4rexx/bsf-rexx-engine.jar apache-jmeter-2.11/lib/ 
heshans@15mbp-08077:~/Dev/tools$ cp bsf4rexx/bsf- apache-jmeter-2.11/lib/

Thursday, February 27, 2014

Fixing java.lang.NoClassDefFoundError: org/codehaus/classworlds/Launcher

I came across this error after I installed a new version of maven.
$ mvn -version
java.lang.NoClassDefFoundError: org/codehaus/classworlds/Launcher
Caused by: java.lang.ClassNotFoundException: org.codehaus.classworlds.Launcher
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Could not find the main class: org.codehaus.classworlds.Launcher.  Program will exit.
Exception in thread "main"
The issue was with having two MAVEN_HOME locations (two versions) in the "path" variable. Once I removed a one, the issue resolved.
$ mvn -version
Apache Maven 3.1.1

Monday, February 24, 2014

Fixing mysql replication errors in a master/slave setup

If you have a mysql master/slave replication setup and have run into replication errors, you can follow the below instructions to fix up the replication break and sync up the data.
1) Stop mysql on the slave.
service mysql stop
2) Login to the master.

3) Lock the master by running the following command
mysql> flush tables with read lock;
NOTE: No data can be written at this time to the master, so be quick in the following steps if your site is in production. It is important that you do not close mysql or this running ssh terminal. Login to a separate ssh terminal for the next part.

4) Now, in a separate ssh screen, type the following command from the master mysql server.
rsync -varPe ssh /var/lib/mysql root@IP_ADDRESS:/var/lib/ —delete-after
5) After this is done, now you must get the binlog and position from the master before you unlock the tables. Run the following command on master
mysql> show master status\G;
Then you’ll get some information on master status. You need the file and the position because that’s what you’re going to use on the slave in a moment. See step 10 on how this information is used, but please do not skip to step 10.

6) Unlock the master. It does not need to be locked now that you have the copy of the data and the log position.
mysql> unlock tables;
7) Login to the slave now via ssh. First remove the two files : /var/lib/mysql/master.info and /var/lib/mysql/relay-log.info

8) Start mysql on the slave.
service mysqld start
9) Immediately login to mysql and stop slave
mysql> slave stop; 
10) Now, you have to run the following query filling in the information from the show master status above (Step 5.)
mysql> CHANGE MASTER TO MASTER_HOST=MASTER_IP,
mysql> MASTER_USER=‘replicate’, MASTER_PASSWORD=‘replicate’,
mysql> MASTER_LOG_FILE=‘mysql-bin.000001’, MASTER_LOG_POS=1234512351;
11) Now start the slave.
mysql > slave start
12) Check slave status.
mysql> show slave status\G;

Thursday, February 20, 2014

XML to XML tranformation using XSLT

In this example I am transforming an XML using XSLT by modifying certain child elements. In coming XML message:
<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="/xsl/error.xsl"?>
<outtask_error>
    <server>
        <name>RSDC-C12</name>
    </server>
    <application>
        <name>Jobs</name>
        <version>2012_06_15</version>
        <prod_status>qa</prod_status>
        <datacenter_location>rtwa3</datacenter_location>
        <request_id>n6dft440-8049-4dff-982a-ee05abc8433</request_id>
    </application>
    <error time="2014-02-06T20:01:05" timezone="Pacific Standard Time">
        <error_id>aab10-825-4a52d-a261-7a845262f</error_id>
        <error_default_source>ICSYC</error_default_source>
        <request_id>b2263a40-8049-4dff-942a-ee05ef3f8433</request_id>
        <error_source>ICSync</error_source>
        <error_description>Connection Entity:abc no DB name is not configured</error_description>
        <stack_trace>at Company.Core.Sync.GetConnectionInfo...
        </stack_trace>
    </error>
    <server_variables>
        <param name="SERVER_NAME">RSDC-C12</param>
        <param name="SCRIPT_NAME">C:\Sync.exe</param>
        <param name="QUERY_STRING">Sync.exe Day1</param>
    </server_variables>
    <Error_Context>
        <param name="databasename">Company_MT</param>
        <param name="error_defaultsource">SYS</param>
        <param name="error_defaultapplicationname">Jobs</param>
        <param name="requestid">b8943a40-1349-4dff-232a-ee05ef523452342f</param>
        <param name="dbservername">fabc-sql02,1420</param>
    </Error_Context>
</outtask_error>
XSLT for the transformation:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="outtask_error/server_variables">
        <server_variables>
            <xsl:for-each select="param">
                <xsl:text disable-output-escaping="yes"><</xsl:text><xsl:value-of select="./@name"/><xsl:text disable-output-escaping="yes">></xsl:text>
                <xsl:value-of select="."/>
                <xsl:text disable-output-escaping="yes"><</xsl:text>/<xsl:value-of select="./@name"/><xsl:text disable-output-escaping="yes">></xsl:text>
            </xsl:for-each>
        </server_variables>
    </xsl:template>

    <xsl:template match="outtask_error/Error_Context">
        <Error_Context>
            <xsl:for-each select="param">
                <xsl:text disable-output-escaping="yes"><</xsl:text><xsl:value-of select="./@name"/><xsl:text disable-output-escaping="yes">></xsl:text>
                <xsl:value-of select="."/>
                <xsl:text disable-output-escaping="yes"><</xsl:text>/<xsl:value-of select="./@name"/><xsl:text disable-output-escaping="yes">></xsl:text>
            </xsl:for-each>
        </Error_Context>
    </xsl:template>

</xsl:stylesheet>
Out going XML:
<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="/xsl/error.xsl"?><outtask_error>
    <server>
        <name>RSDC-C12</name>
    </server>
    <application>
        <name>Jobs</name>
        <version>2012_06_15</version>
        <prod_status>qa</prod_status>
        <datacenter_location>rtwa3</datacenter_location>
        <request_id>n6dft440-8049-4dff-982a-ee05abc8433</request_id>
    </application>
    <error time="2014-02-06T20:01:05" timezone="Pacific Standard Time">
        <error_id>aab10-825-4a52d-a261-7a845262f</error_id>
        <error_default_source>ICSYC</error_default_source>
        <request_id>b2263a40-8049-4dff-942a-ee05ef3f8433</request_id>
        <error_source>ICSync</error_source>
        <error_description>Connection Entity:abc no DB name is not configured</error_description>
        <stack_trace>at Company.Core.Sync.GetConnectionInfo...
        </stack_trace>
    </error>
    <server_variables><SERVER_NAME>RSDC-C12</SERVER_NAME><SCRIPT_NAME>C:\Sync.exe</SCRIPT_NAME><QUERY_STRING>Sync.exe Day1</QUERY_STRING></server_variables>
    <Error_Context><databasename>Company_MT</databasename><error_defaultsource>SYS</error_defaultsource><error_defaultapplicationname>Jobs</error_defaultapplicationname><requestid>b8943a40-1349-4dff-232a-ee05ef523452342f</requestid><dbservername>fabc-sql02,1420</dbservername></Error_Context>
</outtask_error>

Thursday, January 30, 2014

Aspect oriented programming with Java

I started working with AspectJ and Perf4J recently. I did not have any prior AOP experience. I was looking for an example which did not use Spring AOP but I did not find a good sample which I could use to get my work done. Therefore, once I completed my project, thought of writing this sample up. There are a lot of tutorials out there which describes what AOP is. Therefore, I’m not going to introduce it here. You can do a Google search and find it out.

What I wanted was to measure the method runtimes without doing any modifications to the existing source. AspectJ helped me to achieve that.

Following are my sample source code. Following is my test class which I'm using to measure method runtimes.
import org.apache.log4j.Logger;

public class TestTarget {

    static Logger logger = Logger.getLogger(TestTarget.class);

    public static void main(String[] args) throws Exception {
        // Test case 01
        testCountFast(1000);

        // Test case 02
        testCountSlow(1000);

    }

    public static void testCountSlow(int value) {
        count(value,5);
    }

    public static void testCountFast(int value) {
        count(value,0);
    }

    private static void count(int value, int delay) {
        for (int i=0;i<value;i++) {
            try {
                Thread.sleep(delay);
            } catch (Exception e) {
                logger.error("Error occurred while sleeping", e);
            }
        }
    }

}
Following is my Aspect class which uses AspectJ and Perf4J.
import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.perf4j.StopWatch;
import org.perf4j.log4j.Log4JStopWatch;

@Aspect
public class Perf4JAspect {
    static Logger logger = Logger.getLogger(Perf4JAspect.class);

    @Around("execution (* com.company.molva.aspectj.TestTarget.test*(..))")
    public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info(MolvaLoggingUtil.getCurrentDateTime()
                + " MainAspect.measureExecutionTime() called on " + joinPoint.getSignature());

        long startNanoTime = System.nanoTime();
        StopWatch stopWatch = new Log4JStopWatch();
        Object proceed = joinPoint.proceed();
        stopWatch.stop(joinPoint.getSignature().toLongString());

        long endNanoTime = System.nanoTime();
        long executionNanoTime = endNanoTime - startNanoTime;
        logger.info(MolvaLoggingUtil.getCurrentDateTime() + " "
                + joinPoint.getSignature()+" took "+ executionNanoTime/1000000.0 +"ms");
        return proceed;
    }
}
My aop.xml configuration is as follows.
<aspectj>
    <aspects>
        <aspect name="com.company.molva.aspectj.MainAspect"/>
        <aspect name="com.company.molva.aspectj.Perf4JAspect"/>
    </aspects>

    <weaver options="-verbose">
        <include within="com.aspectj.*"/>
    </weaver>
</aspectj>
My log4j.xml looks as follows.
 
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration debug="false" xmlns:log4j="http://jakarta.apache.org/log4j/">

    <appender name="aspectjFileAppender" class="org.apache.log4j.FileAppender">
        <param name="File" value="aspectj_stats.log"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%m%n"/>
        </layout>
    </appender>
 
    <appender name="CoalescingStatistics"
              class="org.perf4j.log4j.AsyncCoalescingStatisticsAppender">
        <param name="TimeSlice" value="10000"/>
        <appender-ref ref="fileAppender"/>
    </appender>

    <appender name="fileAppender" class="org.apache.log4j.FileAppender">
        <param name="File" value="perf_stats.log"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%m%n"/>
        </layout>
    </appender>

     <logger name="org.perf4j.TimingLogger" additivity="false">
        <level value="INFO"/>
        <appender-ref ref="CoalescingStatistics"/>
    </logger>

    <root>
        <level value="INFO"/>
        <appender-ref ref="aspectjFileAppender"/>
    </root>
    
</log4j:configuration>
Once the sample completes running, I get the following logs at my log files.
aspectj_stats.log:
2014-01-30 13:19:25 MainAspect.measureExecutionTime() called on void com.company.molva.aspectj.TestTarget.testCountFast(int)
2014-01-30 13:19:25 void com.company.molva.aspectj.TestTarget.testCountFast(int) took 0.904ms
2014-01-30 13:19:25 MainAspect.measureExecutionTime() called on void com.company.molva.aspectj.TestTarget.testCountSlow(int)
2014-01-30 13:19:31 void com.company.molva.aspectj.TestTarget.testCountSlow(int) took 5608.996ms
perf_stats.log:
Performance Statistics   2014-01-30 13:19:20 - 2014-01-30 13:19:30
Tag                                                                        Avg(ms)         Min         Max     Std Dev       Count
public static void com.company.molva.aspectj.TestTarget.testCountFast(int)     0.0           0           0         0.0           1
public static void com.company.molva.aspectj.TestTarget.testCountSlow(int)  5608.0        5608        5608         0.0           1
As you can see, we can use AspectJ and Perf4J to generate some nice statistics.

Java library to convert XML to JSON

Recently I wanted to convert some XMLs to JSON messages. I came across this library called JSON-Java and found it very useful.
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;

public class Main {

    public static int PRETTY_PRINT_INDENT_FACTOR = 4;
    public static String TEST_XML_STRING =
            "\n" +
                    "\n" +
                    "Belgian Waffles\n" +
                    "$5.95\n" +
                    "\n" +
                    "Two of our famous Belgian Waffles with plenty of real maple syrup\n" +
                    "\n" +
                    "650\n" +
                    "\n" +
                    "\n" +
                    "Strawberry Belgian Waffles\n" +
                    "$7.95\n" +
                    "\n" +
                    "Light Belgian waffles covered with strawberries and whipped cream\n" +
                    "\n" +
                    "900\n" +
                    "\n" +
                    "";

    public static void main(String[] args) {
        try {
            JSONObject xmlJSONObj = XML.toJSONObject(TEST_XML_STRING);
            String jsonPrettyPrintString = xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR);
            System.out.println(jsonPrettyPrintString);
        } catch (JSONException je) {
            System.out.println(je.toString());
        }
    }
}
The XML:
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<description>
Two of our famous Belgian Waffles with plenty of real maple syrup
</description>
<calories>650</calories>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<description>
Light Belgian waffles covered with strawberries and whipped cream
</description>
<calories>900</calories>
</food>
</breakfast_menu>
JSON:
{"breakfast_menu": {"food": [
    {
        "price": "$5.95",
        "description": "Two of our famous Belgian Waffles with plenty of real maple syrup",
        "name": "Belgian Waffles",
        "calories": 650
    },
    {
        "price": "$7.95",
        "description": "Light Belgian waffles covered with strawberries and whipped cream",
        "name": "Strawberry Belgian Waffles",
        "calories": 900
    }
]}}

Monday, November 18, 2013

My first tandem sky dive experience

Never thought jumping out of an air plane at 11000 feet would be this much fun. What a rush!

Video quality is a bit low because I had to convert it to a lesser quality to upload it to youtube.

Techniques to backup and restore mysql databases - A comparison

When I started working at Digital Mediat Solutions, one of the biggest problems that we had was the runtime of daily mysql backup scripts. They were taking 8 hours to complete. The first task I had was to fix the performance of the backups. The existing scripts were based on mysqldump. 

I compiled a list of options to look into by referring the web. I'm sharing this, so that someone else might find it useful. 

Out of the following options, the most feasible (economically, disk space wise and performance wise) option for us, was to use mysqlhotcopy. Now the backup script I have written based on  mysqlhotcopy, completes in 1 hours time, which is a significant imporvement. 


Options

1) MySQL enterprise backup
pros
  • incremental backup
  • compressed backup
  • Backing up the physical database files makes restore much faster than logical techniques such as the mysqldump command.
  • InnoDB tables are copied using a hot backup mechanism. (Ideally, the InnoDB tables should represent a substantial majority of the data.)
  • Tables from other storage engines are copied using a warm backup mechanism.


cons
  • enterprise licensed
  • Minimalistic license per 1 mysql server instance per 1 year is XXXXUSD.
  • The cost will grow as the instances grow and the running time exceeds year by year.
  • It even exceeds our current budget for underlying hardware.
  • Therefore, I don’t think it’s feasible for our budget and IMV it’s not needed for the current deployment.


2) MySQL dumps with diffs
pros
  • Saves space in the backed up device as we are backing up the diff.   
  • It won't result in network traffic as the only time the full dump is transferred, is when it’s run for the first time.


cons
  • We are looking into stopping the overhead generated by the mysql dump command.
  • Since, we are using the same command over and over again, in this deployment, this wont satisfuy our need. Therefore, IMV this is not the option for us.


3) Make incremental backups by enabling the binary logs.
pros
  • Used to set up replication
  • Used for restore operations
  • The above two pros outweigh the con.
  • Can do pinpoint restorations
  • Can tarball the existing logs and ship to the backup location. Just a matter of file zipping operation.


cons
  • Makes performance slightly slower.


4) Suggestions to improve current backup scripts
  • Improve the cron job (which gets triggered on low usage period) to perform the slaving task to avoid high CPU utilization.


5) Should investigate and run some performance matrices on mysql-parallel-dump and mk-parallel-dump (http://www.maatkit.org/) utilities.
  • mk-parallel-dump is deprecated now. So, it not feasible.
  • TODO: Talk to Matt regarding:
    • Setting up a dev env, so that I could test these stuff. I don’t need any new fancy hardware for these. Just give me a PC and I’ll configure it with linux and try these out. We don’t have to buy new hardware.
    • Need to test these in a dev env. So, that we could roll these out to a production environment.
    • Need to have a mock server (which have kind of the same traffic as the real servers), so that we could test and verify things properly


6) Remove the current scripts and use a tool specifically written for this and see how it performs.


7) Update the current scripts with --quick option which avoids buffering of large tables and does row by row backups. Resulting in faster restores. This will be a minor tweak to the current scripts.


8) Use of mysqlhotcopy instead of mysquldump
  • It uses FLUSH TABLES, LOCK TABLES, and cp or scp to make a database backup.
  • It is a fast way to make a backup of the database or single tables
  • but it can be run only on the same machine where the database directories are located.
  • mysqlhotcopy works only for backing up MyISAM and ARCHIVE tables.
  • Since we are using MyISAM, this wont be a problem for us.


9) Use SVN to backup databases.
  • This will help to have revisions.
  • I don’t think we need such a mechanism for us.


10) If replication to a slave isn't an option, we could leverage the filesystem, depending on the OS we are using,