Using concurrent.futures to do Multithreading

Using concurrent.futures to download a list of urls and store the result in another list.

import concurrent.futures

import requests

def get_requests(url, data_list):

    resp = requests.get(url)


URLs = [”,”]


data_list = []

with concurrent.futures.ThreadPoolExecutor(max_workers=NUMBER_OF_THREADS) as executor:

    future_to_url = {executor.submit(get_requests, url, data_list):

                     url for url in URLs}

print data_list


How to Setup Static or Dynamic IP Addresses on Debian based Linux Systems

$ sudo vim /etc/network/interfaces

Set a dynamic IP address:

This is how a network having an dynamic IP address (got from a dhcp server) is configured.

auto eth0
iface eth0 inet dhcp


  • auto eth0 – enable at startup the eth0 interface
  • iface eth0 inet dhcp – consider that iface eth0 comes from interface eth0, inet tells you that the network configuration is IPv4 and dhcp that the dynamic ip is assigned by a dhcp server.

Set a static IP address

We have a little more work to do for configurationg a network interface with a static IP address. Edit your/etc/network/interfaces file again, so that it looks like this (these are my IP addresses, replace them with yours.) :

auto eth0
iface eth0 inet static


  • auto eth0 – enable at startup the eth0 interface
  • iface eth0 inet static– consider that iface eth0 comes from interface eth0, inet tells you that the network configuration is IPv4 and static that your network interface has static ip adresses.
  • address – the network’s IP address
  • netmask – the network’s mask address
  • network – the network’s address
  • broadcast – the broadcast address
  • gateway – the gateway address

It is not necesarry to insert the network and broadcast lines in the /etc/network/interfaces file because the system calculates them from the address and the netmask fields.

So, your network interface file could also look like this, for static IP configurations:

auto eth0
iface eth0 inet static

Set the network’s DNS server:

To set the DNS server address, you have to edit the /etc/resolv.conf file, with root priviledges:

$ sudo vim /etc/resolv.conf

The /etc/resolv.conf file, should look like this:

name server is Google’s private DNS address. You can replace with another DNS address, but everything works perfect with the Google DNS.

Reboot the networking service:

All the configurations that are made in configuration files, are persistent. They don’t apply before you reboot the service, but they will not be discarded after reboot. This is how you reboot the network service, to apply the changes:

$ sudo /etc/init.d/networking restart




How to Setup Static or Dynamic IP Addresses on Debian based Linux Systems

Basic Linux security


—–>  Keep your software upto date

Check if your software is up to date:

$sudo apt-get update

(This command updates your package source list. After this the system is aware what all software is available and the most recent versions )

$sudo apt-get upgrade

(This command would actually go ahead and update the software to the latest versions)

$sudo apt-get autoremove

(Removes not nedded software)

$sudo apt-install finger

(Install a software called finger.)


Install finger


(Gives all the user that are logged in currently)

$finger username

(Gives more info about the  user called username)

Finger gets most of the info from a file called ‘/etc/passwd’. This files is used to store user information.

$cat /etc/passwd |grep vagrant

vagrant:x:1000:1000:Vagrant user decscripton:/home/vagrant:/bin/bash

(Here I am getting info for a user called vagrant)

Each field in the output is separated by a ‘:’

vagrant –> username

x –> encrypted password of the user (Not used anymore)

1000 —> User id (0 for root)

1000 —> group id (0 for root)

Vagrant user decscripton —> User description

/home/vagrant —> home directory

/bin/bash –> shell

One should never be able ssh to a server as a root. 

You can create a user

$sudo adduser username

Give the new user sudo access. You can add the new user in the ‘/etc/sudoers’. But in ubuntu instead of directly adding it in this file which can be overwritten on an update you can also add the user to the ‘/etc/sudoers.d’ directory.

You can add your new user here. Here is a link for more info on sudoers

You can expire the password of this user so that he is forced to create a new secure one since now that he is added to the sudoers list.

$sudo passwd -e username


You should always use public private key authentication (RSA).

Generate a rsa key pair and always USE A PASSPHRASE!!

Disable ssh through password authentication.

$sudo nano /etc/ssh/sshd_config

In this file search for ‘passwordAuthentication yes’ change it to ‘passwordAuthentication no’. Restart ssh service.

File Permissions:

We use chmod to change file permission. But what exactly are file permission.

$ ls -al

-rw-r–r– 1 vagrant vagrant 3637 Apr  9  2014 .bashrc

We are interested in ‘rw-r–r–‘ (The first ‘-‘ represents wether it is a directory or a file)

These are basically divided in three groups

Owner : ‘rw-‘

Group : ‘r–‘

Everyone: ‘r–‘

This basically tells us which user or group of users is allowed to what with the particular file.

r: read permission

w: write permission

– : not permitted

x : allowed to execute this file

Octal permissions:

r –> 4

w –> 2

x –> 1

So to represent ‘rw-r–r–‘ in octal form we just add the values



$chmod 644 filename

