From 291cf6ef987f9fbcda10fa65d3229ce68ca22cb0 Mon Sep 17 00:00:00 2001 From: Jondy Zhao <jondy.zhao@gmail.com> Date: Tue, 28 May 2013 15:22:06 +0800 Subject: [PATCH] Use sqlite3 db to save local data --- windows/netreport/src/netreport.py | 226 +++++++++++------------------ 1 file changed, 84 insertions(+), 142 deletions(-) diff --git a/windows/netreport/src/netreport.py b/windows/netreport/src/netreport.py index bc36f72..99fc5eb 100644 --- a/windows/netreport/src/netreport.py +++ b/windows/netreport/src/netreport.py @@ -26,95 +26,16 @@ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## -# -# Paramters: -# -# computer_id, which computer sends this report -# -# server_name, if it's not empty, only the net drives in this server -# will be involved in the report. -# -# report_internal, in seconds -# -# data_file, save report state and unsending records last time, pickle format. -# -# main process -# -# read data from data file (pickle) -# -# check start state, there are 3 cases -# -# case 1: first report -# -# Send init report to server -# -# case 2: normal report -# -# case 3: unexpected error -# -# Request server to send back last report information -# -# If there are unsend reports in json file, send them first -# -# Start sending report thread, the thread will enter loop as the following: -# -# Are there unsend records? -# -# Yes, send those. -# -# Resend failed, insert the records in the current buffer to unsending queue. -# -# No. -# -# Send records in the current buffer -# -# Failed, insert all the records in the currnet buffer to unsending queue. -# -# If main process quit? -# -# Enter main loop: -# -# If report interval is out, -# -# Yes, insert a record to the current bffer -# -# No, sleep for (report_interval / 2 + 1) seconds -# -# If user wants to quit -# -# Yes, break main loop -# -# After quit from main loop, -# -# Stop sending report thread -# -# Save unsending queue, report id and state to pickle file. -# -# -# Interface of computer: -# -# reportNetDriveUsage will post a list of record: -# -# (computer_id, sequence_no, timestamp, duration, -# domain, user, usage, remark) -# -# getReportSequenceNo?computer_id=XXXX -# import argparse -from datetime import datetime +import datetime import logger import netuse import os.path import pickle -import Queue import slapos.slap.slap import sys from time import sleep -REPORT_STATE_INIT = 0 -REPORT_STATE_RUNNING = 1 -REPORT_STATE_STOP = 2 - def parseArgumentTuple(): parser = argparse.ArgumentParser() parser.add_argument("--master-url", @@ -151,18 +72,16 @@ def parseArgumentTuple(): class NetDriveUsageReporter(object): - queue_size = 512 - def __init__(self, option_dict): for option, value in option_dict.items(): setattr(self, option, value) self.slap = slapos.slap.slap() self.slap_computer = None - self.report_sequence_no = 0 - self._queue = None - self._state_file = self.data_file + ".state" self._domain_name = None self._domain_account = None + self._config_id = None + self._report_date = None + self._db = initializeDatabase(self.data_file) def initializeConnection(self): connection_dict = {} @@ -172,18 +91,25 @@ class NetDriveUsageReporter(object): **connection_dict) self.slap_computer = self.slap.registerComputer(self.computer_id) - def _getUserInfo(self): + def initializeConfigData(self): user_info = netuser.userInfo() - self._domain_name = user_info[1] - self._domain_account = user_info[0] + self._domain_account = "%s\\%s" % user_info[0:2] + + q = self._db.execute + s = "SELECT _rowid, report_date FROM config WHERE domain_account=? and computer_id=?" + r = + for r in q(s, (self._domain_account, self.computer_id)): + self._config_id, self._report_date = r + else: + q("INSERT OR REPLACE INTO config(domain_account, computer_id, report_date)" + " VALUES (?,?,?)", + (self._domain_account, self.computer_id, datetime.now())) + for r in q(s, (self._domain_account, self.computer_id)): + self._config_id, self._report_date = r def run(self): - self._getUserInfo() + self.initializeConfigData() self.initializeConnection() - self._loadReportState() - self._sendReportInQueue() - self.report_state = REPORT_STATE_RUNNING - pickle.dump(self.report_state, self._state_file) current_timestamp = datetime.now() try: while True: @@ -194,41 +120,10 @@ class NetDriveUsageReporter(object): continue r = self.getUsageReport(d.seconds, current_timestamp) current_timestamp = last_timestamp - if not self.sendUsageReport(r): - break + self.insertRecord(r[0], r[1], r[2], r[3]) + self.sendReport() except KeyboardInterrupt: pass - self._saveReportState() - self.report_state = REPORT_STATE_STOP - pickle.dump(self.report_state, self._state_file) - - def _loadReportState(self): - if not os.path.exists(self.data_file): - s = { - "sequence-no" : -1, - "computer-id" : self.computer_id, - "queue" : [], - } - pickle.dump(s, self.data_file) - else: - s = pickle.load(self.data_file) - - if not s.get("computer-id", "") == self.computer_id: - pass # data file is not expected - - if s.get("state", None) == REPORT_STATE_RUNNING: - pass # get sequence no from master sever - - self.report_sequence_no = s["sequence-no"] - self._queue = s["queue"] - - def _saveReportState(self): - s = { - "computer-id" : self.computer_id, - "sequence-no" : self.report_sequence_no, - "queue" : self._queue, - } - pickle.dump(s, self.data_file) def getUsageReport(self, duration, timestamp=None): if timestamp is None: @@ -245,26 +140,73 @@ class NetDriveUsageReporter(object): r.append("\n".join(remark)) return r - def sendUsageReport(self, r): - self._queue[0:0] = [r] - return self._sendReportInQueue() - - def _postData(self, r): + def sendReport(self): + # If report_date is not today, then + # Generate xml data from local table by report_date + # Send xml data to master node + # Change report_date to today + # (Optional) Move all the reported data to histroy table + today = datetime.now() + if self._report_date < today: + xml_data = self.generateDailyReport() + self._postData(xml_data) + self._db.execute("UPDATE config SET report_date=? where _rowid=?", + (today, self._config_id)) + + def _postData(self, xml_data): """Send a marshalled dictionary of the net drive usage record serialized via_getDict. """ - self.slap_computer.reportNetDriveUsage(r) - - def _sendReportInQueue(self): - try: - while True: - r = self._queue[-1] - if not self._postData(r): - return False - self._queue.pop() - except IndexError: + self.slap_computer.reportNetDriveUsage(xml_data) + + def initializeDatabase(self, db_path): + self._db = sqlite3.connect(db_path, isolation_level=None) + q = self._db.execute + q("""CREATE TABLE IF NOT EXISTS config ( + domain_account TEXT PRIMARY KEY, + computer_id TEXT NOT NULL, + report_date TEXT NOT NULL, + remark TEXT)""") + q("""CREATE TABLE IF NOT EXISTS net_drive_usage ( + id INTEGER PRIMARY KEY, + config_id INTEGER REFERENCES config ( _rowid ), + drive_letter TEXT NOT NULL, + remote_folder TEXT NOT NULL, + start_timestamp TEXT DEFAULT CURRENT_TIMESTAMP, + duration FLOAT NOT NULL, + usage_bytes INTEGER, + remark TEXT)""") + q("""CREATE TABLE IF NOT EXISTS net_drive_usage_history ( + id INTEGER PRIMARY KEY, + config_id INTEGER REFERENCES config ( _rowid ), + drive_letter TEXT NOT NULL, + remote_folder TEXT NOT NULL, + start_timestamp TEXT NOT NULL, + duration FLOAT NOT NULL, + bytes INTEGER + remark TEXT)""") + + def insertRecord(self, drive_letter, remote_foler, duration, usage_bytes): + self._db.execute("INSERT INTO net_drive_usage " + "(config_id, drive_letter, remote_folder, duration, usage_bytes )" + " VALUES (?, ?, ?, ?, ?)", + (self._config_id, drive_letter, remote_folder, duration, usage_bytes)) + + def generateDailyReport(self, report_date=None, remove=False): + if report_date is None: + report_date = self._report_date + q = self._db.execute + xml_data = "" + for r in q("SELECT * FROM net_drive_usage WHERE start_timestamp=?", report_date): pass - return True + if remove: + q("INSERT INTO net_drive_usage_history " + "SELECT * FROM net_drive_usage WHERE start_timestamp=?", + report_date) + q("DELETE FROM net_drive_usage WHERE start_timestamp=?", + report_date) + return xml_data + def main(): reporter = NetDriveUsageReporter(parseArgumentTuple()) -- 2.30.9