Kaydet (Commit) 32bd72c2 authored tarafından Eray Özkural's avatar Eray Özkural

* one-shot transaction protection for install and remove atomicops

üst 7ba956ac
......@@ -9,26 +9,19 @@
#
# Please read the COPYING file.
#
# Package install operation
# Author: Eray Ozkural <eray@uludag.org.tr>
# for python 2.3 compatibility
import sys
ver = sys.version_info
if ver[0] <= 2 and ver[1] < 4:
from sets import Set as set
import os
"Atomic package operations such as install/remove/upgrade"
import gettext
__trans = gettext.translation('pisi', fallback=True)
_ = __trans.ugettext
import pisi
import sys
import os
import bsddb3.db as db
import pisi
import pisi.context as ctx
import pisi.packagedb as packagedb
import pisi.dependency as dependency
......@@ -78,6 +71,7 @@ class Install(AtomicOperation):
(self.pkginfo.name, self.pkginfo.version,
self.pkginfo.release, self.pkginfo.build))
ctx.ui.notify(pisi.ui.installing, package = self.pkginfo, files = self.files)
self.ask_reinstall = ask_reinstall
self.check_requirements()
self.check_relations()
......@@ -90,7 +84,15 @@ class Install(AtomicOperation):
ctx.ui.notify(pisi.ui.configuring, package = self.pkginfo, files = self.files)
comariface.run_postinstall(self.pkginfo.name)
ctx.ui.notify(pisi.ui.configured, package = self.pkginfo, files = self.files)
self.update_databases()
txn = ctx.dbenv.txn_begin()
try:
self.update_databases(txn)
txn.commit()
except db.DBError, e:
txn.abort()
raise e
self.update_environment()
ctx.ui.status()
if self.upgrade:
......@@ -228,11 +230,10 @@ class Install(AtomicOperation):
pisi.comariface.register(pcomar, self.metadata.package.name,
scriptPath)
def update_databases(self):
def update_databases(self, txn):
"update databases"
if self.reinstall:
Remove(self.metadata.package.name).remove_db()
Remove(self.metadata.package.name).remove_db(txn)
if not self.same_ver:
Remove.remove_pisi_files(self.old_path)
......@@ -241,13 +242,14 @@ class Install(AtomicOperation):
self.metadata.package.version,
self.metadata.package.release,
self.metadata.package.build,
self.metadata.package.distribution)
self.metadata.package.distribution,
txn)
# filesdb
ctx.filesdb.add_files(self.metadata.package.name, self.files)
ctx.filesdb.add_files(self.metadata.package.name, self.files, txn)
# installed packages
packagedb.inst_packagedb.add_package(self.pkginfo)
packagedb.inst_packagedb.add_package(self.pkginfo, txn)
def update_environment(self):
# check if we have any shared objects or anything under
......@@ -327,8 +329,15 @@ class Remove(AtomicOperation):
for fileinfo in self.files.list:
self.remove_file(fileinfo)
self.remove_db()
txn = ctx.dbenv.txn_begin()
try:
self.remove_db(txn)
txn.commit()
except db.DBError, e:
txn.abort()
raise e
self.remove_pisi_files(self.package.pkg_dir())
ctx.ui.status()
ctx.ui.notify(pisi.ui.removed, package = self.package, files = self.files)
......@@ -372,11 +381,13 @@ class Remove(AtomicOperation):
remove_pisi_files = staticmethod(remove_pisi_files)
def remove_db(self):
ctx.installdb.remove(self.package_name)
ctx.filesdb.remove_files(ctx.installdb.files(self.package_name))
#FIXME: this looks like a mistake!
packagedb.remove_package(self.package_name)
def remove_db(self, txn):
ctx.installdb.remove(self.package_name, txn)
ctx.filesdb.remove_files(ctx.installdb.files(self.package_name), txn)
if packagedb.thirdparty_packagedb.has_package(self.package_name, txn):
packagedb.thirdparty_packagedb.remove_package(self.package_name, txn)
if packagedb.inst_packagedb.has_package(self.package_name, txn):
packagedb.inst_packagedb.remove_package(self.package_name, txn)
def remove_single(package_name):
......
......@@ -41,3 +41,19 @@ initialized = False
#def register(_impl):
# """ Register a UI implementation"""
# ui = _impl
def txn_proc(proc, txn):
# can be used to txn protect a method automatically
assert dbenv
if not txn:
autotxn = dbenv.txn_begin()
try:
retval = proc(autotxn)
except db.DBError, e:
autotxn.abort()
raise e
autotxn.commit()
return retval
else:
return proc(txn)
......@@ -51,7 +51,7 @@ class DBShelf:
return self.db.has_key(key, txn)
else:
return self.db.has_key(key)
def txn_proc(self, proc, txn):
# can be used to txn protect a method automatically
if not txn:
......
......@@ -161,26 +161,31 @@ class InstallDB:
self.d.txn_proc(proc,txn)
def clear_pending(self, pkg):
def clear_pending(self, pkg, txn = None):
pkg = str(pkg)
info = self.d[pkg]
if self.is_installed(pkg):
assert info.state == 'ip'
info.state = 'i'
self.d[pkg] = info
del self.dp[pkg]
def proc(txn):
info = self.d.get(pkg, txn)
if self.is_installed(pkg, txn):
assert info.state == 'ip'
info.state = 'i'
self.d.put(pkg, info, txn)
self.dp.delete(pkg, txn)
self.d.txn_proc(proc,txn)
def remove(self, pkg):
def remove(self, pkg, txn = None):
pkg = str(pkg)
info = self.d[pkg]
info.state = 'r'
self.d[pkg] = info
def proc(txn):
info = self.d.get(pkg, txn)
info.state = 'r'
self.d.put(pkg, info, txn)
self.d.txn_proc(proc, txn)
def purge(self, pkg):
def purge(self, pkg, txn = None):
pkg = str(pkg)
if self.d.has_key(pkg):
del self.d[pkg]
def proc(txn):
if self.d.has_key(pkg, txn):
self.d.delete(pkg, txn)
self.d.txn_proc(proc, txn)
db = None
......
......@@ -36,7 +36,11 @@ class Error(pisi.Error):
def init_dbenv():
ctx.dbenv = dbobj.DBEnv()
ctx.dbenv.open(pisi.context.config.db_dir(),
db.DB_CREATE | db.DB_INIT_MPOOL | db.DB_INIT_TXN | db.DB_INIT_LOG )
db.DB_CREATE | # allow db to create files
db.DB_INIT_MPOOL | # cache
db.DB_INIT_TXN | # transaction subsystem
db.DB_INIT_LOG | # logging subsystem
db.DB_RECOVER) # run normal recovery
#def open(filename, flags='r', mode = 0644, filetype = db.DB_BTREE):
# db = LockedDBShelf(None, mode, filetype, None, True)
......
......@@ -44,9 +44,9 @@ class PackageDB(object):
self.d.close()
self.dr.close()
def has_package(self, name):
def has_package(self, name, txn = None):
name = str(name)
return self.d.has_key(name)
return self.d.has_key(name, txn)
def get_package(self, name):
name = str(name)
......@@ -95,12 +95,14 @@ class PackageDB(object):
def clear(self):
self.d.clear()
def remove_package(self, name):
def remove_package(self, name, txn = None):
name = str(name)
package_info = self.d[name]
del self.d[name]
#FIXME: what's happening to dr?
ctx.componentdb.remove_package(package_info.partOf, package_info.name)
def proc(txn):
package_info = self.d.get(name, txn)
self.d.delete(name, txn)
#FIXME: what's happening to dr?
ctx.componentdb.remove_package(package_info.partOf, package_info.name, txn)
self.d.txn_proc(proc, txn)
packagedbs = {}
......@@ -114,18 +116,22 @@ def remove_db(name):
del pisi.packagedb.packagedbs[name]
#FIXME: erase database file?
def has_package(name):
repo = which_repo(name)
if repo or thirdparty_packagedb.has_package(name) or inst_packagedb.has_package(name):
return True
return False
def which_repo(name):
def has_package(name, txn = None):
def proc(txn):
repo = which_repo(name)
if repo or thirdparty_packagedb.has_package(name, txn) or inst_packagedb.has_package(name, txn):
return True
return False
return ctx.txn_proc(proc, txn)
def which_repo(name, txn = None):
import pisi.repodb
for repo in pisi.repodb.db.list():
if get_db(repo).has_package(name):
return repo
return None
def proc(txn):
for repo in pisi.repodb.db.list():
if get_db(repo).has_package(name, txn):
return repo
return None
return ctx.txn_proc(proc, txn)
def get_package(name):
repo = which_repo(name)
......
......@@ -59,7 +59,7 @@ class RepoDB(object):
l = self.list()
return l[ix]
def swap(self, x,y):
def swap(self, x, y):
l = self.d["order"]
t = l[x]
l[x] = l[y]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment