diff options
Diffstat (limited to 'certmaster/forkbomb.py')
-rw-r--r-- | certmaster/forkbomb.py | 153 |
1 files changed, 0 insertions, 153 deletions
diff --git a/certmaster/forkbomb.py b/certmaster/forkbomb.py deleted file mode 100644 index 3dfa6f2..0000000 --- a/certmaster/forkbomb.py +++ /dev/null @@ -1,153 +0,0 @@ -# forkbomb is a module that partitions arbitrary workloads -# among N seperate forks, for a configurable N, and -# collates results upon return, as if it never forked. -# -# Copyright 2007, Red Hat, Inc -# Michael DeHaan <mdehaan@redhat.com> -# -# This software may be freely redistributed under the terms of the GNU -# general public license. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -import os -import random # for testing only -import time # for testing only -import shelve -import bsddb -import sys -import tempfile -import fcntl -import utils -import xmlrpclib - -DEFAULT_FORKS = 4 -DEFAULT_CACHE_DIR = "/var/lib/func" - -def __get_storage(dir): - """ - Return a tempfile we can use for storing data. - """ - dir = os.path.expanduser(dir) - if not os.path.exists(dir): - os.makedirs(dir) - return tempfile.mktemp(suffix='', prefix='asynctmp', dir=dir) - -def __access_buckets(filename,clear,new_key=None,new_value=None): - """ - Access data in forkbomb cache, potentially clearing or - modifying it as required. - """ - - internal_db = bsddb.btopen(filename, 'c', 0644 ) - handle = open(filename,"r") - fcntl.flock(handle.fileno(), fcntl.LOCK_EX) - storage = shelve.BsdDbShelf(internal_db) - - if clear: - storage.clear() - storage.close() - fcntl.flock(handle.fileno(), fcntl.LOCK_UN) - return {} - - if not storage.has_key("data"): - storage["data"] = {} - else: - pass - - if new_key is not None: - # bsdb is a bit weird about this - newish = storage["data"].copy() - newish[new_key] = new_value - storage["data"] = newish - - rc = storage["data"].copy() - storage.close() - fcntl.flock(handle.fileno(), fcntl.LOCK_UN) - - return rc - -def __bucketize(pool, slots): - """ - Given a pre-existing list of X number of tasks, partition - them into a hash of Y number of slots. - """ - buckets = {} - count = 0 - for key in pool: - count = count + 1 - slot = count % slots - if not buckets.has_key(slot): - buckets[slot] = [] - buckets[slot].append(key) - return buckets - -def __with_my_bucket(bucket_number,buckets,what_to_do,filename): - """ - Process all tasks assigned to a given fork, and save - them in the shelf. - """ - things_in_my_bucket = buckets[bucket_number] - results = {} - for thing in things_in_my_bucket: - (nkey,nvalue) = what_to_do(bucket_number,buckets,thing) - __access_buckets(filename,False,nkey,nvalue) - -def __forkbomb(mybucket,buckets,what_to_do,filename): - """ - Recursive function to spawn of a lot of worker forks. - """ - nbuckets = len(buckets) - pid = os.fork() - if pid != 0: - if mybucket < (nbuckets-1): - __forkbomb(mybucket+1,buckets,what_to_do,filename) - try: - os.waitpid(pid,0) - except OSError, ose: - if ose.errno == 10: - pass - else: - raise ose - else: - __with_my_bucket(mybucket,buckets,what_to_do,filename) - sys.exit(0) - -def __demo(bucket_number, buckets, my_item): - """ - This is a demo handler for test purposes. - It just multiplies all numbers by 1000, but slowly. - """ - # print ">> I am fork (%s) and I am processing item (%s)" % (bucket_number, my_item) - # just to verify forks are not sequential - sleep = random.randrange(0,4) - time.sleep(sleep) - return (my_item, my_item * 1000) - -def batch_run(pool,callback,nforks=DEFAULT_FORKS,cachedir=DEFAULT_CACHE_DIR): - """ - Given an array of items (pool), call callback in each one, but divide - the workload over nfork forks. Temporary files used during the - operation will be created in cachedir and subsequently deleted. - """ - if nforks <= 1: - # modulus voodoo gets crazy otherwise and bad things happen - nforks = 2 - shelf_file = __get_storage(cachedir) - __access_buckets(shelf_file,True,None) - buckets = __bucketize(pool, nforks) - __forkbomb(1,buckets,callback,shelf_file) - rc = __access_buckets(shelf_file,False,None) - os.remove(shelf_file) - return rc - -def __test(nforks=4,sample_size=20): - pool = xrange(0,sample_size) - print batch_run(pool,__demo,nforks=nforks) - -if __name__ == "__main__": - __test() - - |