Monday 7 December 2015

Writable redis slave

While working with redis, you may have a master redis running on a central server and all of your web application servers are running redis slaves. There may be some instances where you want to make these slaves writable for some testing purposes. Here is how we can accomplish this:

1. Load the data from master redis:
nohup /usr/bin/redis-server --port "slave port" --slaveof "Master Redis Machine IP" "Master Redis Port" > redis.out &

nohup /usr/bin/redis-server --port 7000 --slaveof 137.53.57.37 7000 > redis.out &

2. Kill the above redis process using kill command once the data is loaded.

3. Disconnect slave from master redis:
nohup /usr/bin/redis-server --port "slave port" --slaveof none "Master Redis Port" > redis.out &

nohup /usr/bin/redis-server --port 7000 --slaveof none 7000 > redis.out &

Now your slave is disconnected from master and you can write on it.

Monday 16 November 2015

Grep/Search specific line number in linux/unix.

Today I had a situation where I had to search/grep for a specific line number in a file in linux. Here is the solution I found and thought it is worth sharing:

Uncompressed File:
cat test_file.csv | head -line_number | tail -1
cat test_file.csv | head -337930 | tail -1

Compressed File:
zcat test_file.gz | head -line_number | tail -1
zcat test_file.gz | head -337930 | tail -1

Above examples grep/search for line number 337930.

Tuesday 3 November 2015

Webpage redirection

What happens if your visitors try to access a page that was recently renamed, deleted, or moved? By default they will get an error message, but you can change that. Instead of your visitors stumbling upon an error when trying to access such a page, you can set a redirection rule that will redirect them to a new page.

This page is about individual page redirection. For information on domain redirection check out our domain redirection tutorial.

NOTE: Redirection is very good for search engines. Search engines need to know when one of your files has changed locations to re-index your site properly.

301 and 302 redirects

There are two types of redirects - 301 and 302. These are actually HTTP status codes which specify the status of communication between the web browser and the web server.

The code samples below should be placed in the file you're redirecting from unless otherwise specified.

302 redirects

302 redirects are used when a page's location has been changed temporarily.

HTML

HTML 302 redirects work through the <meta> tag:

<meta http-equiv="refresh" content="10; url=http://www.site.com/newpage.html" />

In the content attribute, the number is the amount of seconds before redirecting to the new page specified by url.

Javascript

Javascript 302 redirects work through the window.location property:

<script type="text/javascript">
window.location="http://www.yahoo.com";
</script>

Set the window.location property equal to the URL you want to redirect to. Include this Javascript code in the head section of an HTML document. The redirect should occur right away.

PHP

PHP 302 redirects work through the header function:

<?php header("Location: http://www.site.com/newpage.html"); ?>

Inside the header() function, put Location: followed by the URL to redirect to.

.htaccess

Put this in your .htaccess file:

redirect 302 /oldfile.html http://www.yoursite.com/newfile.html

/oldfile.html is the location of the file you're redirecting from and http://www.yoursite.com/newfile.html is the location of the file you're redirecting to.

301 redirects

301 redirects are used when a page's location has been changed permanently.

PHP

PHP redirects are 302 redirects by default, but by putting the HTTP/1.1 301 code at the top, we create a PHP 301 redirect:

<?php
header("HTTP/1.1 301 Moved Permanently");
header("Location: http://www.site.com/newpage.html");
?>


NOTE: When you use a PHP redirect make sure that the redirect code is the only thing on the page that you are redirecting from.

.htaccess

Put this in your .htaccess file:

redirect 301 /oldfile.html http://www.yoursite.com/newfile.html

/oldfile.html is the location of the file you're redirecting from and http://www.yoursite.com/newfile.html is the location of the file you're redirecting to.

Saturday 17 October 2015

Imitating domain names in linux.

Sometimes we may have to simulate different domains in our local machine. For example If you want to use domain "awesome.com" in place of localhost you can do the following:

You must be having below entry in your /etc/hosts file:

  127.0.0.1 localhost

Change this entry as given below:

  127.0.0.1 awesome.com

And you are done. Hit "awesome.com" from your browser and the request will come to your localhost. Similarly you can do multiple entries in /etc/hosts to simulate multiple domains.

Thursday 17 September 2015

isNumeric in Java.

