[Checkins] SVN: grokui.admin/trunk/ Merge js-pack-zodb branch

Jasper Spaans jspaans at thehealthagency.com
Wed Dec 3 15:37:19 EST 2008


Log message for revision 93592:
  Merge js-pack-zodb branch

Changed:
  U   grokui.admin/trunk/CHANGES.txt
  U   grokui.admin/trunk/src/grokui/admin/README.txt
  A   grokui.admin/trunk/src/grokui/admin/tests/packdatabase.py
  U   grokui.admin/trunk/src/grokui/admin/tests/server.py
  U   grokui.admin/trunk/src/grokui/admin/view.py
  U   grokui.admin/trunk/src/grokui/admin/view_templates/server.pt

-=-
Modified: grokui.admin/trunk/CHANGES.txt
===================================================================
--- grokui.admin/trunk/CHANGES.txt	2008-12-03 20:31:21 UTC (rev 93591)
+++ grokui.admin/trunk/CHANGES.txt	2008-12-03 20:37:13 UTC (rev 93592)
@@ -4,6 +4,11 @@
 0.3 (unreleased)
 ================
 
+Feature changes
+---------------
+
+* Added capability to pack ZODBs.
+
 0.2 (2008-12-01)
 ================
 

Modified: grokui.admin/trunk/src/grokui/admin/README.txt
===================================================================
--- grokui.admin/trunk/src/grokui/admin/README.txt	2008-12-03 20:31:21 UTC (rev 93591)
+++ grokui.admin/trunk/src/grokui/admin/README.txt	2008-12-03 20:37:13 UTC (rev 93592)
@@ -18,7 +18,7 @@
 
 The username and password of the manager principal (kind of super
 user) can be found in the file ``buildout.cfg`` in the root of your
-subversion checkout. 
+subversion checkout.
 
 In case you do not know, what 'subversion checkout' means, look for a
 file ``site.zcml`` in your installation.
@@ -65,6 +65,13 @@
 * Start/Restart the server. Caution! This does not work, if the server
   was started in 'foreground mode' (with 'zopectl fg').
 
+* Pack the ZODB. This removes old data from the database, freeing up
+  disk space. In a production environment, you might want to pack the
+  ZODB automatically from `cron`. This can be done using a command
+  like the following::
+
+    curl -q -s -u admin:admin "http://localhost:8080/server?pack=1&submitted=1"
+
 * Get basic information about the running Zope system.
 
 * Enter a message to be displayed on top. You can, for example, leave

