'''
Created on Mar 11, 2011
Modified on Aug 19, 2012
@author: Dilum Bandara
@version: 0.11
@license: Apache License v2.0

   Copyright 2012 H. M. N. Dilum Bandara and Anura P. Jayasumana, Colorado State
   University

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
'''


'''
Extract time serie partitions from given data.
Support PlanetLab data
'''

import sys

if len(sys.argv) != 2: 
    print 'Incorrect command. should be Python extractTSParti.py <default_split>'
    sys.exit(0)
defaultSplit = int(sys.argv[1]) #Default partition size if time series is not already split

fPartitions = 'partitions_window.txt'
#fPartitions = 'partitions_strucchange_formatted.txt'
fCPUSpeed = 'CPUSpeed.txt'
fNumCores = 'NumCores.txt'
fMemSize = 'MemSize.txt'
fCPUFree = 'CPUFree.txt'
fOneMinLoad = '1MinLoad.txt'
fFiveMinLoad = '5MinLoad.txt'
fFifteenMinLoad = '15MinLoad.txt'
fMemFree = 'MemFree.txt'
fDiskFree = 'DiskFree.txt'
fTxRate = 'TxRate.txt'
fRxRate = 'RxRate.txt'
fRespTime = 'RespTime.txt'
fOut = 'TSLibrary_window.txt'
#fOut = 'TSLibrary_strucchange.txt'

class Node(object):
    def __init__(self, partitions):
        self.partitions = partitions
        self.cpuSpeed = -1
        self.numCores = -1
        self.memSize = -1
        self.cpuFree = []
        self.oneMinLoad = []
        self.fiveMinLoad = []
        self.fifteenMinLoad = []
        self.memFree = []
        self.diskFree = []
        self.txRate = []
        self.rxRate = []
        self.respTime = []

#read partitions file
fdPartitions = open(fPartitions, 'r')
numNodes = 0
nodes = {}
for line in fdPartitions:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine)):
        tmpLine[i] = int(tmpLine[i])
    if len(tmpLine) == 1: #No partitions. So split at regular intervals
        maxTime = tmpLine[0]
        tmpPartitions = []
        for k in range(1, int(maxTime/defaultSplit + 1)):
            tmpPartitions.append(defaultSplit * k)
        if tmpPartitions[-1] != maxTime: tmpPartitions.append(maxTime)
        tmpLine = tmpPartitions
    nodes[numNodes] = Node(tmpLine)
    numNodes += 1
fdPartitions.close()
print 'End reading config file. Nodes', numNodes

#Read data
fdIn = open(fCPUSpeed, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine) - 1): #For each column. Skip '\n'
        nodes[i].cpuSpeed = tmpLine[i]
    break #Read only 1st line for static attributes
fdIn.close()

fdIn = open(fMemSize, 'r')
for line in fdIn:
    tmpLine = line.split('\t') #remove \n
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].memSize = tmpLine[i]
    break #Read only 1st line for static attributes
fdIn.close()

fdIn = open(fNumCores, 'r')
for line in fdIn:
    tmpLine = line.split('\t') #remove \n
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].numCores = tmpLine[i]
    break #Read only 1st line for static attributes
fdIn.close()

fdIn = open(fCPUFree, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine)- 1): #For each column
        nodes[i].cpuFree.append(tmpLine[i])
fdIn.close()

fdIn = open(fOneMinLoad, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].oneMinLoad.append(tmpLine[i])
fdIn.close()

fdIn = open(fFiveMinLoad, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].fiveMinLoad.append(tmpLine[i])
fdIn.close()

fdIn = open(fFifteenMinLoad, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].fifteenMinLoad.append(tmpLine[i])
fdIn.close()

fdIn = open(fMemFree, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].memFree.append(tmpLine[i])
fdIn.close()

fdIn = open(fDiskFree, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].diskFree.append(tmpLine[i])
fdIn.close()

fdIn = open(fTxRate, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].txRate.append(tmpLine[i])
fdIn.close()

fdIn = open(fRxRate, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].rxRate.append(tmpLine[i])
fdIn.close()

fdIn = open(fRespTime, 'r')
for line in fdIn:
    tmpLine = line.split('\t')
    for i in range(len(tmpLine) - 1): #For each column
        nodes[i].respTime.append(tmpLine[i])
fdIn.close()

print 'End reading data...'

