get genpoi multiprocessing working on windows
This commit is contained in:
@@ -32,7 +32,6 @@ from optparse import OptionParser
|
|||||||
from overviewer_core import logger
|
from overviewer_core import logger
|
||||||
from overviewer_core import nbt
|
from overviewer_core import nbt
|
||||||
from overviewer_core import configParser, world
|
from overviewer_core import configParser, world
|
||||||
from overviewer_core import rendermodes
|
|
||||||
|
|
||||||
UUID_LOOKUP_URL = 'https://sessionserver.mojang.com/session/minecraft/profile/'
|
UUID_LOOKUP_URL = 'https://sessionserver.mojang.com/session/minecraft/profile/'
|
||||||
|
|
||||||
@@ -85,11 +84,27 @@ def jsonText(s):
|
|||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
# Since functions are not pickleable, we send their names instead.
|
||||||
|
# Here, set up worker processes to have a name -> function map
|
||||||
|
bucketChunkFuncs = {}
|
||||||
|
def initBucketChunks(config_path):
|
||||||
|
global bucketChunkFuncs
|
||||||
|
|
||||||
|
mw_parser = configParser.MultiWorldParser()
|
||||||
|
mw_parser.parse(config_path)
|
||||||
|
# ought not to fail since we already did it once
|
||||||
|
config = mw_parser.get_validated_config()
|
||||||
|
for name, render in config['renders'].iteritems():
|
||||||
|
for f in render['markers']:
|
||||||
|
ff = f['filterFunction']
|
||||||
|
bucketChunkFuncs[ff.__name__] == ff
|
||||||
|
|
||||||
# yes there's a double parenthesis here
|
# yes there's a double parenthesis here
|
||||||
# see below for when this is called, and why we do this
|
# see below for when this is called, and why we do this
|
||||||
# a smarter way would be functools.partial, but that's broken on python 2.6
|
# a smarter way would be functools.partial, but that's broken on python 2.6
|
||||||
# when used with multiprocessing
|
# when used with multiprocessing
|
||||||
def parseBucketChunks((bucket, rset, filters)):
|
def parseBucketChunks((bucket, rset, filters)):
|
||||||
|
global bucketChunkFuncs
|
||||||
pid = multiprocessing.current_process().pid
|
pid = multiprocessing.current_process().pid
|
||||||
markers = defaultdict(list)
|
markers = defaultdict(list)
|
||||||
|
|
||||||
@@ -102,7 +117,8 @@ def parseBucketChunks((bucket, rset, filters)):
|
|||||||
if poi['id'] == 'Sign':
|
if poi['id'] == 'Sign':
|
||||||
poi = signWrangler(poi)
|
poi = signWrangler(poi)
|
||||||
for name, filter_function in filters:
|
for name, filter_function in filters:
|
||||||
result = filter_function(poi)
|
ff = bucketChunkFuncs[filter_function]
|
||||||
|
result = ff(poi)
|
||||||
if result:
|
if result:
|
||||||
d = create_marker_from_filter_result(poi, result)
|
d = create_marker_from_filter_result(poi, result)
|
||||||
markers[name].append(d)
|
markers[name].append(d)
|
||||||
@@ -127,7 +143,7 @@ def signWrangler(poi):
|
|||||||
return poi
|
return poi
|
||||||
|
|
||||||
|
|
||||||
def handleEntities(rset, config, filters, markers):
|
def handleEntities(rset, config, config_path, filters, markers):
|
||||||
"""
|
"""
|
||||||
Add markers for Entities or TileEntities.
|
Add markers for Entities or TileEntities.
|
||||||
|
|
||||||
@@ -169,10 +185,10 @@ def handleEntities(rset, config, filters, markers):
|
|||||||
logging.info("Buckets has %d entries", len(b));
|
logging.info("Buckets has %d entries", len(b));
|
||||||
|
|
||||||
# Create a pool of processes and run all the functions
|
# Create a pool of processes and run all the functions
|
||||||
pool = Pool(processes=numbuckets)
|
pool = Pool(processes=numbuckets, initializer=initBucketChunks, initargs=(config_path,))
|
||||||
|
|
||||||
# simplify the filters dict, so pickle doesn't have to do so much
|
# simplify the filters dict, so pickle doesn't have to do so much
|
||||||
filters = [(name, filter_function) for name, __, filter_function, __, __, __ in filters]
|
filters = [(name, filter_function.__name__) for name, __, filter_function, __, __, __ in filters]
|
||||||
|
|
||||||
results = pool.map(parseBucketChunks, ((buck, rset, filters) for buck in buckets))
|
results = pool.map(parseBucketChunks, ((buck, rset, filters) for buck in buckets))
|
||||||
|
|
||||||
@@ -452,17 +468,6 @@ def main():
|
|||||||
# internal identifier for this filter
|
# internal identifier for this filter
|
||||||
name = replaceBads(f['name']) + hex(hash(f['filterFunction']))[-4:] + "_" + hex(hash(rset))[-4:]
|
name = replaceBads(f['name']) + hex(hash(f['filterFunction']))[-4:] + "_" + hex(hash(rset))[-4:]
|
||||||
|
|
||||||
# we need to make the function pickleable for multiprocessing to
|
|
||||||
# work
|
|
||||||
# We set a custom prefix here to not override any functions there.
|
|
||||||
# These functions are only pickleable if they are bound to a
|
|
||||||
# module. Since rendermodes imports the config, they are bound to
|
|
||||||
# it anyway, but don't end up importable as
|
|
||||||
# `rendermodes.filter_fn`. That's why we set it here explicitly on
|
|
||||||
# the module.
|
|
||||||
f['filterFunction'].__name__ = "custom_filter_" + f['filterFunction'].__name__
|
|
||||||
setattr(rendermodes, f['filterFunction'].__name__, f['filterFunction'])
|
|
||||||
|
|
||||||
# add it to the list of filters
|
# add it to the list of filters
|
||||||
filters.add((name, f['name'], f['filterFunction'], rset, worldpath, rname))
|
filters.add((name, f['name'], f['filterFunction'], rset, worldpath, rname))
|
||||||
|
|
||||||
@@ -484,7 +489,7 @@ def main():
|
|||||||
keyfunc = lambda x: x[3]
|
keyfunc = lambda x: x[3]
|
||||||
sfilters = sorted(filters, key=keyfunc)
|
sfilters = sorted(filters, key=keyfunc)
|
||||||
for rset, rset_filters in itertools.groupby(sfilters, keyfunc):
|
for rset, rset_filters in itertools.groupby(sfilters, keyfunc):
|
||||||
handleEntities(rset, config, rset_filters, markers)
|
handleEntities(rset, config, options.config, rset_filters, markers)
|
||||||
|
|
||||||
# apply filters to players
|
# apply filters to players
|
||||||
if not options.skipplayers:
|
if not options.skipplayers:
|
||||||
|
|||||||
Reference in New Issue
Block a user