Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Feb 18th, 2006, 3:25 PM   #1
Sane
Banned
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,101
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
CherryPy Multiple Threads

My problem now is that CherryPy can only handle one request at a time.

This is a VERY BIG problem. If someone is downloading a 100kb picture on dial-up, it can take so long that CherryPy times out.

I've tried making a program that detects if CherryPy has timed out, but it can't because it will never even return a signal saying it has timed out when you access the page.

I've been needing to reboot my server up to three times a day just because of the large amount of people accessing my site at the same time.

I've searched the documentation for possibly a time-out if a response takes too long, couldn't find anything. But even if I could, people's downloads would cancel.

The best answer would be a way to multi-thread using CherryPy. And I'm not ready to convert a 200kb script from CherryPy to Apache.
Sane is offline   Reply With Quote
Old Feb 18th, 2006, 4:52 PM   #2
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
What about setting the "server.threadPool" option under "[Global]" in the configuration file to, say, 10 or 20? That should get CherryPy using threads.
Arevos is offline   Reply With Quote
Old Feb 18th, 2006, 5:59 PM   #3
Sane
Banned
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,101
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
Okay, wow. I'm not going to test it yet. First I will need a way to synchronize the data files so one doesn't write while the other is reading, etc...

Errm... so how is that possible? @_@
Sane is offline   Reply With Quote
Old Feb 18th, 2006, 8:22 PM   #4
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Well, the first solution that springs to mind is to create a lock file, but since only your cherrypy server is supposed to be accessing these files, I suspect you could get away with a Lock object.

import threading
import cherrypy
import datetime

lock = threading.Lock()

class HelloWorld:
    @cherrypy.expose
    def index(self):
        lock.acquire()
        file = open("test.txt", "a")
        file.write(str(datetime.datetime.now()) + "\n")
        file.close()
        lock.release()

cherrypy.root = HelloWorld()
cherrypy.server.start()
Lock objects prevent more than one thread accessing a section of code. When a Python thread comes to lock.acquire(), and the lock has not be released, then that thread will wait until the lock becomes available.
Arevos is offline   Reply With Quote
Old Feb 18th, 2006, 8:47 PM   #5
Sane
Banned
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,101
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
That is seriously the coolest thing I've ever seen. @_@

lock.acquire() / lock.release() .... *drools*


Thanks man. ^_^

Quote:
Originally Posted by vBulletin Message
You must spread some Reputation around before giving it to Arevos again.
:mad: lol


Just curious though. If one section of code is locked using lock.acquire, can a completely different section containing lock.acquire be accessed? Or is it smart enough to map the code blocks to seperate instances?

Oh... but how would I make it so code that's writing to a file in a certain place won't be doing it at the same time it's being written. Or should I not worry about synchronizing something that's just reading? But even so I have more then two different pages that will write to the same file.

Last edited by Sane; Feb 18th, 2006 at 9:06 PM.
Sane is offline   Reply With Quote
Old Feb 19th, 2006, 10:48 AM   #6
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by Sane
Just curious though. If one section of code is locked using lock.acquire, can a completely different section containing lock.acquire be accessed? Or is it smart enough to map the code blocks to seperate instances?
You'd need two separate locks. A Lock object can be acquired or released. When a lock is acquired by a thread, any other thread trying to then acquire the lock will wait until that particular lock is released.

Quote:
Originally Posted by Sane
Oh... but how would I make it so code that's writing to a file in a certain place won't be doing it at the same time it's being written. Or should I not worry about synchronizing something that's just reading? But even so I have more then two different pages that will write to the same file.
I've been wrestling with this problem for a while, and I haven't been able to as yet, get a very satisfactory solution.

The pseudocode of what needs to be done is:
1. A file can be written if not being already read or written.
2. A file can be read if not already being written.

My first thoughts were that you need a lock for each file. A cache seems the best option. Luckily I never leave home without my automated cache maker function:
def cached(func):
    """Creates a cached function.
    Cached function cannot handle keyword or mutable arguments."""
    store = {}
    def cached_func(*args):
        if not store.has_key(args):
            store[args] = func(*args)
        return store[args]
    return cached_func
Using the cached function, I can construct a function that will return a Lock object unique to a filename:
import threading

@cached
def FileLock(key):
    return threading.Lock()
Then my mind wandered onto Semaphores, and then to reverse Semaphores:
class ReverseSemaphore:
    def __init__(self):
    self.__cond  = threading.Condition(threading.Lock())
        self.__value = 0

    def acquire(self, blocking = True):
        is_blocked = False
        self.__cond.acquire()
        while self.__value > 0:
            if not blocking:
                break
            self.__cond.wait()
        else:
            self.__value += 1
            is_blocked = True
            self.__cond.release()
            return is_blocked
	
    def release(self):
        self.__cond.acquire()
        self.__value -= 1
        self.__cond.notify()
        self.__cond.release()
This provides a solution to blocking write-access to a file when it's being read. Now I need to create a Lock class that allows blocking without acquiring - which is getting too complicated for my liking.

There has to be a simpler solution. I'll update this thread when I have anything more.
Arevos is offline   Reply With Quote
Old Feb 19th, 2006, 11:11 AM   #7
Jessehk
The Oblivious One
 
Jessehk's Avatar
 
Join Date: May 2005
Location: Ontario, Canada
Posts: 648
Rep Power: 4 Jessehk is on a distinguished road
Quote:
You must spread some Reputation around before giving it to Arevos again.
That's the same message I got (and with Grumpy, and DaWei, and etc...). :p
__________________
Dr. Zoidberg: [ecstatic] I'm going to a movie... with FRIENDS!
Jessehk is offline   Reply With Quote
Old Feb 19th, 2006, 11:23 AM   #8
Polyphemus_
Expert Programmer
 
Polyphemus_'s Avatar
 
Join Date: Aug 2005
Location: Rotterdam, the Netherlands
Posts: 942
Rep Power: 4 Polyphemus_ is on a distinguished road
Quote:
Originally Posted by Jessehk
That's the same message I got (and with Grumpy, and DaWei, and etc...). :p
Just give some disrep points to inactive users
Polyphemus_ is offline   Reply With Quote
Old Feb 19th, 2006, 11:23 AM   #9
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Currently trying to fix this Python cookbook recipe. The author has the right idea, but as the comment points out, the code will lock up under some circumstances. Namely, if the program tries to acquire a write-lock before all the read-locks have been released.
Arevos is offline   Reply With Quote
Old Feb 19th, 2006, 12:27 PM   #10
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by Arevos
The author has the right idea, but as the comment points out, the code will lock up under some circumstances. Namely, if the program tries to acquire a write-lock before all the read-locks have been released.
Ahh! I spoke too soon! Looks like the author knows more than I do! I assumed that the wait() method of Condition objects operated much the same as the wait() method on threads. I was wrong, since re-reading the documentation reveals that Condition.wait() gives up it's acquired lock until notified, at which point it attempts to reacquire it.

Combining the ReadWriteLock class with a cache:
@cached
def FileReadWriteLock(filename):
    return ReadWriteLock()

lock = FileReadWriteLock("test.txt")

lock.acquire_write()
file = open("test.txt", "w")
file.write("Hello world\n")
file.close()
lock.release_write()

lock.acquire_read()
file = open("test.txt", "r")
print file.readline()
file.close()
lock.release_read()
And that should work.
Arevos is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 12:26 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC