[Zope-dev] Zope container objects can't multitask; Z2 CONFLICT mis-reported

gtk gtk@well.com
Sun, 31 Oct 1999 22:52:27 +1100


Zope container objects can't multitask. If you try and add more than one
item to a folder at a time -- even if they have different ids -- a Z2
CONFLICT error occurs. To add insult to injury, the error message sent to
the user seems to be almost random. I've seen both of these:

    Missing doc string at: http://BEETLEJUICE:8080/folder1
    The parameter, <em>id</em>, was omitted from the request.

To reproduce the problem, create a folder named /folder1 on your server and
run the following code (don't forget to edit the defaults!):

# test Zope's ability to add more than one item to a folder simultaneously

import httplib, sys, time, urllib, base64, thread, string

__defaultServer = '127.0.0.1'
__defaultPath = '/folder1'
__defaultPort = 8080
__defaultUsername = 'zopeadmin'
__defaultPassword = '<your password>'

def httpPOST(dict, server, port, path, username, password):
    """I blame section 4.61 of the Python FAQ."""

    postings = []
    for key in dict.keys():
        postings.append('%s=%s' % (key, urllib.quote(dict[key])))

    qs = string.join(postings, '&')
    userpass = '%s:%s' % (username, password)

    httpobj = httplib.HTTP(server, port)
    httpobj.putrequest('POST', path)
    httpobj.putheader('Accept', '*/*')
    httpobj.putheader('Connection', 'Keep-Alive')
    httpobj.putheader('Content-type', 'application/x-www-form-urlencoded')
    httpobj.putheader('Content-length', '%d' % len(qs))
    httpobj.putheader('Authorization', 'Basic %s' %
base64.encodestring(userpass))
    httpobj.endheaders()
    httpobj.send(qs)

    reply, msg, headers = httpobj.getreply()
    return reply, msg, headers, httpobj.getfile().read()

def createDTMLDocument(
        id,
        title='',
        server=__defaultServer,
        port=__defaultPort,
        path=__defaultPath,
        username=__defaultUsername,
        password=__defaultPassword
        ):
    """Create a DTML document"""

    dict = { 'id': id, 'title': title }
    return httpPOST(dict, server, port, path +
'/manage_addProduct/OFSP/addDTMLDocument', username, password)

def Test(numDocs):
    for intId in range(numDocs):
        ident = thread.get_ident()
        id = '%d.%d' % (intId, ident)
        title = 'concurrency'

        print 'creating document %s' % id
        reply, msg, headers, body = createDTMLDocument(id, title)

        if reply != 302: # I'm expecting a redirect
            print 'reply status:', reply
            print headers
            print body

def MultiThreadedTest(numThreads, numDocs):
    for threadnum in range(numThreads):
        thread.start_new_thread(Test, (numDocs,) )

# Test(5)
MultiThreadedTest(3,3)

Regards,
Garth.

--
<gtk@well.com>