Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have two text files:

file #1: domain.txt

cocacola.com
airtel.com
pepsi.com

file #2: servers.txt

192.0.53.42 , 4    # 4 domains already allocated on server 192.0.53.42
192.53.1.2 , 1     # 1 domains already allocated on server 192.53.1.2
192.36.155.21 , 2  # 2 domains already allocated on server  192.36.155.21

I need to write a script, which will allocate each domain (one by one from top to bottom from domains.txt) to the server (to server.txt) which has the minimum load at a given instant (if there is a tie in minimum load then the the server is allocated with FCFS).

Finally I want to write a script to do as above then create a new file with modifications named: allocation.txt.

In the above example allocation.txt as a output will have (after execution of script):

192.0.53.42 , 4
192.53.1.2 , 3 , cocacola.com , airtel.com
192.36.155.21 , 3 , pepsi.com

I am a newbie to scripting, and would appreciate any help/guidance!

What would be your basic approach to solving this problem? Can all this be accomplished by one script?

share|improve this question
    
can you please add more domain in example and expected output.. –  Rahul Patil Apr 29 '13 at 2:17
    
Do not see the connection between file #1, file #2 and allocation.txt. How do you decide that there should be two domains on line two, and what makes line two increase count by 2 and line 3 by 1? –  Sukminder Apr 29 '13 at 10:31
add comment

2 Answers

up vote 1 down vote accepted

The following python script should do what you want:

#!/usr/bin/python
serv=[]
for l in open("servers.txt","r").xreadlines():  # for each server
    s,n = l.split(",") # extract server name and load
    n=int(n.split("#")[0].strip()) # ignore comments
    serv.append([s.strip(),n]) # store server and its load
for l in open("domain.txt","r").xreadlines(): # for each domain
    m = serv.index(min(serv,key=lambda i:i[1])) # find server with lowest load
    serv[m].append(l.strip()) # add the domain
    serv[m][1]=serv[m][1]+1 # increase the load
alloc=open("allocation.txt","w")
for l in serv:
    print>>alloc, " , ".join([l[0],str(l[1])] + l[2:]) # write output file
share|improve this answer
    
How you increasing load, in which basis ? –  Rahul Patil May 2 '13 at 2:18
    
@RahulPatil The load is the second column in servers.txt. Each time a new domain is distributed to a server, the program increases this number.BTW, I changed my program such that the internal ordering in the serv variable is the same as in the output file. –  jofel May 2 '13 at 8:19
    
that's exactly did in my bash script then why down vote ? –  Rahul Patil May 2 '13 at 8:53
    
@RahulPatil Yes, your scripts includes this logic, but it is not general, it works only for the given example in the question with one load "1" and one "2", but not in most other cases where the load is different distributed or if many more domains need to be added. –  jofel May 2 '13 at 10:04
    
hmmm.. interesting.. –  Rahul Patil May 2 '13 at 16:49
add comment

Instead of storing the information in flat text files, you could make use of the file system. For instance, have one file per IP address in your pool. Allocating a domain to the IP address would be linking a domain file to the IP address file. Then you know what's the current allocation for the IP address by looking at the number of links (which is an information readily available since it's stored in the inode). And you don't have to worry about rewriting flat files each time and guarantee exclusive access to those flat files. You can use other attributes of the file (like mtime, ctime, uids) to store other information about the IP addresses.

For example:

$ ls -lRi
.:
total 8
59597091 drwxr-xr-x 2 chazelas chazelas 4096 May  1 10:12 domain/
59597087 drwxr-xr-x 2 chazelas chazelas 4096 May  1 10:11 ip/

./domain:
total 28
59554312 -rw-r--r-- 5 chazelas chazelas 12 May  1 10:11 test1.com
59554312 -rw-r--r-- 5 chazelas chazelas 12 May  1 10:11 test2.com
59554312 -rw-r--r-- 5 chazelas chazelas 12 May  1 10:11 test3.com
59554312 -rw-r--r-- 5 chazelas chazelas 12 May  1 10:11 test4.com
59554314 -rw-r--r-- 2 chazelas chazelas 11 May  1 10:11 test5.com
59562599 -rw-r--r-- 3 chazelas chazelas 14 May  1 10:11 test6.com
59562599 -rw-r--r-- 3 chazelas chazelas 14 May  1 10:11 test7.com

./ip:
total 12
59554312 -rw-r--r-- 5 chazelas chazelas 12 May  1 10:11 192.0.53.42
59562599 -rw-r--r-- 3 chazelas chazelas 14 May  1 10:11 192.36.155.21
59554314 -rw-r--r-- 2 chazelas chazelas 11 May  1 10:11 192.53.1.2

Above, the number of links (5, 3, 2) is one plus the number of domains allocated to the IP address.

(re-)allocating a domain is then just a matter of:

#! /bin/zsh -
domain=domain/$1
rm -f $domain
least_loaded_ip=(ip/*(ol[1]))
ln -f $least_loaded_ip $domain

De-allocating is just

#! /bin/zsh -
domain=domain/$1
rm -f $domain

Getting the IP for a domain is just

#! /bin/zsh -
domain=domain/$1
cat $domain

(assuming the file contains the IP address)

Getting the list of domains allocated to an IP address (with GNU find).

#! /bin/zsh -
ip=ip/$1
find domain -samefile $ip -printf '%P\n'

Then as a bonus, the ctime of the file is the last time a domain was allocated or deallocated to it. You could also use the mtime (using touch) to store another time related to it.

It uses one inode per IP address. If your filesystems have indexed/hashed directories, then getting the IP address for a domain would be very quick. All the ln and rm operations are atomic so two concurrent calls to those scripts would not mess things up.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.