summaryrefslogtreecommitdiffstats
path: root/Tools/QueueStatusServer/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/QueueStatusServer/handlers')
-rw-r--r--Tools/QueueStatusServer/handlers/__init__.py3
-rw-r--r--Tools/QueueStatusServer/handlers/dashboard.py64
-rw-r--r--Tools/QueueStatusServer/handlers/gc.py44
-rw-r--r--Tools/QueueStatusServer/handlers/nextpatch.py59
-rw-r--r--Tools/QueueStatusServer/handlers/patch.py53
-rw-r--r--Tools/QueueStatusServer/handlers/patchstatus.py40
-rw-r--r--Tools/QueueStatusServer/handlers/queuestatus.py72
-rw-r--r--Tools/QueueStatusServer/handlers/queuestatus_unittest.py62
-rw-r--r--Tools/QueueStatusServer/handlers/recentstatus.py94
-rw-r--r--Tools/QueueStatusServer/handlers/releasepatch.py62
-rw-r--r--Tools/QueueStatusServer/handlers/showresults.py41
-rw-r--r--Tools/QueueStatusServer/handlers/statusbubble.py59
-rw-r--r--Tools/QueueStatusServer/handlers/statusbubble_unittest.py62
-rw-r--r--Tools/QueueStatusServer/handlers/submittoews.py64
-rw-r--r--Tools/QueueStatusServer/handlers/svnrevision.py40
-rw-r--r--Tools/QueueStatusServer/handlers/updatebase.py41
-rw-r--r--Tools/QueueStatusServer/handlers/updatestatus.py66
-rw-r--r--Tools/QueueStatusServer/handlers/updatesvnrevision.py53
-rw-r--r--Tools/QueueStatusServer/handlers/updateworkitems.py66
19 files changed, 1045 insertions, 0 deletions
diff --git a/Tools/QueueStatusServer/handlers/__init__.py b/Tools/QueueStatusServer/handlers/__init__.py
new file mode 100644
index 0000000..296e173
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/__init__.py
@@ -0,0 +1,3 @@
+# Required for Python to search this directory for module files
+
+from handlers.updatebase import UpdateBase
diff --git a/Tools/QueueStatusServer/handlers/dashboard.py b/Tools/QueueStatusServer/handlers/dashboard.py
new file mode 100644
index 0000000..660c595
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/dashboard.py
@@ -0,0 +1,64 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import operator
+
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+from model.attachment import Attachment
+from model.queues import Queue
+
+
+class Dashboard(webapp.RequestHandler):
+ # We may want to sort these?
+ _ordered_queues = Queue.all()
+ _header_names = [queue.short_name() for queue in _ordered_queues]
+
+ def _build_bubble(self, attachment, queue):
+ queue_status = attachment.status_for_queue(queue)
+ bubble = {
+ "status_class": attachment.state_from_queue_status(queue_status) if queue_status else "none",
+ "status_date": queue_status.date if queue_status else None,
+ }
+ return bubble
+
+ def _build_row(self, attachment):
+ row = {
+ "bug_id": attachment.bug_id(),
+ "attachment_id": attachment.id,
+ "bubbles": [self._build_bubble(attachment, queue) for queue in self._ordered_queues],
+ }
+ return row
+
+ def get(self):
+ template_values = {
+ "headers": self._header_names,
+ "rows": [self._build_row(attachment) for attachment in Attachment.recent(limit=25)],
+ }
+ self.response.out.write(template.render("templates/dashboard.html", template_values))
diff --git a/Tools/QueueStatusServer/handlers/gc.py b/Tools/QueueStatusServer/handlers/gc.py
new file mode 100644
index 0000000..d04ee4d
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/gc.py
@@ -0,0 +1,44 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import webapp
+
+from model.queuestatus import QueueStatus
+
+
+class GC(webapp.RequestHandler):
+ def get(self):
+ statuses = QueueStatus.all().order("-date")
+ seen_queues = set()
+ for status in statuses:
+ if status.active_patch_id or status.active_bug_id:
+ continue
+ if status.queue_name in seen_queues:
+ status.delete()
+ seen_queues.add(status.queue_name)
+ self.response.out.write("Done!")
diff --git a/Tools/QueueStatusServer/handlers/nextpatch.py b/Tools/QueueStatusServer/handlers/nextpatch.py
new file mode 100644
index 0000000..5f6d71d
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/nextpatch.py
@@ -0,0 +1,59 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from datetime import datetime
+
+from google.appengine.ext import db
+from google.appengine.ext import webapp
+
+from model.queues import Queue
+
+
+class NextPatch(webapp.RequestHandler):
+ # FIXME: This should probably be a post, or an explict lock_patch
+ # since GET requests shouldn't really modify the datastore.
+ def get(self, queue_name):
+ queue = Queue.queue_with_name(queue_name)
+ if not queue:
+ self.error(404)
+ return
+ # FIXME: Patch assignment should probably move into Queue.
+ patch_id = db.run_in_transaction(self._assign_patch, queue.active_work_items().key(), queue.work_items().item_ids)
+ if not patch_id:
+ self.error(404)
+ return
+ self.response.out.write(patch_id)
+
+ @staticmethod
+ def _assign_patch(key, work_item_ids):
+ now = datetime.now()
+ active_work_items = db.get(key)
+ active_work_items.deactivate_expired(now)
+ next_item = active_work_items.next_item(work_item_ids, now)
+ active_work_items.put()
+ return next_item
diff --git a/Tools/QueueStatusServer/handlers/patch.py b/Tools/QueueStatusServer/handlers/patch.py
new file mode 100644
index 0000000..3219212
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/patch.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+from model.queuestatus import QueueStatus
+
+
+class Patch(webapp.RequestHandler):
+ def get(self, attachment_id_string):
+ attachment_id = int(attachment_id_string)
+ statuses = QueueStatus.all().filter("active_patch_id =", attachment_id).order("-date")
+
+ bug_id = None
+ queue_status = {}
+ for status in statuses:
+ bug_id = status.active_bug_id # Should be the same for every status.
+ per_queue_statuses = queue_status.get(status.queue_name, [])
+ per_queue_statuses.append(status)
+ queue_status[status.queue_name] = per_queue_statuses
+
+ template_values = {
+ "attachment_id" : attachment_id,
+ "bug_id" : bug_id,
+ "queue_status" : queue_status,
+ }
+ self.response.out.write(template.render("templates/patch.html", template_values))
diff --git a/Tools/QueueStatusServer/handlers/patchstatus.py b/Tools/QueueStatusServer/handlers/patchstatus.py
new file mode 100644
index 0000000..1a5422e
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/patchstatus.py
@@ -0,0 +1,40 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import webapp
+
+from model.queuestatus import QueueStatus
+
+
+class PatchStatus(webapp.RequestHandler):
+ def get(self, queue_name, attachment_id):
+ statuses = QueueStatus.all().filter('queue_name =', queue_name).filter('active_patch_id =', int(attachment_id)).order('-date').fetch(1)
+ if not statuses:
+ self.error(404)
+ return
+ self.response.out.write(statuses[0].message)
diff --git a/Tools/QueueStatusServer/handlers/queuestatus.py b/Tools/QueueStatusServer/handlers/queuestatus.py
new file mode 100644
index 0000000..54c0fdd
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/queuestatus.py
@@ -0,0 +1,72 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import itertools
+
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+from model.queues import Queue
+from model import queuestatus
+
+
+class QueueStatus(webapp.RequestHandler):
+ def _rows_for_work_items(self, queue):
+ queued_items = queue.work_items()
+ active_items = queue.active_work_items()
+ if not queued_items:
+ return []
+ rows = []
+ for item_id in queued_items.item_ids:
+ rows.append({
+ "attachment_id": item_id,
+ "bug_id": 1,
+ "lock_time": active_items and active_items.time_for_item(item_id),
+ })
+ return rows
+
+ def _grouping_key_for_status(self, status):
+ return "%s-%s" % (status.active_patch_id, status.bot_id)
+
+ def _build_status_groups(self, statuses):
+ return [list(group) for key, group in itertools.groupby(statuses, self._grouping_key_for_status)]
+
+ def get(self, queue_name):
+ queue_name = queue_name.lower()
+ queue = Queue.queue_with_name(queue_name)
+ if not queue:
+ self.error(404)
+ return
+
+ statuses = queuestatus.QueueStatus.all().filter("queue_name =", queue.name()).order("-date").fetch(15)
+ template_values = {
+ "display_queue_name": queue.display_name(),
+ "work_item_rows": self._rows_for_work_items(queue),
+ "status_groups": self._build_status_groups(statuses),
+ }
+ self.response.out.write(template.render("templates/queuestatus.html", template_values))
diff --git a/Tools/QueueStatusServer/handlers/queuestatus_unittest.py b/Tools/QueueStatusServer/handlers/queuestatus_unittest.py
new file mode 100644
index 0000000..a5ae844
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/queuestatus_unittest.py
@@ -0,0 +1,62 @@
+# Copyright (C) 2010 Google, Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Research in Motion Ltd. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import unittest
+
+from handlers.queuestatus import QueueStatus
+from model.queues import Queue
+
+
+class MockStatus(object):
+ def __init__(self, patch_id, bot_id):
+ self.active_patch_id = patch_id
+ self.bot_id = bot_id
+
+
+class QueueStatusTest(unittest.TestCase):
+ def test_build_status_groups(self):
+ queue_status = QueueStatus()
+ statuses = [
+ MockStatus(1, "foo"),
+ MockStatus(1, "foo"),
+ MockStatus(2, "foo"),
+ MockStatus(1, "foo"),
+ MockStatus(1, "bar"),
+ MockStatus(1, "foo"),
+ ]
+ groups = queue_status._build_status_groups(statuses)
+ self.assertEqual(len(groups), 5)
+ self.assertEqual(groups[0], statuses[0:2])
+ self.assertEqual(groups[1], statuses[2:3])
+ self.assertEqual(groups[2], statuses[3:4])
+ self.assertEqual(groups[3], statuses[4:5])
+ self.assertEqual(groups[4], statuses[5:6])
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/Tools/QueueStatusServer/handlers/recentstatus.py b/Tools/QueueStatusServer/handlers/recentstatus.py
new file mode 100644
index 0000000..fddc93a
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/recentstatus.py
@@ -0,0 +1,94 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import datetime
+
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+from model.queues import Queue
+from model.queuestatus import QueueStatus
+from model.workitems import WorkItems
+
+
+class QueueBubble(object):
+ """View support class for recentstatus.html"""
+ def __init__(self, queue):
+ self._queue = queue
+ self._work_items = queue.work_items()
+ self._last_status = QueueStatus.all().filter("queue_name =", queue.name()).order("-date").get()
+
+ # FIXME: name and display_name should be replaced by a .queue() accessor.
+ def name(self):
+ return self._queue.name()
+
+ def display_name(self):
+ return self._queue.display_name()
+
+ def _last_status_date(self):
+ if not self._last_status:
+ return None
+ return self._last_status.date
+
+ def last_heard_from(self):
+ if not self._work_items:
+ return self._last_status_date()
+ return max(self._last_status_date(), self._work_items.date)
+
+ def is_alive(self):
+ if not self.last_heard_from():
+ return False
+ return self.last_heard_from() > (datetime.datetime.now() - datetime.timedelta(minutes=30))
+
+ def status_class(self):
+ if not self.is_alive():
+ return "dead"
+ if self.pending_items_count() > 1:
+ return "behind"
+ return "alive"
+
+ def status_text(self):
+ if not self._work_items:
+ return "Offline"
+ if not self._work_items.item_ids:
+ return "Idle"
+ return self._last_status.message
+
+ def pending_items_count(self):
+ if not self._work_items:
+ return 0
+ return len(self._work_items.item_ids)
+
+
+class QueuesOverview(webapp.RequestHandler):
+
+ def get(self):
+ template_values = {
+ "queues": [QueueBubble(queue) for queue in Queue.all()],
+ }
+ self.response.out.write(template.render("templates/recentstatus.html", template_values))
diff --git a/Tools/QueueStatusServer/handlers/releasepatch.py b/Tools/QueueStatusServer/handlers/releasepatch.py
new file mode 100644
index 0000000..0e46e69
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/releasepatch.py
@@ -0,0 +1,62 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import webapp, db
+from google.appengine.ext.webapp import template
+
+from handlers.updatebase import UpdateBase
+from model.attachment import Attachment
+from model.queues import Queue
+
+
+class ReleasePatch(UpdateBase):
+ def get(self):
+ self.response.out.write(template.render("templates/releasepatch.html", None))
+
+ def post(self):
+ queue_name = self.request.get("queue_name")
+ # FIXME: This queue lookup should be shared between handlers.
+ queue = Queue.queue_with_name(queue_name)
+ if not queue:
+ self.error(404)
+ return
+
+ attachment_id = self._int_from_request("attachment_id")
+ attachment = Attachment(attachment_id)
+ last_status = attachment.status_for_queue(queue)
+
+ # Ideally we should use a transaction for the calls to
+ # WorkItems and ActiveWorkItems.
+
+ # Only remove it from the queue if the last message is not a retry request.
+ # Allow removing it from the queue even if there is no last_status for easier testing.
+ if not last_status or not last_status.is_retry_request():
+ queue.work_items().remove_work_item(attachment_id)
+
+ # Always release the lock on the item.
+ queue.active_work_items().expire_item(attachment_id)
diff --git a/Tools/QueueStatusServer/handlers/showresults.py b/Tools/QueueStatusServer/handlers/showresults.py
new file mode 100644
index 0000000..e4cb71b
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/showresults.py
@@ -0,0 +1,41 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import webapp
+
+from model.queuestatus import QueueStatus
+
+
+class ShowResults(webapp.RequestHandler):
+ def get(self, status_id):
+ status = QueueStatus.get_by_id(int(status_id))
+ if not status:
+ self.error(404)
+ return
+ self.response.headers["Content-Type"] = "text/plain; charset=utf-8"
+ self.response.out.write(status.results_file)
diff --git a/Tools/QueueStatusServer/handlers/statusbubble.py b/Tools/QueueStatusServer/handlers/statusbubble.py
new file mode 100644
index 0000000..5690484
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/statusbubble.py
@@ -0,0 +1,59 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import operator
+
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+
+from model.attachment import Attachment
+from model.workitems import WorkItems
+from model.queues import Queue
+
+
+class StatusBubble(webapp.RequestHandler):
+ _queues_to_display = [queue for queue in Queue.all() if queue.is_ews()]
+
+ def _build_bubble(self, queue, attachment):
+ queue_status = attachment.status_for_queue(queue)
+ bubble = {
+ "name": queue.short_name().lower(),
+ "attachment_id": attachment.id,
+ "queue_position": attachment.position_in_queue(queue),
+ "state": attachment.state_from_queue_status(queue_status) if queue_status else "none",
+ "status": queue_status,
+ }
+ return bubble
+
+ def get(self, attachment_id):
+ attachment = Attachment(int(attachment_id))
+ bubbles = [self._build_bubble(queue, attachment) for queue in self._queues_to_display]
+ template_values = {
+ "bubbles": bubbles,
+ }
+ self.response.out.write(template.render("templates/statusbubble.html", template_values))
diff --git a/Tools/QueueStatusServer/handlers/statusbubble_unittest.py b/Tools/QueueStatusServer/handlers/statusbubble_unittest.py
new file mode 100644
index 0000000..3ffbdaf
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/statusbubble_unittest.py
@@ -0,0 +1,62 @@
+# Copyright (C) 2010 Google, Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Research in Motion Ltd. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import unittest
+
+
+from handlers.statusbubble import StatusBubble
+from model.queues import Queue
+
+
+class MockAttachment(object):
+ def __init__(self):
+ self.id = 1
+
+ def status_for_queue(self, queue):
+ return None
+
+ def position_in_queue(self, queue):
+ return 1
+
+
+class StatusBubbleTest(unittest.TestCase):
+ def test_build_bubble(self):
+ bubble = StatusBubble()
+ queue = Queue("mac-ews")
+ attachment = MockAttachment()
+ bubble_dict = bubble._build_bubble(queue, attachment)
+ # FIXME: assertDictEqual (in Python 2.7) would be better to use here.
+ self.assertEqual(bubble_dict["name"], "mac")
+ self.assertEqual(bubble_dict["attachment_id"], 1)
+ self.assertEqual(bubble_dict["queue_position"], 1)
+ self.assertEqual(bubble_dict["state"], "none")
+ self.assertEqual(bubble_dict["status"], None)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/Tools/QueueStatusServer/handlers/submittoews.py b/Tools/QueueStatusServer/handlers/submittoews.py
new file mode 100644
index 0000000..3ba4373
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/submittoews.py
@@ -0,0 +1,64 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import webapp, db
+from google.appengine.ext.webapp import template
+
+from handlers.updatebase import UpdateBase
+from model.attachment import Attachment
+from model.queues import Queue
+
+
+class SubmitToEWS(UpdateBase):
+ def get(self):
+ self.response.out.write(template.render("templates/submittoews.html", None))
+
+ def _should_add_to_ews_queue(self, queue, attachment):
+ # This assert() is here to make sure we're not submitting to the commit-queue.
+ # The commit-queue clients check each patch anyway, but there is not sense
+ # in adding things to the commit-queue when they won't be processed by it.
+ assert(queue.is_ews())
+ latest_status = attachment.status_for_queue(queue)
+ if not latest_status:
+ return True
+ # Only ever re-submit to the EWS if the EWS specifically requested a retry.
+ # This allows us to restart the EWS feeder queue, without all r? patches
+ # being retried as a result of that restart!
+ # In some future version we might add a "force" button to allow the user
+ # to override this restriction.
+ return latest_status.is_retry_request()
+
+ def _add_attachment_to_ews_queues(self, attachment):
+ for queue in Queue.all_ews(): # all_ews() currently includes the style-queue
+ if self._should_add_to_ews_queue(queue, attachment):
+ queue.work_items().add_work_item(attachment.id)
+
+ def post(self):
+ attachment_id = self._int_from_request("attachment_id")
+ attachment = Attachment(attachment_id)
+ self._add_attachment_to_ews_queues(attachment)
diff --git a/Tools/QueueStatusServer/handlers/svnrevision.py b/Tools/QueueStatusServer/handlers/svnrevision.py
new file mode 100644
index 0000000..36eab33
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/svnrevision.py
@@ -0,0 +1,40 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import webapp
+
+import model
+
+
+class SVNRevision(webapp.RequestHandler):
+ def get(self, svn_revision_number):
+ svn_revisions = model.SVNRevision.all().filter('number =', int(svn_revision_number)).order('-date').fetch(1)
+ if not svn_revisions:
+ self.error(404)
+ return
+ self.response.out.write(svn_revisions[0].to_xml())
diff --git a/Tools/QueueStatusServer/handlers/updatebase.py b/Tools/QueueStatusServer/handlers/updatebase.py
new file mode 100644
index 0000000..b087e83
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/updatebase.py
@@ -0,0 +1,41 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.api import users
+from google.appengine.ext import webapp, db
+
+
+class UpdateBase(webapp.RequestHandler):
+ def _int_from_request(self, name):
+ string_value = self.request.get(name)
+ try:
+ int_value = int(string_value)
+ return int_value
+ except ValueError, TypeError:
+ pass
+ return None
diff --git a/Tools/QueueStatusServer/handlers/updatestatus.py b/Tools/QueueStatusServer/handlers/updatestatus.py
new file mode 100644
index 0000000..7301101
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/updatestatus.py
@@ -0,0 +1,66 @@
+# Copyright (C) 2009 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.api import users
+from google.appengine.ext import webapp, db
+from google.appengine.ext.webapp import template
+
+from handlers.updatebase import UpdateBase
+from model.attachment import Attachment
+from model.queuestatus import QueueStatus
+
+
+class UpdateStatus(UpdateBase):
+ def get(self):
+ self.response.out.write(template.render("templates/updatestatus.html", None))
+
+ def _queue_status_from_request(self):
+ queue_status = QueueStatus()
+
+ # FIXME: I think this can be removed, no one uses it.
+ if users.get_current_user():
+ queue_status.author = users.get_current_user()
+
+ bug_id = self._int_from_request("bug_id")
+ patch_id = self._int_from_request("patch_id")
+ queue_name = self.request.get("queue_name")
+ bot_id = self.request.get("bot_id")
+ queue_status.queue_name = queue_name
+ queue_status.bot_id = bot_id
+ queue_status.active_bug_id = bug_id
+ queue_status.active_patch_id = patch_id
+ queue_status.message = self.request.get("status")
+ results_file = self.request.get("results_file")
+ queue_status.results_file = db.Blob(str(results_file))
+ return queue_status
+
+ def post(self):
+ queue_status = self._queue_status_from_request()
+ queue_status.put()
+ Attachment.dirty(queue_status.active_patch_id)
+ self.response.out.write(queue_status.key().id())
diff --git a/Tools/QueueStatusServer/handlers/updatesvnrevision.py b/Tools/QueueStatusServer/handlers/updatesvnrevision.py
new file mode 100644
index 0000000..075982a
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/updatesvnrevision.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import webapp, db
+from google.appengine.ext.webapp import template
+
+import handlers
+import model
+
+
+class UpdateSVNRevision(handlers.UpdateBase):
+ def get(self):
+ self.response.out.write(template.render("templates/updatesvnrevision.html", None))
+
+ def post(self):
+ svn_revision_number = self._int_from_request("number")
+
+ svn_revisions = model.SVNRevision.all().filter('number =', svn_revision_number).order('-date').fetch(1)
+ svn_revision = None
+ if svn_revisions:
+ svn_revision = svn_revisions[0]
+ else:
+ svn_revision = model.SVNRevision()
+ svn_revision.number = svn_revision_number
+ svn_revision.broken_bots.append(self.request.get("broken_bot"))
+ svn_revision.put()
+
+ self.response.out.write(svn_revision.key().id())
diff --git a/Tools/QueueStatusServer/handlers/updateworkitems.py b/Tools/QueueStatusServer/handlers/updateworkitems.py
new file mode 100644
index 0000000..16a9d49
--- /dev/null
+++ b/Tools/QueueStatusServer/handlers/updateworkitems.py
@@ -0,0 +1,66 @@
+# Copyright (C) 2010 Google Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+from google.appengine.ext import webapp, db
+from google.appengine.ext.webapp import template
+
+from handlers.updatebase import UpdateBase
+from model.queues import Queue
+from model.workitems import WorkItems
+
+from datetime import datetime
+
+
+class UpdateWorkItems(UpdateBase):
+ def get(self):
+ self.response.out.write(template.render("templates/updateworkitems.html", None))
+
+ def _parse_work_items_string(self, items_string):
+ # Our parsing could be much more robust.
+ item_strings = items_string.split(" ") if items_string else []
+ return map(int, item_strings)
+
+ def _work_items_from_request(self):
+ queue_name = self.request.get("queue_name")
+ queue = Queue.queue_with_name(queue_name)
+ if not queue:
+ self.response.out.write("\"%s\" is not in queues %s" % (queue_name, Queue.all()))
+ return None
+
+ items_string = self.request.get("work_items")
+ work_items = queue.work_items()
+ work_items.item_ids = self._parse_work_items_string(items_string)
+ work_items.date = datetime.now()
+ return work_items
+
+ def post(self):
+ work_items = self._work_items_from_request()
+ if not work_items:
+ self.response.set_status(500)
+ return
+ work_items.put()