Once in while in java we might have to check If a passed string to method is a valid numerical value. Below are some utility methods to accomplish this:

    Using java.text.NumberFormat.


    public static boolean isNumeric(final String str) {
        try {
            Double.parseDouble(str);
        } catch (final NumberFormatException | NullPointerException e) {
            return false;
        }

        return true;
    }

    JUnit Test Case:


        Assert.assertEquals(false, yourClass.isNumeric(null));
        Assert.assertEquals(false, yourClass.isNumeric(""));
        Assert.assertEquals(true, yourClass.isNumeric("2.74"));
        Assert.assertEquals(true, yourClass.isNumeric("2.745435E3"));
        Assert.assertEquals(true, yourClass.isNumeric("0"));
        Assert.assertEquals(true, yourClass.isNumeric("0.0f"));
        Assert.assertEquals(false, yourClass.isNumeric("NaN"));       


    Using Double.parseDouble.


     public static boolean isNumeric(final String string) {
        try {
            NumberFormat.getInstance().parse(string);
        } catch (ParseException | NullPointerException e) {
            return false;
        }

        return true;
    }

    JUnit Test Case:


        Assert.assertEquals(false, yourClass.isNumeric(null));
        Assert.assertEquals(false, yourClass.isNumeric(""));
        Assert.assertEquals(true, yourClass.isNumeric("2.74"));
        Assert.assertEquals(true, yourClass.isNumeric("2.745435E3"));
        Assert.assertEquals(true, yourClass.isNumeric("0"));
        Assert.assertEquals(true, yourClass.isNumeric("0.0f"));
        Assert.assertEquals(true, yourClass.isNumeric("NaN"));


As you guys might have noticed that I have an assert statement for both the methods which checks the method against string "NaN". The thing which makes this more interesting is that the method which uses NumberFormat returns false for this string while the method which uses Double.parseDouble(string) returns true.

You might say that the method which uses NumberFormat is correct because "NaN" is technically just a mere string value. Below is the description of how java treats "NaN" while doing floating-point operations :

"NaN" stands for "not a number". "Nan" is produced if a  floating point operation has some input parameters that cause the operation to produce some undefined result. For example, 0.0 divided
by 0.0 is arithmetically undefined. Taking the square root of a negative number is also undefined.


That's all for now folks stay tuned for new posts !!!!!!!!

 
 
 



Saturday 5 September 2015

Jetty - Enabling request logs

Whenever you start jetty using jetty.sh shell script located inside jetty's bin folder, the jetty will start with the below logs enabled defined inside /opt/jetty/start.ini file (defined using xml files) by default:

etc/jetty.xml
etc/jetty-annotations.xml
etc/jetty-deploy.xml
etc/jetty-webapps.xml
etc/jetty-contexts.xml
etc/jetty-testrealm.xml

Below is the snapshot of the /opt/jetty/start.ini file to show complete set of configuration files:

#===========================================================
# Configuration files.
# For a full list of available configuration files do
#   java -jar start.jar --help
#-----------------------------------------------------------
#etc/jetty-jmx.xml
etc/jetty.xml
etc/jetty-annotations.xml
# etc/jetty-ssl.xml
# etc/jetty-requestlog.xml
etc/jetty-deploy.xml
#etc/jetty-overlay.xml
etc/jetty-webapps.xml
etc/jetty-contexts.xml
etc/jetty-testrealm.xml
#===========================================================

As highlighted in the above configuration the request log xml file is commented by default. We just have to uncomment the same and restart jetty to enable request logs and you should be able to see the request logs generated in the below directory:

/opt/jetty/logs

$ ls -lt
total 48
-rw-rw-r-- 1 jetty jetty  165 Aug 21 13:54 2015_08_21.request.log

Thursday 4 June 2015

AspectJ Weaving - Finally Working !!!!!



After almost banging my head on the desk I finally get this working and thought of sharing the same in order to have a smooth run for anyone looking at it for the first time.

Before explaining the sample project I would like to set the plot that why I wanted to use AspectJ at the first place. I wanted to log a method's execution time in java. Though I would have done it a simple way by recording the difference between start time and end time of the method I chose AspectJ for not polluting the method body with the execution time logic.

In this tutorial I am not going to explain what is AspectJ? As I wanted to focus more on a working example. I have created a sample MAVEN project consists of the following java files:

SampleTarget.java:
This class contains a method fact for which we have to record the execution time.

 package com.piyush.aspect.tutorial;

/**
 * Class on which advice will be applied
 */
public class SampleTarget {
    public static void main(String[] args) {
        // Calling fact method on which 'around' advice will be applied
        new SampleTarget().fact(5);
    }

