##// END OF EJS Templates
fixed lock decorator bug which didn't release the lock after func execution and rewrote the pidlock a little with Ask Solem suggestions!...
marcink -
r506:d5efb835 default
parent child Browse files
Show More
@@ -36,7 +36,7 b' BROKER_PASSWORD = "qweqwe"'
36 CELERYD_CONCURRENCY = 2
36 CELERYD_CONCURRENCY = 2
37 # CELERYD_LOG_FILE = "celeryd.log"
37 # CELERYD_LOG_FILE = "celeryd.log"
38 CELERYD_LOG_LEVEL = "DEBUG"
38 CELERYD_LOG_LEVEL = "DEBUG"
39 CELERYD_MAX_TASKS_PER_CHILD = 1
39 CELERYD_MAX_TASKS_PER_CHILD = 3
40
40
41 #Tasks will never be sent to the queue, but executed locally instead.
41 #Tasks will never be sent to the queue, but executed locally instead.
42 CELERY_ALWAYS_EAGER = False
42 CELERY_ALWAYS_EAGER = False
@@ -35,7 +35,7 b' from datetime import datetime, timedelta'
35 from time import mktime
35 from time import mktime
36 import calendar
36 import calendar
37 import logging
37 import logging
38
38 import json
39 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
40
40
41 class SummaryController(BaseController):
41 class SummaryController(BaseController):
@@ -79,18 +79,25 b' class SummaryController(BaseController):'
79 c.ts_min = ts_min_m
79 c.ts_min = ts_min_m
80 c.ts_max = ts_max_y
80 c.ts_max = ts_max_y
81
81
82
83 stats = self.sa.query(Statistics)\
82 stats = self.sa.query(Statistics)\
84 .filter(Statistics.repository == c.repo_info.dbrepo)\
83 .filter(Statistics.repository == c.repo_info.dbrepo)\
85 .scalar()
84 .scalar()
86
85
87 if stats:
86
87 if stats and stats.languages:
88 lang_stats = json.loads(stats.languages)
88 c.commit_data = stats.commit_activity
89 c.commit_data = stats.commit_activity
89 c.overview_data = stats.commit_activity_combined
90 c.overview_data = stats.commit_activity_combined
91 c.trending_languages = json.dumps(OrderedDict(
92 sorted(lang_stats.items(), reverse=True,
93 key=lambda k: k[1])[:2]
94 )
95 )
96 print c.trending_languages
90 else:
97 else:
91 import json
92 c.commit_data = json.dumps({})
98 c.commit_data = json.dumps({})
93 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 0] ])
99 c.overview_data = json.dumps([[ts_min_y, 0], [ts_max_y, 0] ])
100 c.trending_languages = json.dumps({})
94
101
95 return render('summary/summary.html')
102 return render('summary/summary.html')
96
103
@@ -42,7 +42,7 b' def locked_task(func):'
42 log.info('running task with lockkey %s', lockkey)
42 log.info('running task with lockkey %s', lockkey)
43 try:
43 try:
44 l = DaemonLock(lockkey)
44 l = DaemonLock(lockkey)
45 return func(*fargs, **fkwargs)
45 func(*fargs, **fkwargs)
46 l.release()
46 l.release()
47 except LockHeld:
47 except LockHeld:
48 log.info('LockHeld')
48 log.info('LockHeld')
@@ -1,16 +1,16 b''
1 from celery.decorators import task
1 from celery.decorators import task
2 from celery.task.sets import subtask
2 from celery.task.sets import subtask
3 from celeryconfig import PYLONS_CONFIG as config
3 from celeryconfig import PYLONS_CONFIG as config
4 from operator import itemgetter
4 from pylons.i18n.translation import _
5 from pylons.i18n.translation import _
5 from pylons_app.lib.celerylib import run_task, locked_task
6 from pylons_app.lib.celerylib import run_task, locked_task
6 from pylons_app.lib.helpers import person
7 from pylons_app.lib.helpers import person
7 from pylons_app.lib.smtp_mailer import SmtpMailer
8 from pylons_app.lib.smtp_mailer import SmtpMailer
8 from pylons_app.lib.utils import OrderedDict
9 from pylons_app.lib.utils import OrderedDict
9 from operator import itemgetter
10 from time import mktime
10 from vcs.backends.hg import MercurialRepository
11 from vcs.backends.hg import MercurialRepository
11 from time import mktime
12 import json
12 import traceback
13 import traceback
13 import json
14
14
15 __all__ = ['whoosh_index', 'get_commits_stats',
15 __all__ = ['whoosh_index', 'get_commits_stats',
16 'reset_user_password', 'send_email']
16 'reset_user_password', 'send_email']
@@ -75,10 +75,10 b' def whoosh_index(repo_location, full_ind'
75 @task
75 @task
76 @locked_task
76 @locked_task
77 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
77 def get_commits_stats(repo_name, ts_min_y, ts_max_y):
78 author_key_cleaner = lambda k: person(k).replace('"', "") #for js data compatibilty
79
80 from pylons_app.model.db import Statistics, Repository
78 from pylons_app.model.db import Statistics, Repository
81 log = get_commits_stats.get_logger()
79 log = get_commits_stats.get_logger()
80 author_key_cleaner = lambda k: person(k).replace('"', "") #for js data compatibilty
81
82 commits_by_day_author_aggregate = {}
82 commits_by_day_author_aggregate = {}
83 commits_by_day_aggregate = {}
83 commits_by_day_aggregate = {}
84 repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '')
84 repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '')
@@ -99,7 +99,7 b' def get_commits_stats(repo_name, ts_min_'
99 if cur_stats:
99 if cur_stats:
100 last_rev = cur_stats.stat_on_revision
100 last_rev = cur_stats.stat_on_revision
101
101
102 if last_rev == repo.revisions[-1]:
102 if last_rev == repo.revisions[-1] and len(repo.revisions) > 1:
103 #pass silently without any work
103 #pass silently without any work
104 return True
104 return True
105
105
@@ -109,6 +109,7 b' def get_commits_stats(repo_name, ts_min_'
109 cur_stats.commit_activity_combined))
109 cur_stats.commit_activity_combined))
110 commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
110 commits_by_day_author_aggregate = json.loads(cur_stats.commit_activity)
111
111
112 log.debug('starting parsing %s', parse_limit)
112 for cnt, rev in enumerate(repo.revisions[last_rev:]):
113 for cnt, rev in enumerate(repo.revisions[last_rev:]):
113 last_cs = cs = repo.get_changeset(rev)
114 last_cs = cs = repo.get_changeset(rev)
114 k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
115 k = '%s-%s-%s' % (cs.date.timetuple()[0], cs.date.timetuple()[1],
@@ -187,9 +188,16 b' def get_commits_stats(repo_name, ts_min_'
187 stats = cur_stats if cur_stats else Statistics()
188 stats = cur_stats if cur_stats else Statistics()
188 stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
189 stats.commit_activity = json.dumps(commits_by_day_author_aggregate)
189 stats.commit_activity_combined = json.dumps(overview_data)
190 stats.commit_activity_combined = json.dumps(overview_data)
191
192 log.debug('last revison %s', last_rev)
193 leftovers = len(repo.revisions[last_rev:])
194 log.debug('revisions to parse %s', leftovers)
195
196 if last_rev == 0 or leftovers < parse_limit:
197 stats.languages = json.dumps(__get_codes_stats(repo_name))
198
190 stats.repository = dbrepo
199 stats.repository = dbrepo
191 stats.stat_on_revision = last_cs.revision
200 stats.stat_on_revision = last_cs.revision
192 stats.languages = json.dumps({'_TOTAL_':0, '':0})
193
201
194 try:
202 try:
195 sa.add(stats)
203 sa.add(stats)
@@ -198,8 +206,8 b' def get_commits_stats(repo_name, ts_min_'
198 log.error(traceback.format_exc())
206 log.error(traceback.format_exc())
199 sa.rollback()
207 sa.rollback()
200 return False
208 return False
201
209 if len(repo.revisions) > 1:
202 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
210 run_task(get_commits_stats, repo_name, ts_min_y, ts_max_y)
203
211
204 return True
212 return True
205
213
@@ -259,3 +267,31 b' def send_email(recipients, subject, body'
259 log.error(traceback.format_exc())
267 log.error(traceback.format_exc())
260 return False
268 return False
261 return True
269 return True
270
271 def __get_codes_stats(repo_name):
272 LANGUAGES_EXTENSIONS = ['action', 'adp', 'ashx', 'asmx', 'aspx', 'asx', 'axd', 'c',
273 'cfg', 'cfm', 'cpp', 'cs', 'diff', 'do', 'el', 'erl',
274 'h', 'java', 'js', 'jsp', 'jspx', 'lisp',
275 'lua', 'm', 'mako', 'ml', 'pas', 'patch', 'php', 'php3',
276 'php4', 'phtml', 'pm', 'py', 'rb', 'rst', 's', 'sh',
277 'tpl', 'txt', 'vim', 'wss', 'xhtml', 'xml', 'xsl', 'xslt',
278 'yaws']
279 repos_path = get_hg_ui_settings()['paths_root_path'].replace('*', '')
280 repo = MercurialRepository(repos_path + repo_name)
281
282 code_stats = {}
283 for topnode, dirs, files in repo.walk('/', 'tip'):
284 for f in files:
285 k = f.mimetype
286 if f.extension in LANGUAGES_EXTENSIONS:
287 if code_stats.has_key(k):
288 code_stats[k] += 1
289 else:
290 code_stats[k] = 1
291
292 return code_stats or {}
293
294
295
296
297
@@ -1,6 +1,8 b''
1 import os, time
1 import os, time
2 import sys
2 import sys
3 from warnings import warn
3 from warnings import warn
4 from multiprocessing.util import Finalize
5 import errno
4
6
5 class LockHeld(Exception):pass
7 class LockHeld(Exception):pass
6
8
@@ -27,55 +29,67 b' class DaemonLock(object):'
27 self.held = False
29 self.held = False
28 #run the lock automatically !
30 #run the lock automatically !
29 self.lock()
31 self.lock()
30
32 self._finalize = Finalize(self, DaemonLock._on_finalize,
31 def __del__(self):
33 args=(self, debug), exitpriority=10)
32 if self.held:
33
34
34 # warn("use lock.release instead of del lock",
35 @staticmethod
35 # category = DeprecationWarning,
36 def _on_finalize(lock, debug):
36 # stacklevel = 2)
37 if lock.held:
37
38 if debug:
38 # ensure the lock will be removed
39 print 'leck held finilazing and running lock.release()'
39 self.release()
40 lock.release()
40
41
41
42
42 def lock(self):
43 def lock(self):
43 """locking function, if lock is present it will raise LockHeld exception
44 """locking function, if lock is present it will raise LockHeld exception
44 """
45 """
45 lockname = '%s' % (os.getpid())
46 lockname = '%s' % (os.getpid())
46
47 if self.debug:
48 print 'running lock'
47 self.trylock()
49 self.trylock()
48 self.makelock(lockname, self.pidfile)
50 self.makelock(lockname, self.pidfile)
49 return True
51 return True
50
52
51 def trylock(self):
53 def trylock(self):
52 running_pid = False
54 running_pid = False
55 if self.debug:
56 print 'checking for already running process'
53 try:
57 try:
54 pidfile = open(self.pidfile, "r")
58 pidfile = open(self.pidfile, "r")
55 pidfile.seek(0)
59 pidfile.seek(0)
56 running_pid = pidfile.readline()
60 running_pid = int(pidfile.readline())
61
62 pidfile.close()
63
57 if self.debug:
64 if self.debug:
58 print 'lock file present running_pid: %s, checking for execution'\
65 print 'lock file present running_pid: %s, checking for execution'\
59 % running_pid
66 % running_pid
60 # Now we check the PID from lock file matches to the current
67 # Now we check the PID from lock file matches to the current
61 # process PID
68 # process PID
62 if running_pid:
69 if running_pid:
63 if os.path.exists("/proc/%s" % running_pid):
70 try:
64 print "You already have an instance of the program running"
71 os.kill(running_pid, 0)
65 print "It is running as process %s" % running_pid
72 except OSError, exc:
66 raise LockHeld
73 if exc.errno in (errno.ESRCH, errno.EPERM):
74 print "Lock File is there but the program is not running"
75 print "Removing lock file for the: %s" % running_pid
76 self.release()
77 raise
67 else:
78 else:
68 print "Lock File is there but the program is not running"
79 print "You already have an instance of the program running"
69 print "Removing lock file for the: %s" % running_pid
80 print "It is running as process %s" % running_pid
70 self.release()
81 raise LockHeld()
82
71 except IOError, e:
83 except IOError, e:
72 if e.errno != 2:
84 if e.errno != 2:
73 raise
85 raise
74
86
75
76 def release(self):
87 def release(self):
77 """releases the pid by removing the pidfile
88 """releases the pid by removing the pidfile
78 """
89 """
90 if self.debug:
91 print 'trying to release the pidlock'
92
79 if self.callbackfn:
93 if self.callbackfn:
80 #execute callback function on release
94 #execute callback function on release
81 if self.debug:
95 if self.debug:
@@ -2963,6 +2963,28 b' div.form div.fields div.buttons input'
2963 /* -----------------------------------------------------------
2963 /* -----------------------------------------------------------
2964 SUMMARY
2964 SUMMARY
2965 ----------------------------------------------------------- */
2965 ----------------------------------------------------------- */
2966 .trending_language_tbl, .trending_language_tbl td {
2967 margin: 0px !important;
2968 padding: 0px !important;
2969 border: 0 !important;
2970
2971 }
2972 .trending_language{
2973 -moz-border-radius-bottomright:4px;
2974 -moz-border-radius-topright:4px;
2975 border-bottom-right-radius: 4px 4px;
2976 border-top-right-radius: 4px 4px;
2977 background-color:#336699;
2978 color:#FFFFFF;
2979 display:block;
2980 min-width:20px;
2981 max-width:400px;
2982 padding:3px;
2983 text-decoration:none;
2984 height: 10px;
2985 margin-bottom: 4px;
2986 margin-left: 5px;
2987 }
2966
2988
2967 #clone_url{
2989 #clone_url{
2968 border: none;
2990 border: none;
@@ -90,7 +90,62 b' E.onDOMReady(function(e){'
90 <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
90 <input type="text" id="clone_url" readonly="readonly" value="hg clone ${c.clone_repo_url}" size="70"/>
91 </div>
91 </div>
92 </div>
92 </div>
93
93
94 <div class="field">
95 <div class="label">
96 <label>${_('Trending languages')}:</label>
97 </div>
98 <div class="input-short">
99 <div id="lang_stats">
100
101 </div>
102 <script type="text/javascript">
103 var data = ${c.trending_languages|n};
104 var total = 0;
105 var no_data = true;
106 for (k in data){
107 total += data[k];
108 no_data = false;
109 }
110 var tbl = document.createElement('table');
111 tbl.setAttribute('class','trending_language_tbl');
112 for (k in data){
113 var tr = document.createElement('tr');
114 var percentage = Math.round((data[k]/total*100),2);
115 var value = data[k];
116 var td1 = document.createElement('td');
117 td1.width=150;
118 var trending_language_label = document.createElement('div');
119 trending_language_label.innerHTML = k;
120 td1.appendChild(trending_language_label);
121
122 var td2 = document.createElement('td');
123 var trending_language = document.createElement('div');
124 trending_language.title = k;
125 trending_language.innerHTML = "<b>"+value+" ${_('files')} - "+percentage+" %</b>";
126 trending_language.setAttribute("class", 'trending_language');
127 trending_language.style.width=percentage+"%";
128 td2.appendChild(trending_language);
129
130 tr.appendChild(td1);
131 tr.appendChild(td2);
132 tbl.appendChild(tr);
133 //YAHOO.util.Dom.get('lang_stats').appendChild(trending_language_label);
134
135 }
136 if(no_data){
137 var tr = document.createElement('tr');
138 var td1 = document.createElement('td');
139 td1.innerHTML = "${_('No data loaded yet...')}";
140 tr.appendChild(td1);
141 tbl.appendChild(tr);
142 }
143 YAHOO.util.Dom.get('lang_stats').appendChild(tbl);
144 </script>
145
146 </div>
147 </div>
148
94 <div class="field">
149 <div class="field">
95 <div class="label">
150 <div class="label">
96 <label>${_('Download')}:</label>
151 <label>${_('Download')}:</label>
General Comments 0
You need to be logged in to leave comments. Login now