#-*- coding: utf-8 -*-

# Copyright 2012-2013 Calculate Ltd. http://www.calculate-linux.org
#
#  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.

import os, glob, sys
import time, datetime
import pickle
from calculate.core.datavars import DataVarsCore
from calculate.lib.cl_lang import setLocalTranslate
setLocalTranslate('cl_core3',sys.modules[__name__])

# clear server files after restart
def clean (SID_FILE, PID_FILE, SID_PID, SIDS_DIR, PIDS_DIR):
    if os.path.exists(SID_FILE):
        os.unlink(SID_FILE)
    if os.path.exists(PID_FILE):
        os.unlink(PID_FILE)
    if os.path.exists(SID_PID):
        os.unlink(SID_PID)

    if os.path.isdir(SIDS_DIR):
        for filename in glob.glob(os.path.join(SIDS_DIR, "*.sid")):
            os.unlink (filename)
            if os.path.exists(filename):
                print 'Not deleted file %s!!!' %filename
    if os.path.isdir(PIDS_DIR):
        for filename in glob.glob(os.path.join(PIDS_DIR, "*.pid")):
            os.unlink (filename)    

class CoreWsdl:
    # watch for process
    def watcher_pid_proc(self, sid, pid):
        period = 2
        time.sleep(period)
        try:
            # while process status "Active"
            while self.glob_process_dict[pid]['status'] == 1:
                # frequency check
                time.sleep(period)
                
            self._delete_pid(sid, pid)
        except IOError:
            print 'Except IOError'
        except Exception:
            print _("PID %d watcher error") %pid
            try:
                self._delete_pid(sid, pid)
            except:
                pass
            time.sleep(0.1)

    def _delete_pid(self, sid, pid):
        while len(self.glob_frame_list[pid]) > \
                  self.glob_process_dict[pid]['counter']:
            time.sleep(1)
        methodname = self.glob_process_dict[pid]['method_name']
        if methodname:
            self.clear_cache(sid, methodname)
        self.del_pid(pid)
        self.del_pid_from_sid_pid(pid)
            
def monitor(certbase, SID_FILE):
    """ function to delete old session """
    # set default
    period = 180
    sid_live = 240
#    cert_live = 10080
    # Get value of period and lifetime session from DataVars
    try:
        ob = DataVarsCore()
        ob.importCore()

        if not ob.flIniFile():
            sys.exit(1)
        period = float(ob.Get('cl_core_monitor_period'))
        sid_live = float(ob.Get('cl_core_sid_live'))
    except:
        print _("Variable cl_core_monitor_period or cl_core_sid_live not "
                "found")
        raise
        return 1
    # Check lifetime. if necessary, remove
    while True:
        # check session
        try:
            SID_FILE_T = SID_FILE + '_temp'
            fd = open(SID_FILE, 'r')
            ft = open(SID_FILE_T, 'w')
            while 1:
                try:
                    # read all on one record
                    list_sid = pickle.load(fd)
                except:
                    break
                # how time exists session
                delta = datetime.datetime.now() - list_sid[2]
                # if not outdated, then leave
                if (delta.seconds < sid_live * 60):
                    pickle.dump(list_sid, ft)
            fd.close()
            ft.close()
            
            # copy all from temp file
            ft = open(SID_FILE_T, 'rb')
            fd = open(SID_FILE, 'wb')
            ft.seek(0)
            fd.write(ft.read())
            ft.close()
            fd.close()
            
            # Delete temp file
            os.unlink(SID_FILE_T)
        except:
            return 1
        
        # Частота проверки
        time.sleep(60 * period)

# check client's presence
def sid_monitor(SID_FILE, SIDS_DIR):
    # check interval
    period = 21
    while True:
        try:
            sids = []
            # create, if file not exists
            if not os.path.exists(SID_FILE):
                temp = open(SID_FILE, 'w')
                temp.close()
            fd = open(SID_FILE, 'r')
            while 1:
                try:
                    # read all on one record
                    list_sid = pickle.load(fd)
                except:
                    break
                # add session id in sesession list
                sids.append(list_sid[0])
            fd.close()
        except:
            print _("Error reading SID files")
            return
        
        try:
            # for each session
            for filename in sids:
                # find file this session
                sid_path = SIDS_DIR + "/%d.sid"%filename
                if os.path.isfile(sid_path):
                    with open(sid_path) as fd:
                        # read information about session
                        sid_inf = pickle.load(fd)
                        # if number of missed inspections more 3
                        if sid_inf[1] > 3:
                            # flag client absence
                            sid_inf[2] = 1
                    fd.close()
                    if os.path.isfile(sid_path):
                        ft = open(sid_path, 'w')
                        # add to digit missed inspections
                        # client constantly nulls this value!
                        if sid_inf[1] < 4:
                            sid_inf[1] += 1
                            pickle.dump(sid_inf, ft)
                            ft.close()
        except:
            pass
        # check period
        time.sleep(period)
