ns_codecache.py :  » Network » PyWX » PyWX-1.0b2 » pywx-lib » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » PyWX 
PyWX » PyWX 1.0b2 » pywx lib » ns_codecache.py
# $Id: ns_codecache.py,v 1.1 2002/12/12 18:09:54 titus Exp $

###
### See included file COPYRIGHT for copyright and license information.
###

"""Implements a version of execfile() that caches the code in memory."""


import sys, os, stat, threading, string

import Ns

Ns.Log(Ns.Debug, 'importing ns_codecache.py')

#
# a simple code caching mechanism.
#

class CodeCache:

    # __init__ primarily acquires the code cache dictionary and
    # increments a counter so that it doesn't get deleted. __del__
    # decrements the counter.
    
    def __init__(self):
        Ns.Log(Ns.Debug, 'Creating CodeCache object')
        # Move lack of thread safety into creation of this counter + lock
        # (creation will later be moved into single-thread C function)

        # create counter lock if it doesn't exist. (@CTB --> initialize code)
        if not __persistdict__.has_key('_codeCacheCounter'):
            __persistdict__['_codeCacheCounterLock'] = threading.Lock()
            __persistdict__['_codeCacheCounter'] = 0

        # increment counter so no-one else flushes/cleans cache.
        self._incrementCounter()

        # create read/update lock if it doesn't exist:
        if not __persistdict__.has_key('_codeCacheLock'):
            __persistdict__['_codeCacheLock'] = threading.Lock()

        # now, get the dictionary.
        
        # Storing the dictionary turns out to be much easier than storing
        # an instance of the CodeCache class...
        if __persistdict__.has_key('_code'):
            # @@MRH: Potential problem here if cache is deleted by
            # another thread
            self._code = __persistdict__['_code']
        else:
            # @@MRH: Potential problem here if cache is initialized by
            # another thread
            self._code = {}
            __persistdict__['_code'] = self._code

    def __del__(self):
        # decrement the code cache counter
        Ns.Log(Ns.Debug, 'Decrementing CodeCache counter')
        self._decrementCounter()

    # save (mtime, code) into cache keyed by 'filename'
    def save(self, filename, code):
        Ns.Log(Ns.Debug, 'saving "%s" into CodeCache' % filename)
        try:
            mtime = os.stat(filename)[stat.ST_MTIME]
        except:
            return

        # atomic -- no locking necessary
        self._code[filename] = (mtime, code)

    # retrieve code (if up-to-date with filename) from cache
    def retrieve(self, filename):
        
        # @@CTB    __persistdict__['_codeCacheLock'].acquire()
        
        if self._code.has_key(filename): # in cache
            # @@MRH: Potential problem here if cache or cache entry is
            # deleted by another thread

            # retrieve cached mtime & code
            (old_mtime, code) = self._code[filename]

            # get new mtime
            try:
                new_mtime = os.stat(filename)[stat.ST_MTIME]
            except:
                return None             # file doesn't exist, etc.

            # compare
            if new_mtime != old_mtime:
                # @@MRH: Potential problem here if cache or cache entry
                # is deleted by another thread:
                del(self._code[filename]) # clear entry
                return None

            Ns.Log(Ns.Debug, 'retrieving "%s" from CodeCache' % filename)

            return code
            
        else:
            return None

    def _incrementCounter(self):
        __persistdict__['_codeCacheCounterLock'].acquire()
        __persistdict__['_codeCacheCounter'] = \
                __persistdict__['_codeCacheCounter'] + 1
        __persistdict__['_codeCacheCounterLock'].release()

    def _decrementCounter(self):
        __persistdict__['_codeCacheCounterLock'].acquire()
        __persistdict__['_codeCacheCounter'] = \
                __persistdict__['_codeCacheCounter'] - 1
        __persistdict__['_codeCacheCounterLock'].release()


#
# a function to replace standard Python execfile with something that makes
# use of code caching.
#

def execfile(filename, globaldict=None, localdict=None):
    Ns.Log(Ns.Debug, 'in pywx.execfile')

    codeCache = CodeCache()             # @@CTB

    code = codeCache.retrieve(filename)

    if not code:                        # ...then we want to compile it.
        Ns.Log(Ns.Debug, 'not in cache or mtime changed - forcing reload')

        f = open(filename, 'r')
        c = []
        for l in f.readlines():     # probably a faster way to do this...
            c.append(string.rstrip(l) + '\n')

        f.close()

        c = string.join(c, '')
        code = compile(c, filename, 'exec')

        codeCache.save(filename, code)

    if globaldict is None:
        globaldict = globals()
        localdict = locals()
    elif localdict is None:
        localdict = globaldict

    exec(code, globaldict, localdict)


#
# initialize
#

def initializeCachingExecFile():
    Ns.Log(Ns.Debug, 'Running initializeCachingExecFile().')
    ### MRH: Not thread safe (?)
    try:                                # already initialized?
        tst = __persistdict__['cachingExecFile']
    except:
        __persistdict__['cachingExecFile'] = 1

        # save a copy of the original
        __persistdict__['oldExecFile'] = sys.modules['__builtin__'].execfile
        
    # now replace the 'execfile' function:
    sys.modules['__builtin__'].execfile = execfile

#
# uninitialize
#

def uninitializeCachingExecFile():
    Ns.Log(Ns.Debug, 'Running uninitializeCachingExecFile().')
    try:                                # may not have been replaced!
        sys.modules['__builtin__'].execfile = __persistdict__['oldExecFile']
    except:
        pass


www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.