    public void fact(int num) {
        int c, fact = 1;
        if ( num < 0 )
           System.out.println("Number should be non-negative.");
        else
        {
           for ( c = 1 ; c <= num ; c++ )
              fact = fact * c;
           System.out.println("Factorial of "+num+" is = "+fact);
        }
    }
} 


SampleAspect.java: This class contains the advice implementation which has to be applied to the SampleTarget fact method.

package com.piyush.aspect.tutorial;

import org.aspectj.lang.ProceedingJoinPoint;
/**
 * A sample class annotated with @Aspect and implementing around advice
 */
@Aspect
public class SampleAspect {
    @Around("execution (* com.piyush.aspect.tutorial.SampleTarget.fact*(..))")
    public void advice(ProceedingJoinPoint joinPoint) throws Throwable {
        final long startTime = System.nanoTime();

        joinPoint.proceed();
        System.out.println("Elapsed time: ="+ (System.nanoTime() - startTime));
    }
}


Above things were not that difficult and can be found easily over the various blogs or tutorials. The key thing which has to be setup right is the pom.xml. Following is the pom.xml file which can be used without any modifications:

<?xml version="1.0" encoding="UTF-8"?>
<project
    <modelVersion>4.0.0</modelVersion>
    <groupId>SampleProject</groupId>
    <artifactId>SampleProject</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <targetJdk>1.7</targetJdk>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.12</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.12</version>
        </dependency>
    </dependencies>
    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.5</version>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>1.6.12</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <complianceLevel>1.6</complianceLevel>
                    <source>1.6</source>
                    <target>1.6</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.piyush.aspect.tutorial.SampleTarget</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Above pom.xml contains 3 dependencies aspectjrt, aspectjweaver and aspectjtools. It also contains aspectj maven plugin and maven execution plugin to execute SampleTarget.java having main method.

Now we have to run this project and see if the advice is applied to the fact method or not. Following command can be used to run the project from command line (make sure you are in the root directory of the project):

Command : mvn clean install OR mvn install

Following output should be displayed after running the project:

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building Unnamed - SampleProject:SampleProject:jar:0.0.1-SNAPSHOT
[INFO]    task-segment: [clean, install]
[INFO] ------------------------------------------------------------------------
[INFO] [clean:clean {execution: default-clean}]
[INFO] Deleting /home/piyusht/workspace/rtb/MyAspect/target
[INFO] [resources:resources {execution: default-resources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] [compiler:compile {execution: default-compile}]
[INFO] Compiling 3 source files to /home/piyusht/workspace/rtb/MyAspect/target/classes
[WARNING] POM for 'org.apache.maven.wagon:wagon-provider-api:pom:1.0-beta-6:runtime' is invalid.
Its dependencies (if any) will NOT be available to the current build.
[INFO] [aspectj:compile {execution: default}]
[INFO] [resources:testResources {execution: default-testResources}]
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /home/piyusht/workspace/rtb/MyAspect/src/test/resources
[INFO] [compiler:testCompile {execution: default-testCompile}]
[INFO] No sources to compile
[WARNING] POM for 'org.apache.maven:maven-toolchain:pom:2.0.9:runtime' is invalid.
Its dependencies (if any) will NOT be available to the current build.
[INFO] [surefire:test {execution: default-test}]
[INFO] No tests to run.
[INFO] Surefire report directory: /home/piyusht/workspace/rtb/MyAspect/target/surefire-reports
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Results :
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0
[INFO] [jar:jar {execution: default-jar}]
[INFO] Building jar: /home/piyusht/workspace/rtb/MyAspect/target/SampleProject-0.0.1-SNAPSHOT.jar
[INFO] Preparing exec:java
[WARNING] Removing: java from forked lifecycle, to prevent recursive invocation.
[INFO] No goals needed for project - skipping
[INFO] [exec:java {execution: default}]
Factorial of 5 is = 120
Elapsed time: =119435
[INFO] [install:install {execution: default-install}]
[INFO] Installing /home/piyusht/workspace/rtb/MyAspect/target/SampleProject-0.0.1-SNAPSHOT.jar to /home/piyusht/.m2/repository/SampleProject/SampleProject/0.0.1-SNAPSHOT/SampleProject-0.0.1-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Wed Jun 03 18:09:31 IST 2015
[INFO] Final Memory: 31M/244M
[INFO] ------------------------------------------------------------------------

das Ende !!!! Nope it is not garbage, its THE END in german. Although it has nothing to do with this post, mentioned just to put THE END in a different way :-)

Hope it helps. Please share your feedback and questions If any.