chiark / gitweb /
Add commentary and licence notices.
[rhodes] / rhodes
diff --git a/rhodes b/rhodes
index 8509a4fcf5a25d8afa755994fd830f51f53c84ba..01a7aad065b01664a3e44b70d7830f5b8a14efa6 100755 (executable)
--- a/rhodes
+++ b/rhodes
@@ -1,4 +1,28 @@
 #! /usr/bin/python
+### -*-python-*-
+###
+### Calculate discrete logs in groups
+###
+### (c) 2017 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of Rhodes, a distributed discrete-log finder.
+###
+### Rhodes is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### Rhodes is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with Rhodes; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
 from sys import argv, stdout, stderr, exit
 import errno as E
@@ -11,9 +35,15 @@ import signal as SIG
 import catacomb as C
 import sqlite3 as SQL
 
+###--------------------------------------------------------------------------
+### Miscellaneous utilities.
+
 class ExpectedError (Exception):
   pass
 
+###--------------------------------------------------------------------------
+### Database handling.
+
 CONNINIT_SQL = """
 PRAGMA foreign_keys = on;
 """
@@ -54,6 +84,16 @@ CREATE TABLE points
          FOREIGN KEY (p, k) REFERENCES progress (p, k));
 """
 
+def connect_db(dir):
+  db = SQL.connect(OS.path.join(dir, 'db'))
+  db.text_factory = str
+  c = db.cursor()
+  c.executescript(CONNINIT_SQL)
+  return db
+
+###--------------------------------------------------------------------------
+### Group support.
+
 GROUPMAP = {}
 
 class GroupClass (type):
@@ -96,6 +136,9 @@ class BinaryFieldUnitGroup (BaseGroup):
 
 def getgroup(kind, desc): return GROUPMAP[kind](desc)
 
+###--------------------------------------------------------------------------
+### Number-theoretic utilities.
+
 def factor(n):
   ff = []
   proc = S.Popen(['./factor', str(n)], stdout = S.PIPE)
@@ -106,6 +149,9 @@ def factor(n):
   if rc: raise ExpectedError, 'factor failed: rc = %d' % rc
   return ff
 
+###--------------------------------------------------------------------------
+### Command dispatch.
+
 CMDMAP = {}
 
 def defcommand(f, name = None):
@@ -116,12 +162,67 @@ def defcommand(f, name = None):
     CMDMAP[name] = f
     return f
 
-def connect_db(dir):
-  db = SQL.connect(OS.path.join(dir, 'db'))
-  db.text_factory = str
+###--------------------------------------------------------------------------
+### Job status utilities.
+
+def get_top(db):
   c = db.cursor()
-  c.executescript(CONNINIT_SQL)
-  return db
+  c.execute("""SELECT kind, groupdesc, g, x, m, n FROM top""")
+  kind, groupdesc, gstr, xstr, mstr, nstr = c.fetchone()
+  G = getgroup(kind, groupdesc)
+  g, x, m = G.elt(gstr), G.elt(xstr), C.MP(mstr)
+  n = nstr is not None and C.MP(nstr) or None
+  return G, g, x, m, n
+
+def get_job(db):
+  c = db.cursor()
+  c.execute("""SELECT p.p, p.e, p.k, p.n, p.dpbits
+               FROM progress AS p LEFT OUTER JOIN workers AS w
+                       ON p.p = w.p and p.k = w.k
+               WHERE p.k < p.e AND (p.dpbits > 0 OR w.pid IS NULL)
+               LIMIT 1""")
+  row = c.fetchone()
+  if row is None: return None, None, None, None, None
+  else:
+    pstr, e, k, nstr, dpbits = row
+    p, n = C.MP(pstr), C.MP(nstr)
+    return p, e, k, n, dpbits
+
+def maybe_cleanup_worker(dir, db, pid):
+  c = db.cursor()
+  f = OS.path.join(dir, 'lk.%d' % pid)
+  state = 'LIVE'
+  try: fd = OS.open(f, OS.O_WRONLY)
+  except OSError, err:
+    if err.errno != E.ENOENT: raise ExpectedError, 'open lockfile: %s' % err
+    state = 'STALE'
+  else:
+    try: F.lockf(fd, F.LOCK_EX | F.LOCK_NB)
+    except IOError, err:
+      if err.errno != E.EAGAIN: raise ExpectedError, 'check lock: %s' % err
+    else:
+      state = 'STALE'
+  if state == 'STALE':
+    try: OS.unlink(f)
+    except OSError: pass
+    c.execute("""DELETE FROM workers WHERE pid = ?""", (pid,))
+
+def maybe_kill_worker(dir, pid):
+  f = OS.path.join(dir, 'lk.%d' % pid)
+  try: fd = OS.open(f, OS.O_RDWR)
+  except OSError, err:
+    if err.errno != E.ENOENT: raise ExpectedError, 'open lockfile: %s' % err
+    return
+  try: F.lockf(fd, F.LOCK_EX | F.LOCK_NB)
+  except IOError, err:
+    if err.errno != E.EAGAIN: raise ExpectedError, 'check lock: %s' % err
+  else: return
+  OS.kill(pid, SIG.SIGTERM)
+  try: OS.unlink(f)
+  except OSError: pass
+
+###--------------------------------------------------------------------------
+### Setup.
 
 @defcommand
 def setup(dir, kind, groupdesc, gstr, xstr):
@@ -166,14 +267,8 @@ def setup(dir, kind, groupdesc, gstr, xstr):
       c.execute("""INSERT INTO progress (p, e, dpbits) VALUES (?, ?, ?)""",
                 (str(p), e, dpbits))
 
-def get_top(db):
-  c = db.cursor()
-  c.execute("""SELECT kind, groupdesc, g, x, m, n FROM top""")
-  kind, groupdesc, gstr, xstr, mstr, nstr = c.fetchone()
-  G = getgroup(kind, groupdesc)
-  g, x, m = G.elt(gstr), G.elt(xstr), C.MP(mstr)
-  n = nstr is not None and C.MP(nstr) or None
-  return G, g, x, m, n
+###--------------------------------------------------------------------------
+### Check.
 
 @defcommand
 def check(dir):
@@ -239,19 +334,8 @@ def check(dir):
 
   exit(rc[0])
 
-def get_job(db):
-  c = db.cursor()
-  c.execute("""SELECT p.p, p.e, p.k, p.n, p.dpbits
-               FROM progress AS p LEFT OUTER JOIN workers AS w
-                       ON p.p = w.p and p.k = w.k
-               WHERE p.k < p.e AND (p.dpbits > 0 OR w.pid IS NULL)
-               LIMIT 1""")
-  row = c.fetchone()
-  if row is None: return None, None, None, None, None
-  else:
-    pstr, e, k, nstr, dpbits = row
-    p, n = C.MP(pstr), C.MP(nstr)
-    return p, e, k, n, dpbits
+###--------------------------------------------------------------------------
+### Done.
 
 @defcommand
 def done(dir):
@@ -265,38 +349,8 @@ def done(dir):
   if p is None: exit(2)
   else: exit(1)
 
-def maybe_cleanup_worker(dir, db, pid):
-  c = db.cursor()
-  f = OS.path.join(dir, 'lk.%d' % pid)
-  state = 'LIVE'
-  try: fd = OS.open(f, OS.O_WRONLY)
-  except OSError, err:
-    if err.errno != E.ENOENT: raise ExpectedError, 'open lockfile: %s' % err
-    state = 'STALE'
-  else:
-    try: F.lockf(fd, F.LOCK_EX | F.LOCK_NB)
-    except IOError, err:
-      if err.errno != E.EAGAIN: raise ExpectedError, 'check lock: %s' % err
-    else:
-      state = 'STALE'
-  if state == 'STALE':
-    try: OS.unlink(f)
-    except OSError: pass
-    c.execute("""DELETE FROM workers WHERE pid = ?""", (pid,))
-
-def maybe_kill_worker(dir, pid):
-  f = OS.path.join(dir, 'lk.%d' % pid)
-  try: fd = OS.open(f, OS.O_RDWR)
-  except OSError, err:
-    if err.errno != E.ENOENT: raise ExpectedError, 'open lockfile: %s' % err
-    return
-  try: F.lockf(fd, F.LOCK_EX | F.LOCK_NB)
-  except IOError, err:
-    if err.errno != E.EAGAIN: raise ExpectedError, 'check lock: %s' % err
-  else: return
-  OS.kill(pid, SIG.SIGTERM)
-  try: OS.unlink(f)
-  except OSError: pass
+###--------------------------------------------------------------------------
+### Step.
 
 @defcommand
 def step(dir, cmd, *args):
@@ -516,6 +570,9 @@ def step(dir, cmd, *args):
     with db:
       c.execute("""DELETE FROM workers WHERE pid = ?""", (mypid,))
 
+###--------------------------------------------------------------------------
+### Top-level program.
+
 PROG = argv[0]
 
 try: