Monday, August 14, 2017

Simple Thread Pool in Golang


Simple Thread Pool in golang with Simple Future response.

package main

import "fmt"
import "time"
import "sync"

// Call is a callable which returns a value
type Call func() interface{}

// Run is a runnable function
type Run func()

// Future is a holder for cal result.
type Future interface {
Done() bool
Result() interface{}
ResultAwait(time.Duration) interface{}
}

// future is an implementation of Future interface
type future struct {
done    bool
result  interface{}
reschan chan struct{}
sync.RWMutex
}

func (f *future) Done() bool {
f.RLock()
defer f.RUnlock()
return f.done
}

func (f *future) Result() interface{} {
f.RLock()
defer f.RUnlock()
return f.result
}

func (f *future) ResultAwait(d time.Duration) interface{} {
select {
case <-f.reschan:
case <-time.After(d):
}
return f.result
}

//--------------------------------------------------------

// worker is worker used in pool
type worker struct {
name string
}

// start method of worker, called when pool is initialized
func (w *worker) start(runq <-chan Run, quit <-chan struct{}) {
for {
select {
case f := <-runq:
f()
case <-quit:
return
}
}
}

//-------------------------------------------------------------

// Pool is pool
type Pool struct {
pool
}

// pool is a local pool used to implemnt pool methods
type pool struct {
size int
runq chan Run
quit chan struct{}
}

// NewPool is pool constructor
func NewPool(size int) *Pool {
var p = Pool{
pool: pool{
size: size,
runq: make(chan Run, size),
quit: make(chan struct{}, size),
},
}
p.init()
return &p
}

// init method to initialize the pool.
func (p *pool) init() {
for i := 0; i < p.size; i++ {
var w = worker{name: fmt.Sprintf("worker %d", i)}
go w.start(p.runq, p.quit)
}
}

// Stop the pool after all the submitted tasks are done.
func (p *pool) Stop() {
p.ExecuteRun(func() {
close(p.quit)
})
}

// ExecuteRun runs a runnable object.
func (p *pool) ExecuteRun(run Run) {
p.runq <- run
}

// ExecuteCall runs a callable function.
func (p *pool) ExecuteCall(call Call) Future {
var fut = future{reschan: make(chan struct{})}
fn := func() {
res := call()
fut.Lock()
defer fut.Unlock()
fut.done = true
fut.result = res
}
p.ExecuteRun(fn)
return &fut
}

//-----------------------------------------------------------------
func main() {
p := NewPool(10)
for i := 0; i < 5; i++ {
j := i + 1
p.ExecuteRun(func() {
fmt.Println("hello ", j)
})
}

time.Sleep(10 * time.Millisecond)

fut := p.ExecuteCall(hello)
res := fut.ResultAwait(30 * time.Millisecond)
fmt.Println("Result is", res)

fut1 := p.ExecuteCall(wrap(welcome))
res1 := fut1.ResultAwait(45 * time.Millisecond)
fmt.Println("Result for fut1 is:----->>>", res1)

time.Sleep(1 * time.Second)
p.Stop()
fmt.Println("Result after stop for fut is: -->>>>", fut.Result())
fmt.Println("Done............")

}

func hello() interface{} {
time.Sleep(45 * time.Millisecond)
return "Hello World."
}

func welcome() string {
time.Sleep(30 * time.Millisecond)
return "Welcome to go world."
}

// wrap is a wrapper function,
// as func() interface{} signature type does not match func() string signature type,
// Not sure why :)

func wrap(f func() string) func() interface{} {
return func() interface{} { return f() }
}

Tuesday, March 29, 2016




Simple kotlin sparkjava project with gradle.



Lets start by creating the directory structure for simple kotlin sparkjava project.

Assuming we have java and gradle on the path
The version of gradle 2.12 and java 1.8

If you don't have them on your path, set it as
set JAVA_HOME=your_java_home_dir
set GRADLE_HOME=your_gradle_home_dir

set path=%JAVA_HOME%/bin;%GRADLE_HOME%/bin;
you can now test if they are working properly by typing command
%> java -version
%> gradle -v

Lets move to workspace directory, for me it is c:\workspace

Lets create a project named "myspark" by creating a directory under c:\workspace

mkdir myspak

cd myspark

now you are into myspark folder (c:\workspace\myspark)


Lets create source folders as per maven standard directory structure for java and kotlin.

mkdir src\main\java
mkdir src\main\kotlin
mkdir src\test\java
mkdir src\test\kotlin
mkdir src\main\resources
mkdir src\test\resources

create a new file name build.gradle under myspark directory
paste the content below into build.gradle


// c:\workspace\myspark\build.gradle