Will make the filename permssions to be ‘rw-r–r–‘


Ubuntu comes with a firewall called ‘ufw’. You can check the status using

$sudo ufw status

Good rule of thumb is to start with denying all incoming traffic.

$ sudo ufw default deny incoming

Also we should allow all outgoing traffice

$sudo ufw default allow outgoing

Now open only the ports you need to use

$sudo ufw allow ssh

(This will open the port 22 to allow us to ssh to the server)

$sudo ufw allow www

(Open port 80 for http traffic)

Implement LRU Cache

How to implement LRU caching scheme? What data structures should be used?

We are given total possible page numbers that can be referred. We are also given cache (or memory) size (Number of page frames that cache can hold at a time). The LRU caching scheme is to remove the least recently used frame when the cache is full and a new page is referenced which is not there in cache. Please see the Galvin book for more details (see the LRU page replacement slide here).

We use two data structures to implement an LRU Cache.

1. A Queue which is implemented using a doubly linked list. The maximum size of the queue will be equal to the total number of frames available (cache size).
The most recently used pages will be near front end and least recently pages will be near rear end.

2. A Hash with page number as key and address of the corresponding queue node as value.

When a page is referenced, the required page may be in the memory. If it is in the memory, we need to detach the node of the list and bring it to the front of the queue.
If the required page is not in the memory, we bring that in memory. In simple words, we add a new node to the front of the queue and update the corresponding node address in the hash. If the queue is full, i.e. all the frames are full, we remove a node from the rear of queue, and add the new node to the front of queue.

Note: Initially no page is in the memory.


Rest API Design guidelines and best practices

When designing an api you should think about

  • naming
  • Proper http verbs and response codes for different CRUD operations
  • Think about versioning.

General guidelines to keep in mind:

-> Always prefer to use lowercase characters in uri’s. A forward slash should be used to indicate a hierarchical relationship. Also a trailing forward slash should be not be included. Hyphens (-) can be used for better readability but underscores ( _ ) should not be used.

Note: File extensions like ‘json’ or ‘xml’ should not be used to indicate a format preference. You should look at the ‘Content-Type’ header to determine how to process the body’s content.

-> The uri path should convey the resource model with each segment path identifying an addressable resource.

-> The actual words in the path should either be a singular ,plural  noun or a verb.

Note: Do not use CRUD function names in the uri’s. You can use the query component of the uri for pagination.


-> GET and POST must not be used to tunnel other request methods

->  POST must be used to execute controllers

-> HEAD should be used to retrieve response headers

Response Codes:

200 (OK) Non-specific Success.Must not be used to communicate errors in response body.
201 (OK) Successful resource creation.
204 (No content) Used when response body is intentionally empty
301(“Moved Permanently”) Should be used to relocate resources
302 (“Found”) Should not be used
303 (“See Other”) Should be used to refer the client to a different URI
307 (“Temporary Redirect”) Should be used to tell clients to resubmit the request to another URI
400 (“Bad Request”) Used to indicate nonspecific failure
401 (“Unauthorized”) Used when there is a problem with the client’s credentials
403 (“Forbidden”) Used to forbid access regardless of authorization state
404 (“Not Found”) Used when a client’s URI cannot be mapped to a resource
405 (“Method Not Allowed”) Used when the HTTP method is not supported
406 (“Not Acceptable”) Used when the requested media type cannot be served
415 (“Unsupported Media Type”) Used when the media type of a request’s payload cannot be processed
500 (“Internal Server Error”) Used to indicate API malfunction

HTTP Headers:

-> Content-Type, Content-Length should be used

Note: Cache-Control, Expires, and Date response headers should be used to encourage caching.Expiration caching headers should be used with 200 (“OK”) responses

-> Custom HTTP headers must not be used to change the behavior of HTTP methods

Error Representation

A consistent form should be used to represent errors and error responses.Consistent error types should be used for common error conditions.

Bitwise AND between a range of integers

Problem Statement

You will be given two integers A and B. You are required to compute the bitwise AND amongst all natural numbers lying between A and B, both inclusive.

Since & is only 1 when both are 1 and when calculating in a range if the range ends do not both have 1 the rest of the whole binary is 0

The only bits that will be 1 will be bits that are common to the upper bits of A and B. Everything else will have at least one instance of a 0 in that range. So just start from the high order bit downwards. Output the matching bits. As soon as you hit a disagreement between the binaries of A and B (which will be 0 in A and 1 in B) output zeros until you get to the length of B.

def bitAndWholeArray(arr):
string1 = bin(arr[0])
string2 = bin(arr[1])
index_count = 0
res = ‘0b’
for index,i in enumerate(string1):
if index == 0 or index == 1:
if i == string2[index]:
res = res + i
index_count = index

for _ in range(index_count,len(string2)):
res = res + ‘0’

return int(res,2)
n = int(raw_input())
for _ in range(n):
arr = map(int,raw_input().split(‘ ‘))
print bitAndWholeArray(arr)