DEVELOPERS GUIDE
Module: | pyfileserver |
Author: |
Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: |
Lesser GNU Public License, see LICENSE file attached with package |
This section attempts to give a brief introduction to the PyFileServer application package.
PyFileServer is a WSGI application.
WSGI <http://www.python.org/peps/pep-0333.html> stands for Web Server Gateway
Interface, a proposed standard interface between web servers and Python web
applications or frameworks, to promote web application portability across a
variety of web servers. If you are unfamiliar with WSGI, do take a moment to
read the PEP. Most WSGI application consists middleware which serve as pre-filters and
post-processors, and the actual application.
PyFileServer:
Request -> PyFileApp (container)
|
+-> ErrorPrinter (middleware)
|
RequestResolver (middleware)
|
HTTPAuthenticator (middleware)
|
RequestServer (application)
In addition, PyFileServer comes with an existing WSGI webserver so that the
application can be run as a standalone program.
The PyFileServer application consists of the following modules:
Bundled Web Server:
ext_wsgiutils_server
Application objects:
pyfileserver.mainappwrapper
+ class PyFileApp
pyfileserver.processrequesterrorhandler
+ class ErrorPrinter
+ Exception HTTPRequestException
pyfileserver.requestresolver
+ class RequestResolver
pyfileserver.httpauthentication
+ class HTTPAuthenticator
+ class SimpleDomainController
pyfileserver.pyfiledomaincontroller
+ class PyFileServerDomainController
pyfileserver.extrequestserver
+ class RequestServer
pyfileserver.propertylibrary
+ class LockManager
+ class PropertyManager
pyfileserver.etagprovider
+ func object getETag
Miscellaneous libraries:
pyfileserver.websupportfuncs
pyfileserver.loadconfig_primitive
pyfileserver.httpdatehelper
Each of these modules are documented below.
PyFileServer comes bundled with a simple wsgi webserver.
To run as a standalone server using the bundled ext_wsgiutils_server.py:
usage: python ext_wsgiutils_server.py [options] [config-file]
config-file:
The configuration file for PyFileServer. if omitted, the application
will look for a file named 'PyFileServer.conf' in the current directory
options:
--port=PORT Port to serve on (default: 8080)
--host=HOST Host to serve from (default: localhost, which is only
accessible from the local computer; use 0.0.0.0 to make your
application public)
-h, --help show this help message and exit
To run it with other WSGI web servers, you can:
from pyfileserver.mainappwrapper import PyFileApp
publish_app = PyFileApp('PyFileServer.conf')
# construct the application with configuration file
# if configuration file is omitted, the application
# will look for a file named 'PyFileServer.conf'
# in the current directory
where publish_app is the WSGI application to be run, it will be called with
publish_app(environ, start_response) for each incoming request, as described in
WSGI <http://www.python.org/peps/pep-0333.html>
Note: if you are using the paster development server (from Paste <http://pythonpaste.org>), you can
copy ext_wsgi_server.py to <Paste-installation>/paste/servers and use this server to run the
application by specifying server='ext_wsgiutils' in the server.conf or appropriate paste
configuration.
Module: | pyfileserver.mainappwrapper |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
See Running PyFileServer in ext_wsgiutils_server.py
Module: | pyfileserver.processrequesterrorhandler |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
WSGI Middleware to catch application thrown HTTPRequestExceptions and return
proper responses
Usage:
from pyfileserver.processrequesterrorhandler import ErrorPrinter
WSGIApp = ErrorPrinter(ProtectedWSGIApp, server_descriptor, catchall)
where:
ProtectedWSGIApp is the application throwing HTTPRequestExceptions,
server_descriptor is an optional html string to be included as the
footer of any html response sent
catchall is an optional boolean. if True, ErrorPrinter will catch all
other exceptions and print a trace to sys.stderr stream before sending
a 500 Internal Server Error response (default = False)
Within ProtectedWSGIApp:
from pyfileserver import processrequesterrorhandler
from pyfileserver.processrequesterrorhandler import HTTPRequestException
...
...
raise HTTPRequestException(404)
or
raise HTTPRequestException(processrequesterrorhandler.HTTP_BAD_REQUEST)
#escape the existing application and return the 404 Bad Request immediately
Occasionally it may be useful for an internal ProtectedWSGIApp method to catch the
HTTPRequestException (for compiling into a multi-status, for example). The response
code of the error can be returned as:
from pyfileserver import processrequesterrorhandler
from pyfileserver.processrequesterrorhandler import HTTPRequestException
try:
...
raise HTTPRequestException(processrequesterrorhandler.HTTP_BAD_REQUEST)
...
except HTTPRequestException, e:
numberCode = processrequesterrorhandler.getErrorCodeFromException(e)
textCode = processrequesterrorhandler.interpretErrorException(e)
Classes:
- 'ErrorPrinter': WSGI Middleware to catch HTTPRequestExceptions and return
proper responses
Exception(s):
- 'HTTPRequestException': Raised with error code integer (1xx-5xx) within protected
application to be caught by ErrorPrinter
Function(s):
- 'interpretErrorException(e)': Returns response code string for HTTPRequestException
e.
- 'getErrorCodeFromException(e)': Returns the response code number (1xx-5xx) for
HTTPRequestException e
Constants:
HTTP_CONTINUE = 100
HTTP_SWITCHING_PROTOCOLS = 101
HTTP_PROCESSING = 102
HTTP_OK = 200
HTTP_CREATED = 201
HTTP_ACCEPTED = 202
HTTP_NON_AUTHORITATIVE_INFO = 203
HTTP_NO_CONTENT = 204
HTTP_RESET_CONTENT = 205
HTTP_PARTIAL_CONTENT = 206
HTTP_MULTI_STATUS = 207
HTTP_IM_USED = 226
HTTP_MULTIPLE_CHOICES = 300
HTTP_MOVED = 301
HTTP_FOUND = 302
HTTP_SEE_OTHER = 303
HTTP_NOT_MODIFIED = 304
HTTP_USE_PROXY = 305
HTTP_TEMP_REDIRECT = 307
HTTP_BAD_REQUEST = 400
HTTP_PAYMENT_REQUIRED = 402
HTTP_FORBIDDEN = 403
HTTP_NOT_FOUND = 404
HTTP_METHOD_NOT_ALLOWED = 405
HTTP_NOT_ACCEPTABLE = 406
HTTP_PROXY_AUTH_REQUIRED = 407
HTTP_REQUEST_TIMEOUT = 408
HTTP_CONFLICT = 409
HTTP_GONE = 410
HTTP_LENGTH_REQUIRED = 411
HTTP_PRECONDITION_FAILED = 412
HTTP_REQUEST_ENTITY_TOO_LARGE = 413
HTTP_REQUEST_URI_TOO_LONG = 414
HTTP_MEDIATYPE_NOT_SUPPORTED = 415
HTTP_RANGE_NOT_SATISFIABLE = 416
HTTP_EXPECTATION_FAILED = 417
HTTP_UNPROCESSABLE_ENTITY = 422
HTTP_LOCKED = 423
HTTP_FAILED_DEPENDENCY = 424
HTTP_UPGRADE_REQUIRED = 426
HTTP_INTERNAL_ERROR = 500
HTTP_NOT_IMPLEMENTED = 501
HTTP_BAD_GATEWAY = 502
HTTP_SERVICE_UNAVAILABLE = 503
HTTP_GATEWAY_TIMEOUT = 504
HTTP_VERSION_NOT_SUPPORTED = 505
HTTP_INSUFFICIENT_STORAGE = 507
HTTP_NOT_EXTENDED = 510
Module: | pyfileserver.requestresolver |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
PyFileServer allows the user to specify in PyFileServer.conf a number of
realms, and a number of users for each realm.
- Realms
Each realm corresponds to a filestructure on disk to be stored,
for example:
addrealm('pubshare','/home/public/share')
would allow the users to access using WebDAV the directory/file
structure at /home/public/share from the url
http://<servername:port>/<approot>/pubshare
The realm name is set as '/pubshare'
e.g. /home/public/share/PyFileServer/LICENSE becomes accessible as
http://<servername:port>/<approot>/pubshare/PyFileServer/LICENSE
- Users
A number of username/password pairs can be set for each realm:
adduser('pubshare', 'username', 'password', 'description/unused')
would add a username/password pair to realm /pubshare.
Note: if developers wish to maintain a separate users database, you can
write your own domain controller for the HTTPAuthenticator. See
httpauthentication.py and pyfiledomaincontroller.py for more details.
This module is specific to the PyFileServer application
WSGI Middleware for Resolving Realm and Paths for the PyFileServer
application.
Usage:
from pyfileserver.requestresolver import RequestResolver
WSGIApp = RequestResolver(InternalWSGIApp)
The RequestResolver resolves the requested URL to the following values
placed in the environ dictionary. First it resolves the corresponding
realm:
url: http://<servername:port>/<approot>/pubshare/PyFileServer/LICENSE
environ['pyfileserver.mappedrealm'] = /pubshare
Based on the configuration given, the resource abstraction layer for the
realm is determined. if no configured abstraction layer is found, the
default abstraction layer fileabstractionlayer.FilesystemAbstractionLayer()
is used:
environ['pyfileserver.resourceAL'] = fileabstractionlayer.MyOwnFilesystemAbstractionLayer()
The path identifiers for the requested url are then resolved using the
resource abstraction layer:
environ['pyfileserver.mappedpath'] = /home/public/share/PyFileServer/LICENSE
environ['pyfileserver.mappedURI'] = /pubshare/PyFileServer/LICENSE
in this case, FilesystemAbstractionLayer resolves any relative paths
to its canonical absolute path
The RequestResolver also resolves any value in the Destination request
header, if present, to:
Destination: http://<servername:port>/<approot>/pubshare/PyFileServer/LICENSE-dest
environ['pyfileserver.destrealm'] = /pubshare
environ['pyfileserver.destpath'] = /home/public/share/PyFileServer/LICENSE-dest
environ['pyfileserver.destURI'] = /pubshare/PyFileServer/LICENSE
environ['pyfileserver.destresourceAL'] = fileabstractionlayer.MyOwnFilesystemAbstractionLayer()
classes:
RequestResolver: Request resolver for PyFileServer
Module: | pyfileserver.httpauthentication |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
WSGI middleware for HTTP basic and digest authentication.
- Usage::
from httpauthentication import HTTPAuthenticator
- WSGIApp = HTTPAuthenticator(ProtectedWSGIApp, domain_controller, acceptbasic,
- acceptdigest, defaultdigest)
- where:
ProtectedWSGIApp is the application requiring authenticated access
domain_controller is a domain controller object meeting specific
requirements (below)
acceptbasic is a boolean indicating whether to accept requests using
the basic authentication scheme (default = True)
acceptdigest is a boolean indicating whether to accept requests using
the digest authentication scheme (default = True)
defaultdigest is a boolean. if True, an unauthenticated request will
be sent a digest authentication required response, else the unathenticated
request will be sent a basic authentication required response
(default = True)
The HTTPAuthenticator will put the following authenticated information in the
environ dictionary:
environ['httpauthentication.realm'] = realm name
environ['httpauthentication.username'] = username
The HTTP basic and digest authentication schemes are based on the following
concept:
Each requested relative URI can be resolved to a realm for authentication,
for example:
/fac_eng/courses/ee5903/timetable.pdf -> might resolve to realm 'Engineering General'
/fac_eng/examsolns/ee5903/thisyearssolns.pdf -> might resolve to realm 'Engineering Lecturers'
/med_sci/courses/m500/surgery.htm -> might resolve to realm 'Medical Sciences General'
and each realm would have a set of username and password pairs that would
allow access to the resource.
A domain controller provides this information to the HTTPAuthenticator.
This allows developers to write their own domain controllers, that might,
for example, interface with their own user database.
for simple applications, a SimpleDomainController is provided that will take
in a single realm name (for display) and a single dictionary of username (key)
and password (value) string pairs
- Usage::
- from httpauthentication import SimpleDomainController
users = dict(({'John Smith': 'YouNeverGuessMe', 'Dan Brown': 'DontGuessMeEither'})
realm = 'Sample Realm'
domain_controller = SimpleDomainController(users, realm)
Domain Controllers must provide the methods as described in
pyfileserver.interfaces.domaincontrollerinterface (interface)
The environ variable here is the WSGI 'environ' dictionary. It is passed to
all methods of the domain controller as a means for developers to pass information
from previous middleware or server config (if required).
Classes
- HTTPAuthenticator : WSGI Middleware for basic and digest authenticator.
- SimpleDomainController : Simple domain controller for HTTPAuthenticator.
Module: | pyfileserver.pyfiledomaincontroller |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
This module is specific to the PyFileServer application.
The PyFileServerDomainController fulfills the requirements of a
DomainController as used for authentication with
httpauthentication.HTTPAuthenticator for the PyFileServer application
Domain Controllers must provide the methods as described in
domaincontrollerinterface
See requestresolver.py for more information about user mappings in
PyFileServer
Module: | pyfileserver.extrequestserver |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
This is the main implementation module for the various webDAV methods. Each
method is implemented as a do<METHOD> generator function that is a wsgi
subapplication:
class RequestServer(object)
constructor :
__init__(self, propertymanager,
lockmanager)
main application:
__call__(self, environ, start_response)
application methods:
doPUT(self, environ, start_response)
doOPTIONS(self, environ, start_response)
doGETHEADDirectory(self, environ, start_response)
doGETHEADFile(self, environ, start_response)
doMKCOL(self, environ, start_response)
doDELETE(self, environ, start_response)
doPROPPATCH(self, environ, start_response)
doPROPFIND(self, environ, start_response)
doCOPY(self, environ, start_response)
doMOVE(self, environ, start_response)
doLOCK(self, environ, start_response)
doUNLOCK(self, environ, start_response)
misc methods:
evaluateSingleIfConditionalDoException(self, mappedpath, displaypath,
environ, start_response, checkLock = False)
evaluateSingleHTTPConditionalsDoException(self, mappedpath,
displaypath, environ, start_response)
This module is specific to the PyFileServer application.
The RequestServer takes two supporting objects:
- propertymanager
An object that provides storage for dead properties assigned for webDAV resources.
PropertyManagers must provide the methods as described in
pyfileserver.interfaces.propertymanagerinterface
See propertylibrary.PropertyManager for a sample implementation
using shelve.
- lockmanager
An object that provides storage for locks made on webDAV resources.
LockManagers must provide the methods as described in
pyfileserver.interfaces.lockmanagerinterface
See locklibrary.LockManager for a sample implementation
using shelve.
The RequestServer also uses a resource abstraction layer placed in
environ['pyfileserver.resourceAL'] by requestresolver.py
- abstractionlayer
An object that provides a basic interface to resources.
This layer allows developers to write layers allowing the application to share
resources other than filesystems.
Abstraction Layers must provide the methods as described in
pyfileserver.interfaces.abstractionlayerinterface
See fileabstractionlayer.FilesystemAbstractionLayer and
fileabstractionlayer.ReadOnlyFilesystemAbstractionLayer for sample
implementations based on filesystems.
Module: | pyfileserver.websupportfuncs |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
This module consists of miscellaneous support functions for PyFileServer:
resource list functions
recursiveGetPath(resourceAL, dirtorecurs, displaypath, recursfurther, liststore, preadd=True)
getDepthActionList(resourceAL, mappedpath, displaypath, depthlevel, preadd=True)
getCopyDepthActionList(depthactionlist, origpath, origdisplaypath, destpath, destdisplaypath)
URL functions
getLevelUpURL(displayPath)
cleanUpURL(displayURL)
cleanUpURLWithoutQuote(displayURL)
constructFullURL(displaypath, environ)
getRelativeURL(fullurl, environ)
interpret content range header
obtainContentRanges(rangetext, filesize)
evaluate HTTP If-Match, if-None-Match, If-Modified-Since, If-Unmodified-Since headers
evaluateHTTPConditionals(lastmodifiedsecs, entitytag, environ, isnewfile=False)
evaluate webDAV if header
getIfHeaderDict(iftext)
testIfHeaderDict(dictIf, url, locktokenlist, entitytag, returnlocklist, environ)
testForLockTokenInIfHeaderDict(dictIf, locktoken, fullurl, headurl)
author note: More documentation here required
This module is specific to the PyFileServer application.
Module: | pyfileserver.propertylibrary |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
This module consists of a number of miscellaneous functions for the dead
properties features of webDAV.
It also includes an implementation of a PropertyManager for
storage of dead properties. This implementation use
shelve for file storage. See extrequestserver.py for details.
PropertyManagers must provide the methods as described in
propertymanagerinterface
Properties of a resource refers to the attributes of the resource. A property
is referenced by the property name and the property namespace. We usually
refer to the property as {property namespace}property name
Properties of resources as defined in webdav falls under three categories:
- Live properties
These properties are attributes actively maintained by the server, such as
file size, or read permissions. if you are sharing a database record as a
resource, for example, the attributes of the record could become the live
properties of the resource.
The webdav specification defines the following properties that could be
live properties (refer to webdav specification for details):
{DAV:}creationdate
{DAV:}displayname
{DAV:}getcontentlanguage
{DAV:}getcontentlength
{DAV:}getcontenttype
{DAV:}getetag
{DAV:}getlastmodified
{DAV:}resourcetype
{DAV:}source
These properties are implemented by the abstraction layer.
- Locking properties
They refer to the two webdav-defined properties
{DAV:}supportedlock and {DAV:}lockdiscovery
These properties are implemented by the locking library in
pyfileserver.locklibrary and dead properties library in
pyfileserver.propertylibrary
- Dead properties
They refer to arbitrarily assigned properties not actively maintained.
These properties are implemented by the dead properties library in
pyfileserver.propertylibrary
Classes:
class PropertyManager(object)
Misc and Interface methods:
removeProperties(pm, displaypath)
copyProperties(pm, displaypath, destdisplaypath)
writeProperty(pm, resourceAL, mappedpath, displaypath, propns, propname, propupdatemethod, propvalue, reallydoit = True)
getProperty(pm, lm, resourceAL, mappedpath, displaypath, propns, propname)
getApplicablePropertyNames(pm, lm, resourceAL, mappedpath, displaypath)
author note: More documentation here required
This module is specific to the PyFileServer application.
Module: | pyfileserver.fileabstractionlayer |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
This module is specific to the PyFileServer application. It provides two
classes FilesystemAbstractionLayer and ReadOnlyFilesystemAbstractionLayer.
Abstraction Layers must provide the methods as described in
abstractionlayerinterface
See extrequestserver.py for more information about resource abstraction layers in
PyFileServer
Module: | pyfileserver.loadconfig_primitive |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
Loads a python module file returning its module namespace as a dictionary,
except all variables starting with '__' (excluding system and built-in objects).
A compiled module with the filename suffixed with a 'c' may be created as a
byproduct.
If Paste <http://pythonpaste.org> is installed, then paste.pyconfig should be
used as a safer and better variant.
functions:
load(filename)
Module: | pyfileserver.httpdatehelper |
Author: | Ho Chun Wei, fuzzybr80(at)gmail.com |
Project: | PyFileServer, http://pyfilesync.berlios.de/ |
Copyright: | Lesser GNU Public License, see LICENSE file attached with package |
HTTP dates helper - an assorted library of helpful date functions:
- getstrftime(secs) - returns the rfc 1123 date/time format of secs, where secs is the number
of seconds since the epoch. if secs is not given, the current system time is used
- getsecstime(timetypestring) - returns as the number of seconds since the epoch, the date/time
described in timetypestring. Returns None for invalid input
- getgmtime(timetypestring) - returns as a standard time tuple (see time and calendar), the date/time
described in timetypestring. Returns None for invalid input
The following time type strings are supported by getsecstime() and getgmtime():
Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
This section documents in varying details some of the issues waiting for
resolution or to be done.
The application was developed initially as a file-sharing
application and then converted to a more generic resource-sharing
application. Hence most of the functionality is based on what
files would implement.
Need to shift this so that control on what functionality is active
is based on the resource layer. Example, if entity tags are not
implemented, then entity tag functionality (headers, matching)
should be disabled. If {DAV:}getcontentlanguage is implemented in
the resource layer, then the server should start returning
language headers.... etc.
Supporting Gzip Content Encoding normally can be done by middleware - see
GzipMiddleWare <http://www.saddi.com/software/py-lib/>
One buggy issue is supporting Content Encoding AND Content Ranges, which
does not work too well since Content Ranges is applied after Content Encoding,
i.e. you send ranges of the gzipped file and need to know the total length of
the gzip file in advance to decode and send the Range headers. Trying to do it
in a way that does not buffer unnecessarily (memory or disk).
This is really in the domain of the webserver itself to support SSL.
This section describes the problem of concurrent conflicting requests,
as a result of conflicts at the filesystem level:
- Read and Write
Constant GET requests for a file causes it to be file-open locked
for reading all the time. No write operations like PUT, DELETE,
MOVE can be done even if a write LOCK is obtained since the file
remains locked by filesystem level.
Note: some file systems do support deleting a read-open file.
The file is deleted but remains available to the read handle until
it is closed.
- Concurrent Write
- Two concurrent write requests, like MOVE and DELETE, for the same
resource arrives at the server and is processed in separate threads
concurrently. Exact behaviour will depend on the actual resulting
interleaved execution but it is likely that some MOVE files will fail
as they have been DELETEd and vice versa.
Although the operations themself may fail (interpreting partial success on either
side to be failure) a proper response is returned. This does not cause the webserver or
filesystem to crash or enter an inconsistent/unstable state.
Most filesharing operations should not have any need to resolve these issues.
Three solutions have been identified:
- Optimistic Locking
This assumes that most operations go forward successfully. If it does
not due to the filesystem (as evidenced by a 500 Internal Server Error
flagged for an operation), then the entire request should be rollbacked
and a HTTP 409 Conflict error thrown:
successful = []
try:
for item in actions:
successful.append(do_action(item))
except:
for result in successful:
result.rollback()
raise
else:
for result in successful:
result.commit()
The server has to ensure that rollback() and commit() operations do not
fail. Also partial MOVE/COPY operations may be difficult to rollback.
- File Locking
A WRITE request could block until it has obtained all the filesystem level
locks on all the files it should process. It needs to address the following:
- Should the request block indefinitely waiting for the locks or should it
adopt optimistic locking (409 Conflict if it fails to get all the locks
it wants)
- Race conditions or deadlocks between concurrent requests waiting for the
same locks. Locks should be obtained in a specific order to minimize the
possibility of this happening.
- Variable Locking
This is a complex locking mechanism, when requests identified as possibly
conflicting are prevented from being executed concurrently by a blocking
lock. Conflicting requests can be loosely identified as the request URLs
being the same or ancestor/descendant of each other (Depth: infinity).
Such a scheme should address the following:
- Conflicting read operations can be done concurrently but not conflicting
write operations
- Assuming that all requests that are started will complete in finite time, any request
should eventually complete.
Last Generated : Wed, 31 Aug 2005 07:10:19 GMT