buildscript {

  ext.kotlin_version = '1.0.1'
  ext.gson_version = '2.6.2'
  ext.sparkjava_version = '2.3'

  repositories {
    mavenCentral()
  }
  dependencies {
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
  }
}

apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'application'  // to run main file
apply plugin: 'idea'      // for intellij project


// note 'Kt', static members are grouped in a generated class with 'Kt' here MainKt
mainClassName = 'com.mmk.MainKt'

defaultTasks 'run'

repositories {
  mavenCentral()
}

dependencies {

  compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
  compile "com.google.code.gson:gson:$gson_version"
  compile 'com.sparkjava:spark-core:$sparkjava_version'


  testCompile 'junit:junit:4.11'
  testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
}

On your command prompt, change your current directory to src\main\kotlin
ie c:\workspace\myspark\src\main\kotlin

make directory com\mmk
ie on command prompt %> mkdir com\mmk
You can have any package, make sure it reflects the mainClassName above to run the app.

under com\mmk create a Main.kt file
edit Main.kt and paste the below content,


package com.mmk

import com.google.gson.Gson
import spark.Spark
import spark.Spark.get

fun main(args: Array<String>) {
 val main = Main()
 main.run()
}

data public class Name(val fname: String, val lname: String)

class Main{

val gson = Gson();
fun run(){
// this is folder under src/main/resources  to serve static files.
Spark.staticFileLocation("/public");

get("/hello", { req, res -> "Hello World" });
get("/hello/:name", { req, res -> "Hello " + req.params(":name") });
get("/hello/:fname/:lname", {
req, res ->
val fname = req.params(":fname")
val lname = req.params(":lname")
Name(fname,lname)
},
{obj -> gson.toJson(obj)}
);
}

}

save the file, now on the terminal or command prompt, go to the root directory
here c:\workspace\myspark
run the below command to compile & build.

gradle build

then to run the app, type the below command,
gradle run

this will start jetty at port 4567 by default,
you can test the app by opening the browser with the url below
http://localhost:4567/hello
http://localhost:4567/hello/fazal

press Ctrl+C to exit the server.




Monday, August 31, 2015

Using SparkJava microframework with Kotlin


Using sparkjava framework with kotlin language.

import com.google.gson.Gson
import spark.Spark
import spark.Spark.get
 
