Wednesday, July 7, 2021

Insert element in linkedlist - Implement in go

 This is 4th post on linked list, for previous post on linkedlist, please check posts from :

https://sreesindhusruthi.blogspot.com/2021/07/create-single-linked-list-in-golang.html

Insert is the function name to insert nodes in linked list:

func (ll *LinkedList) Insert(data int, position int){ }

Step1:  We need to have a Node with the data given. 

temp := new(Node)
temp.data = data

Step2: If linked list is empty then insert the temp Node as head of the linked list.

//This inserts new element as linked list is empty
if ll.head == nil{
ll.head = temp
return
}

Step3: If position is 0 then we need to update the linkedlist head to temp Node and update the current linked list reference.

//This inserts at beginning of the linked list.
if position == 0{
temp.next = ll.head
ll.head = temp
}

Step4: Loop till we reach the position we want to Insert  the Node, we need a variable currentNode to traverse till the desired position, update the currentNode for each iteration of the loop, we will compare the position with currentposition.

var currPosition int
currentNode := ll.head
for currPosition < position-1 && currentNode != nil {
currentNode = currentNode.next
currPosition ++
//fmt.Println(currentNode.data, currPosition)
}

Step5: Once we are at the postion where we have to Insert the node update the linked list references.

Example linked list : 3-->7-->10-->NULL
ll.Insert(4, 2)
Expected output is : 3--> 7--> 4-->10--> NULL

To acheive expected output store Node with data 10 into existingNextNode.

existingNextNode := currentNode.next

Update currentNode links 7--> 4 .

currentNode.next = temp

then traverse currentNode from 7 to 4.

currentNode = currentNode.next

update currentNode next to existingNextNode 4-->10

currentNode.next = existingNextNode
//Update the links
existingNextNode := currentNode.next
currentNode.next = temp
currentNode = currentNode.next
currentNode.next = existingNextNode


Full code:



Print elements of linkedlist - Golang

 This is 3rd post on linked list. For previous posts, pls check the links below:

https://sreesindhusruthi.blogspot.com/2021/07/create-single-linked-list-in-golang.html

https://sreesindhusruthi.blogspot.com/2021/07/length-of-linkedlist-implementation-in.html

Writing print function for linked list to print elements.

The function name is Print and elements data is available in Node.data .

Step1: Check if linked list is empty. If empty print "NULL"

Step2: Print Node.data and update head to next Node in the linkedlist.

The function code is :

func (ll *LinkedList) Print() {
if ll.head == nil{
fmt.Print("NULL")
return
}
//No Intermediate variable is used so we are traversing on
//the actual object created and it's references gets updated on updating ll.head.
for ll.head != nil {
fmt.Printf("%+v -->",ll.head.data)
ll.head = ll.head.next
ll.Print()
}
}

Complete code:


Length of linkedlist - Implementation in golang

 To get started with linkedlist please check previous post on how to create singly linkedlist:

Link is as below:

https://sreesindhusruthi.blogspot.com/2021/07/create-single-linked-list-in-golang.html

Now that we have linked list, let's add function to get the length of the linked list.

In previous post we have Node and LinkedList structs created. 

Writing function for length.

func (ll *LinkedList) Len() int{ }

This is the function defintion takes linkedlist as input and integer as return type.

Let's write the logic 

Step1: Intialize variable with count variable. count := 0

Step2: Check if linkedlist is empty.  If it's empty then we return the count as 0.


count := 0
if ll.head == nil{
    return 0
}


Step3: As we have to traverse through linked list we need a variable to traverse to each Node.

count := 0
var temp *Node
if ll.head == nil{
return 0
}
temp = ll.head

Step4: we need to loop till there are no more nodes in linkedlist. so the check would be 

    for temp != nil {}

Step5: now our temp is pointing to head and it;s not nil so will go into the loop, increment the count value, now update temp to next Node of head. 

for temp != nil {
count ++
temp = temp.next
fmt.Println(temp)
}

Prints are added for checking if temp is getting updated as expected.

Complete code of this is:



Create singly linked list in golang

A linked list is a linear data structure, in which the elements are linked to next element using pointers.

The following illustration would help to understand it:  


Let's implement this  in golang:


To create a linked listed we first have to create Node with data and next pointing to the another Node.

To create Node we need two fields, data and next.

Step1:

type Node struct{
data int
next *Node
}

Step2:

Now define Linkedlist struct:

type LinkedList struct{
head *Node
}

Step3:

Now that we have defined structs that we need, let's try creating Node and linkedlist .

func main(){
node1 := new(Node)
fmt.Println(node1)
}

Here when we create new node it will have default values of each field which here is 0 and nil.
so printing node1 would give the output as:

&{0 <nil>}