Copied: grokui.admin/trunk/src/grokui/admin/tests/packdatabase.py (from rev 93591, grokui.admin/branches/js-pack-zodb/src/grokui/admin/tests/packdatabase.py)
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/packdatabase.py	                        (rev 0)
+++ grokui.admin/trunk/src/grokui/admin/tests/packdatabase.py	2008-12-03 20:37:13 UTC (rev 93592)
@@ -0,0 +1,80 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+Create a mammoth-manager, and stuff it with data which can be packed.
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+  >>> browser.open("http://localhost/")
+  >>> subform = browser.getForm(name='StuffedMammoth')
+  >>> subform.getControl('Name your new app:').value = 'my-stuffed-mammoth'
+  >>> subform.getControl('Create').click()
+
+  >>> mylink = browser.getLink('my-stuffed-mammoth (StuffedMammoth)').click()
+
+Stuff this mammoth.
+  >>> url = browser.url
+  >>> browser.open(url+"?stuffing=fresh+vegetables")
+  >>> print browser.contents
+  Today's meal is stuffed mammoth!
+
+Time to pull the stuffing out again.
+  >>> browser.open(url)
+  >>> print browser.contents
+  Time to stuff a mammoth!
+
+Check the size of the ZODB.
+  >>> browser.open("http://localhost/server")
+  >>> lines = [ l.strip() for l in browser.contents.split('\\n') ]
+  >>> zodb_size = lines[lines.index("Demo storage 'unnamed'")+  1]
+  >>> num_zodb_size = int(zodb_size.split(' ')[0])
+
+Now, pack the database.
+  >>> ctrl = browser.getControl(name='pack').click()
+  >>> lines = [ l.strip() for l in browser.contents.split('\\n') ]
+  >>> zodb_size = lines[lines.index("Demo storage 'unnamed'")+  1]
+  >>> new_num_zodb_size = int(zodb_size.split(' ')[0])
+
+Ensure that it is smaller now:
+  >>> new_num_zodb_size < num_zodb_size
+  True
+
+And clean up after ourselves.
+  >>> browser.open("http://localhost/applications")
+  >>> ctrl = browser.getControl(name='items')
+  >>> ctrl.getControl(value='my-stuffed-mammoth').selected = True
+  >>> browser.getControl('Delete Selected').click()
+
+"""
+
+import grok
+
+class StuffedMammoth(grok.Application, grok.Container):
+    """A stuffed mammoth"""
+    stuffing = None
+
+class Index(grok.View):#
+
+    def update(self, stuffing=None):
+        if stuffing is not None:
+            self.context.stuffing = stuffing*1000
+        else:
+            self.context.stuffing = None
+
+    def render(self):
+        if self.context.stuffing is None:
+            return u"Time to stuff a mammoth!"
+        else:
+            return u"Today's meal is stuffed mammoth!"

Modified: grokui.admin/trunk/src/grokui/admin/tests/server.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/tests/server.py	2008-12-03 20:31:21 UTC (rev 93591)
+++ grokui.admin/trunk/src/grokui/admin/tests/server.py	2008-12-03 20:37:13 UTC (rev 93592)
@@ -19,7 +19,7 @@
   >>> from zope.testbrowser.testing import Browser
   >>> browser = Browser()
   >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-  
+
 We fetch the standard page, which should provide us a menu to get all
 installable grok applications/components::
 
@@ -55,7 +55,7 @@
 
 If we submit that message, it should appear in the page::
 
-  >>> msg_form = browser.getForm(index=1)
+  >>> msg_form = browser.getForm(index=2)
   >>> msg_form.submit()
   >>> print browser.contents
   <html xmlns="http://www.w3.org/1999/xhtml">

Modified: grokui.admin/trunk/src/grokui/admin/view.py
===================================================================
--- grokui.admin/trunk/src/grokui/admin/view.py	2008-12-03 20:31:21 UTC (rev 93591)
+++ grokui.admin/trunk/src/grokui/admin/view.py	2008-12-03 20:37:13 UTC (rev 93592)
@@ -29,6 +29,7 @@
 from grokui.admin.utilities import getURLWithParams
 
 from ZODB.broken import Broken
+from ZODB.interfaces import IDatabase
 from BTrees.OOBTree import OOBTree
 
 import zope.component
@@ -38,6 +39,7 @@
 from zope.app.applicationcontrol.applicationcontrol import applicationController
 from zope.app.applicationcontrol.runtimeinfo import RuntimeInfo
 from zope.app.applicationcontrol.browser.runtimeinfo import RuntimeInfoView
+from zope.app.applicationcontrol.browser.zodbcontrol import ZODBControlView
 from zope.app.apidoc import utilities, codemodule
 from zope.app.apidoc.utilities import getPythonPath, renderText, columnize
 from zope.app.apidoc.codemodule.module import Module
@@ -51,6 +53,7 @@
 from zope.exceptions import DuplicationError
 from zope.proxy import removeAllProxies
 from zope.tal.taldefs import attrEscape
+from ZODB.FileStorage.FileStorage import FileStorageError
 
 import z3c.flashmessage.interfaces
 
@@ -135,7 +138,7 @@
 
         if not isinstance(items, list):
             items = [items]
-        
+
         if delete is not None:
             return self.delete(items)
         elif rename is not None:
@@ -177,29 +180,30 @@
 
     grok.context(Interface)
 
+
 class Rename(GAIAView):
     """Rename Grok applications.
     """
     grok.name('grokadmin_rename')
     grok.template('rename')
     grok.require('grok.ManageApplications')
-    
+
     def update(self, cancel=None, items=None, new_names=None):
         msg = u''
 
         if cancel is not None:
             return self.redirect(self.url(self.context))
-        
+
         if not isinstance(items, list):
             items = [items]
         self.apps = items
-        
+
         if new_names is not None and len(new_names) != len(items):
             return self.redirect(self.url(self.context))
 
         if new_names is None:
             return
-        
+
         mapping = dict([(items[x], new_names[x]) for x in range(len(items))])
 
         for oldname, newname in mapping.items():
@@ -431,7 +435,7 @@
             raise KeyError(message)
 
 
-class Server(GAIAView):
+class Server(GAIAView, ZODBControlView):
     """Zope3 management screen."""
 
     grok.require('grok.ManageApplications')
@@ -455,7 +459,8 @@
             return messages[0]
 
     def update(self, time=None, restart=None, shutdown=None,
-              admin_message=None, submitted=False):
+               admin_message=None, submitted=False,
+               dbName="", pack=None, days=0):
         if not submitted:
             return
         # Admin message control
@@ -480,9 +485,25 @@
         elif shutdown is not None:
             self.server_control.shutdown(time)
 
+        if pack is not None:
+            return self.pack(dbName, days)
+
         self.redirect(self.url())
 
+    def pack(self, dbName, days):
+        try:
+            days = int(days)
+        except ValueError:
+            self.flash('Error: Invalid Number')
+            return
+        db = zope.component.getUtility(IDatabase, name=dbName)
+        try:
+            db.pack(days=days)
+            self.flash('ZODB `%s` successfully packed.' % (dbName))
+        except FileStorageError, err:
+            self.flash('ERROR packing ZODB `%s`: %s' % (dbName, err))
 
+
 class Users(GAIAView):
     """Users management screen."""
 

Modified: grokui.admin/trunk/src/grokui/admin/view_templates/server.pt
===================================================================
--- grokui.admin/trunk/src/grokui/admin/view_templates/server.pt	2008-12-03 20:31:21 UTC (rev 93591)
+++ grokui.admin/trunk/src/grokui/admin/view_templates/server.pt	2008-12-03 20:37:13 UTC (rev 93592)
@@ -20,6 +20,25 @@
       </fieldset>
     </form>
 
+    <fieldset>
+      <legend>Manage your databases</legend>
+      <div tal:condition="not: python: len(view.databases)">
+        <p class="menu-description1">Currently no databases are active.</p>
+      </div>
+      <div tal:condition="python: len(view.databases) or True"
+	   tal:repeat="db view/databases">
+        <form method="post" action=""
+              tal:attributes="action string:${context/@@absolute_url}/server">
+	  <input type="hidden" name="submitted" value="true"/>
+          <input type="hidden" name="dbName" value="" tal:attributes="value db/utilName" />
+          <input type="text" name="days" value="0" size="3" title="Days of history to keep" />
+          <input class="button" type="submit" name="pack" value="Pack" />
+          <span tal:replace="db/dbName" />
+          <span tal:replace="db/size" />
+        </form>
+      </div>
+    </fieldset>
+
     <form method="post" action=""
       tal:attributes="action string:${context/@@absolute_url}/server">
       <fieldset>



More information about the Checkins mailing list