fun main(args: Array<String>) {
 
    val gson = Gson();

    
    // this is folder under src/main/resources  to serve static files.
    Spark.staticFileLocation("/public"); 
 
    get("/hello", { req, res -> "Hello World" }); 
    get("/hello/:name", { req, res -> "Hello " + req.params(":name") }); 
    get("/name/:fname/:lname/json", { req, res -> Name(req.params(":fname"), req.params(":lname")) }, { obj -> gson.toJson(obj) });
 
 
    // lets use function to render json, here 'it' is the implicit parameter as in groovy. 
    val toJson : (Any) -> String = {gson.toJson(it)}
 
    // some user to render as json. 
    val addr = Address("street 1", "NY", "US");
    val user = User(Name("Fazal", "Khan"), "faz@gmail.com", addr)
  
    get("/user/json", { req, res -> user }, toJson); 
 
 
// lets define some data classes.

 
data public class Name(val fname: String, val lname: String)
data public class User(val name: Name, val email: String, val address: Address) 
data public class Address(val street: String, val city: String, val country: String) 
 

Friday, July 24, 2015


Implementing Stack & Queue in go (golang)



First lets define the interface for Stack,

type Stack interface {
    Push(value interface{})
    Pop() (interface{}, bool)
    Peek() (interface{}, bool)
    HasNext() bool
    Len() int
}

We can use the doubly linked from "container/list" to implement our Stack,
just import "container/list"

Define a type which implements our Stack interface,

type stack struct{
    list *list.List
}


We can have constructor which returns the stack instance,
func NewStack() Queue{
    return &stack{list: list.New()}
}

We can leverage the PushFront() and Front() list methods to push values to the head
and get hold of the first element

func (this *stack) Push(value interface{}){
    this.list.PushFront(value)
}

The Front() method return a pointer to Element type in list package,
the actual value in list is stored in Element's Value field.


func (this *stack) Pop() (interface{}, bool){
    e := this.list.Front()
    if e == nil{
        return nil,false
    }
    this.list.Remove(e)
    return e.Value,true
}

similarly we can implement Peek(), we just skip the Remove() from Pop.

Len() and HasNext() can leverage the Len() method of list,

func (this *stack) Len() int{
    return this.list.Len()
}

func (this *stack) HasNext() bool{
    return this.list.Len() != 0
}





On the same lines we can implement Queue by leveraging
list.PushBack() method in Push() of Queue method.

Wednesday, July 8, 2015

Implementing Set backed by map in golang

Here is the simple implementation of set

We can define the interface as 

type Set interface { Add(data interface{}) Delete(data interface{}) bool Contains(data interface{}) bool Size() int ToArray() []interface{} Print() }

lets define a type which implements our Set interface,

type set struct {
  mymap map[interface{}]struct{}
  empty struct{}
}
the map is the actual data holder here.
here is the implementation for the Set interface method.

func NewSet() Set { return &set{mymap: make(map[interface{}]struct{})} } func (this *set) Add(data interface{}) { this.mymap[data] = this.empty }
// there may be a better approach func (this *set) Delete(data interface{}) bool { _, ok := this.mymap[data] if ok { delete(this.mymap, data) } return ok } func (this *set) Contains(data interface{}) bool { _, ok := this.mymap[data] return ok } func (this *set) Size() int { return len(this.mymap) } func (this *set) ToArray() []interface{} { size := len(this.mymap) arr := make([]interface{}, size) i := 0 for k, _ := range this.mymap { arr[i] = k i++ } return arr }


Tuesday, July 7, 2015

Checking for nil in go (golang)

Well, am trying to check for nil in golang,

Looks like this utility may help

func IsNil(i interface{}) bool {
    if i == nil {
        return true
    }
    val := reflect.ValueOf(i)
    kind := val.Kind()
    switch kind {
    case reflect.Ptr, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Interface:
        return val.IsNil()
    }
    return false
}
need to import "reflect" package.

Saturday, July 4, 2015

Using JSch to download files.

JSch is a popular java library to connect to SSHD server.

Here is the code listing which connects to the SSHD server to download and upload files.

package com.mm.ftpclient;

import java.io.Closeable;
import java.io.FileInputStream;
import java.util.List;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

public class SftpUtil {

// can be used to filter the files, not implemented here.
public interface LsEntryFilter{
boolean accept(LsEntry e);
}

public static Session getSession(String hostIp, String username, String password)
        throws Exception {
log("SFTPUtil : entering getSession....");
JSch jsch = new JSch();
Session session = jsch.getSession(username, hostIp);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
log("SFTPUtil : exiting getSession....");
return session;
}

public static ChannelSftp getChannelSftp(Session session) throws Exception {
Channel channel = session.openChannel("sftp");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();

ChannelSftp sftpChannel = (ChannelSftp) channel;
return sftpChannel;
}


// updloads the src file to remote server.
public static void uploadFile(Session session, String srcFile, String destFile)
        throws Exception {
log("SFTPUtil : Entering uploadFile.....");

ChannelSftp sftpChannel = getChannelSftp(session);
FileInputStream is = new FileInputStream(srcFile);

try {
sftpChannel.put(is, destFile);
} finally {
close(is);
if (sftpChannel != null)
sftpChannel.disconnect();
}
log("SFTPUtil : Exiting uploadFile.....");
}

public static void downloadFile(Session session, String srcDir, String destDir,
        String fileName) throws Exception {
ChannelSftp sftpChannel = getChannelSftp(session);
List<ChannelSftp.LsEntry> list = getFiles(sftpChannel, srcDir, destDir);
try {
log("SFTPUtil : ls command output is :" + list);
for (ChannelSftp.LsEntry file : list) {
if (!file.getAttrs().isDir() && file.getFilename().equals(fileName)) {
log("SFTPUtil : downloading file to local working dir, filename is : [" +                                                      file.getFilename() + "]");
sftpChannel.get(file.getFilename(), file.getFilename());
}
}
} finally {
if (sftpChannel != null)
sftpChannel.disconnect();
}
}


public static List<ChannelSftp.LsEntry> getFiles(ChannelSftp sftpChannel, String srcDir,
        String destDir) throws Exception {

sftpChannel.lcd(destDir);
log("SFTPUtil : local working dir: " + sftpChannel.lpwd());

sftpChannel.cd(srcDir);
log("SFTPUtil : remote working dir: " + sftpChannel.pwd());

// Get a listing of the remote directory
@SuppressWarnings("unchecked")
List<ChannelSftp.LsEntry> list = sftpChannel.ls(".");
log("SFTPUtil : running command 'ls .' on remote server : ");

return list;
}



private static void log(String msg) {
System.out.println(msg);
}

private static void close(Closeable is) {
try {
if (is != null)
is.close();
} catch (Exception e) {
}
}

}

Here is the driver code to test

public static void test() throws Exception{
Session session = SftpUtil.getSession("127.0.0.1", "demo", "demo");
session.connect();
try{
List<LsEntry> files = SftpUtil.getFiles(getChannelSftp(session), "/test", "c:/test");
for(LsEntry  file : files){
System.out.println(file.getFilename());
}
}finally{
session.disconnect();
}
}