We now need a way to initialise Node struct with our values.

Step4:

Writing a function to do this:
func (n *Node) NewNode(data int, next *Node){
n.data = data
n.next = next
}

Step5:

with this new function we will change the code in main() function

func main(){
node1 := new(Node)
fmt.Println(node1)
node1.NewNode(1, nil)
fmt.Println(node1)
}

Now we the second print statement gives node1 output as &{1 <nil>}

The reason that `next` field is showing it as nil is because we just created one Node and there is no other Node where we can link this node1 to.


Step6:

Let's created linkedlist with this Node:

func main(){
node1 := new(Node)
fmt.Println(node1)
node1.NewNode(1, nil)
fmt.Println(node1)
llist := new(LinkedList)
llist.head = node1
}

Now we have created linked list with it's head pointing to our Node1.

Our linked list would now be like this:



Step7:

Let's create Node2 and update our linkedlist.

func main(){
node1 := new(Node)
fmt.Println(node1)
node1.NewNode(1, nil)
fmt.Println(node1)
llist := new(LinkedList)
llist.head = node1
node2 := new(Node)
node2.NewNode(2, nil)
llist.head.next = node2
}

The last three lines of code we have created new Node which is same as step5, 

now that we have to update our existing linkedlist the update that we have to do is head is pointing to Node1 i.e. head = Node1 now Node1.next has to be pointing to Node2.

Node1 is head here so head.next = node2 will update our linked list as below:



Step8:

For the last step let's create another Node and update our linked list:

func main(){
node1 := new(Node)
fmt.Println(node1)
node1.NewNode(1, nil)
fmt.Println(node1)
llist := new(LinkedList)
llist.head = node1
node2 := new(Node)
node2.NewNode(2, nil)
llist.head.next = node2
node3 := new(Node)
node3.NewNode(3, nil)
llist.head.next.next = node3
}

This will have our linked list as in first figure.

The complete code is:






Tuesday, May 12, 2020

Envoy with grpc Access logs

What is Envoy

Envoy is an L7 proxy and communication bus designed for large modern service oriented architectures. The project was born out of the belief that:

The network should be transparent to applications. When network and application problems do occur it should be easy to determine the source of the problem.

In practice, achieving the previously stated goal is incredibly difficult. Envoy attempts to do so by providing the following high level features:

More details about envoy documentation available at:  https://www.envoyproxy.io/docs/envoy/latest/about_docs

Now let's start implementing envoy as side-car along with our application containers and run it in a single pod:

This implementation is specific to kubernetes environment.

Envoy can be part of side car for any application and communication to application happens through envoy. Any inbound traffic will be done through envoy and envoy will have listeners , routing configured.

This can be done through grpcImplementations or with yaml configuration. These will be registered with envoy XDS Apis and envoy will know where to reach for communicating with application.

Here we will look at envoy yaml configuration:

envoy-grpcconfig.yaml

Here we have configured listeners , filters and routes.

Envoy Configuration:

Envoy is listening  at port 9902 in local host. This is where we can get /stats.

Application configuration:

In routes, we specified details of the cluster that matches with a pattern.

For each of the matching pattern envoy routes it to the cluster specified under virtual_hosts.Cluster details are specified under Clusters. The application will be served for this example with cluster name as service_c.

The host address and port details for service_c is where test application is served.

Grpc Access logs:

Under filters,we have specfied the configuration for access_log.

Here we are specifying it as envoy.http_grpc_access_log. Grpc Access logs details can. be found at

https://github.com/envoyproxy/envoy/blob/d90464cace696da61248d3999081c3c0d22a725b/api/envoy/data/accesslog/v2/accesslog.proto

More options on configuring access logs can be found at

https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/observability/access_logging

The yaml config emits access_logs for upstream systems.

Grpc AccessLogService Implementation:

For grpc we have to implement grpc server for AccessLogService.

Code is available at :https://github.com/sreesindhusruthiyadavalli/envoy-grpc/tree/master

Build the docker image and deploy it in a pod.

Please check kubernetes apply -f <deployment.yaml>/<service.yaml> for deployment and service configuration for any pod.I have given service name as 'envoy-grpc'.

Kubectl get services --> List of services available in kubernetes cluster.

It gives envoy-grpc as service name for grpc AccessLogService.

Now in envoy configuration we have to configure access logs which has to be communicated with the above service.

Under clusters give the service host address(envoy-grpc.default.svc.cluster.local) and add strict_dns to the access_log_cluster.

Build envoy with the yaml configuration and invoke an api inside the test application.

Enter into envoy pod: curl 127.0.0.1:8789/<resource>

This gives the response from the application.

Now check the logs of envoy-grpc pod.We will get to see the accesslog.