#Partition time series
fdOut = open(fOut, 'w')
fdOut.write('#CSp\tNCore\tMSize\n')
fdOut.write('#CFree\t1mLd\t5mLd\t15mLd\tMFree\tDFree\tTx\tRx\tRspT\n') #Write format of output
maxSampleLen = -1
for i in nodes:
    for j in range(len(nodes[i].partitions)):
        tmpStr = nodes[i].cpuSpeed + '\t' + nodes[i].numCores + '\t' + nodes[i].memSize + '\t' 
        if j == 0: 
            tmpLen = nodes[i].partitions[j]
            start = 0
        else: 
            tmpLen = nodes[i].partitions[j] - nodes[i].partitions[j - 1] 
            start = nodes[i].partitions[j - 1]      
        if tmpLen > maxSampleLen: maxSampleLen = tmpLen

        tmpStrCFree = ''
        tmpStr1mLd = ''
        tmpStr5mLd = ''
        tmpStr15mLd = ''
        tmpStrMFree = ''
        tmpStrDFree = ''
        tmpStrTx = ''
        tmpStrRx = ''
        tmpStrRspT = ''
        aveCFree = 0.0
        ave1mLd = 0.0
        ave5mLd = 0.0
        ave15mLd = 0.0
        aveMFree = 0.0
        aveDFree = 0.0
        aveTx = 0.0
        aveRx = 0.0
        aveRspT = 0.0

        for k in range(start, nodes[i].partitions[j]): #Extract time series
            tmpStrCFree += nodes[i].cpuFree[k] + '\t'
            aveCFree += float(nodes[i].cpuFree[k])
        aveCFree = aveCFree/(nodes[i].partitions[j] - start)

        for k in range(start, nodes[i].partitions[j]): #Extract time series
            tmpStr1mLd += nodes[i].oneMinLoad[k] + '\t'
            ave1mLd += float(nodes[i].oneMinLoad[k])
        ave1mLd = ave1mLd/(nodes[i].partitions[j] - start)

        for k in range(start, nodes[i].partitions[j]): #Extract time series
            tmpStr5mLd += nodes[i].fiveMinLoad[k] + '\t'
            ave5mLd += float(nodes[i].fiveMinLoad[k])
        ave5mLd = ave5mLd/(nodes[i].partitions[j] - start)

        for k in range(start, nodes[i].partitions[j]): #Extract time series
            tmpStr15mLd += nodes[i].fifteenMinLoad[k] + '\t'
            ave15mLd += float(nodes[i].fifteenMinLoad[k])
        ave15mLd = ave15mLd/(nodes[i].partitions[j] - start)

        for k in range(start, nodes[i].partitions[j]): #Extract time series
            tmpStrMFree += nodes[i].memFree[k] + '\t'
            aveMFree += float(nodes[i].memFree[k])
        aveMFree = aveMFree/float(nodes[i].partitions[j] - start)

        for k in range(start, nodes[i].partitions[j]): #Extract time series
            tmpStrDFree += nodes[i].diskFree[k] + '\t'
            aveDFree += float(nodes[i].diskFree[k])
        aveDFree = aveDFree/float(nodes[i].partitions[j] - start)

        for k in range(start, nodes[i].partitions[j]): #Extract time series
            tmpStrTx += nodes[i].txRate[k] + '\t'
            aveTx += float(nodes[i].txRate[k])
        aveTx = aveTx/float(nodes[i].partitions[j] - start)

        for k in range(start, nodes[i].partitions[j]): #Extract time series
            tmpStrRx += nodes[i].rxRate[k] + '\t'
            aveRx += float(nodes[i].rxRate[k])
        aveRx = aveRx/float(nodes[i].partitions[j] - start)

        for k in range(start, nodes[i].partitions[j]): #Extract time series
            if k != nodes[i].partitions[j] - 1: tmpStrRspT += nodes[i].respTime[k] + '\t'
            else: tmpStrRspT += nodes[i].respTime[k] #No tab for last entry
            aveRspT += float(nodes[i].respTime[k])
        aveRspT = aveRspT/float(nodes[i].partitions[j] - start)

        tmpStr += str(round(aveCFree, 5)) + '\t' + str(round(ave1mLd, 5)) + '\t' + \
                  str(round(ave5mLd, 5)) + '\t' + str(round(ave15mLd, 5)) + '\t' + \
                  str(round(aveMFree, 5)) + '\t' + str(round(aveDFree, 5)) + '\t' + \
                  str(round(aveTx, 5)) + '\t' + str(round(aveRx, 5)) + '\t' + \
                  str(round(aveRspT, 5)) + '\t'
        tmpStr += str(tmpLen) + '\t'
        tmpStr += tmpStrCFree + tmpStr1mLd + tmpStr5mLd + tmpStr15mLd + tmpStrMFree + \
                  tmpStrDFree + tmpStrTx + tmpStrRx + tmpStrRspT 
        fdOut.write(tmpStr + '\n')
fdOut.close()

print 'Length of longest time series segment', maxSampleLen
