Jean-Claude Wippler wrote:

> Georg Bauer wrote:
>
>> But this file can't be opened by metakit.
>
>
> Try the mkstats utility mentioned at the end of:
> http://www.equi4.com/metakit.html
>
> If errors are reported, then the file is definitely damaged.
>
> One cause for this is having a MK file open more than once in r/w
> mode - if things are mixed up, writes over each other will lead to
> a damaged datafile.  For example, this can happen when quitting an
> app and launching it again before the first instance has really
> exited and flushed its I/O.
>
There is a pretty simple python solution for detecting multiple open
files.  I have a common database that multiple users can open so I
needed a mechanism to prevent multiple people from opening the same
database.  Metakit allows for a super header that is appended before
the metakit database.  This can be any binary data that doesn't
contain the metakit magic string.

Here is a simple python recipe that you can call to see if a database
is opened or not.  What it does is it transparently wraps a storage
and puts in a 32 byte header to store various flags.  One of which is
"is this database open" when the storage closes down and is deleted,
it resets the superheader flags.  You can see the test cases at the
end... Other wise the storage can be used as a normal storage.  My
metakit server actually stores the ip address and socket of the host
machine for the database and automagically connects to the server to
use the database :)  I stole this from FileMaker I think.

Anyway, enjoy...


import metakit, array, os

OPEN_STORAGE = 0x01
CLOSED_STORAGE = 0x00
OPEN_STORAGE_STR = array.array('i', [0x01]).tostring()
CLOSED_STORAGE_STR = array.array('i', [0]).tostring()

class storage:
    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode
        self.st = None
        if mode == 0:
            self.st = metakit.storage(filename, mode)
        else:
            if os.path.exists(filename):
                # check the superheader
                file = open(filename, "rb")
                buffer = array.array("i", file.read(32))
                file.close()
                if buffer[0] & OPEN_STORAGE:
                    raise IOError("Database already open")

                file = open(filename, 'r+b')
                file.write(OPEN_STORAGE_STR)
                file.close()
                self.st = metakit.storage(filename, mode)
            else:
                a = array.array("i", [OPEN_STORAGE,0,0,0])
                file = open(filename, 'wb')
                file.write(a.tostring())
                file.close()
                self.st = metakit.storage(filename, mode)

    def __del__(self):
        self.close(True)

    def close(self,noerrors=False):
        if not noerrors and not self.st:
            raise IOError("Database already closed")
        del self.st
        self.st = None
        if self.mode and os.path.exists(self.filename):
            file = open(self.filename, 'r+b')
            file.write(CLOSED_STORAGE_STR)
            file.close()
            del file

        
    def __getattr__(self, attr):
        return getattr(self.st, attr)

def forceopen(filename):
    """Force a storage to open, the storage must exist"""
    file = open(self.filename, 'r+b')
    file.write(CLOSED_STORAGE_STR)
    file.close()

def test():
    s2 = storage("foo8", 1)
    try:
        s2 = storage("foo8", 1)
    except IOError:
        print "caught error, database is open"
    
    del s2
    s2 = storage("foo8", 1)
    s2.close()
    os.remove("foo8")
_____________________________________________
Metakit mailing list  -  [EMAIL PROTECTED]
http://www.equi4.com/mailman/listinfo/metakit

Reply via email to