<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On 11 Jan 2011, at 16:16, Vladimir Blagojevic wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>On 11-01-11 12:27 PM, Manik Surtani wrote:<br><blockquote type="cite">You can do that but, even as the paper suggests, you usually end up with just 1 result. &nbsp;Essentially it is a case of how simple we want to make the API. &nbsp;I think for a large number of the use cases we've come across, mapping a K and V to a single T works fine (this is a simple value mapping you see in many functional languages). &nbsp;The alternative is to map an entire tuple (e.g., k1, v1 becomes k2, v2) but as Java doesn't support multiple return values, so then you end up with Mapper.map() returning a tuple (Map.Entry&lt;K2, V2&gt; &nbsp;in Java) which I find clunky.<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">Perhaps, if there is adequate demand, we could extend Mapper with TupleMapper, which would support this.<br></blockquote><blockquote type="cite"><br></blockquote><br>Ok noted, but I still need a clarification about your proposal:<br><br>Reducer&lt;T, R&gt; &nbsp;{<br><span class="Apple-tab-span" style="white-space:pre">        </span>// incrementally reduces a transformed entry. &nbsp;Called once for each T produced by the mapper.<br><span class="Apple-tab-span" style="white-space:pre">        </span>// previously reduced value passed in each time.<br><span class="Apple-tab-span" style="white-space:pre">        </span>R reduce(T, R);<br>}<br><br>Collator&lt;R&gt; &nbsp;{<br><span class="Apple-tab-span" style="white-space:pre">        </span>// Adds reduced results from remote nodes. &nbsp;Called once for each R returned by a RemoteReducer.<br><span class="Apple-tab-span" style="white-space:pre">        </span>add(Address origin, R remote);<br><br><span class="Apple-tab-span" style="white-space:pre">        </span>// collates all results added so far.<br><span class="Apple-tab-span" style="white-space:pre">        </span>R collate();<br>}<br><br>So far I understand that we invoke reduce (T) for each returned T map(K,V) invocation. Now, where is this previously reduced R parameter coming from? Are you invoking reduce phase serially across a list of all returned results of T map(K,V) passing R from last invocation of reduce in a new invocation of reduce?<br></div></blockquote><div><br></div><div>How about this pseudocode:</div><div><br></div><div>On each node:</div><div>&nbsp;&nbsp; mapped = list()</div><div>&nbsp;&nbsp; for entry in cache.entries:</div><div>&nbsp;&nbsp; &nbsp; &nbsp;t = mapper.map(entry.key, entry.value)</div><div>&nbsp;&nbsp; &nbsp; &nbsp;mapped.add(t)</div><div><br></div><div>&nbsp;&nbsp; r = null</div><div>&nbsp;&nbsp; for t in mapped:</div><div>&nbsp;&nbsp; &nbsp; &nbsp;r = reducer.reduce(t, r)</div><div><br></div><div>&nbsp;&nbsp; return r to calling node</div><div><br></div><div>On calling node:</div><div>&nbsp;&nbsp; reduced_results = invoke map reduce task on all nodes, retrieve map{address: result}</div><div>&nbsp;&nbsp; for r in reduced_results.entries:</div><div>&nbsp;&nbsp; &nbsp; &nbsp;remote_address = r.key</div><div>&nbsp;&nbsp; &nbsp; &nbsp;remote_reduced_result = r.value</div><div>&nbsp;&nbsp; &nbsp; &nbsp;collator.add(remote_address, remote_reduced_result)</div><div><br></div><div>&nbsp;&nbsp; return collator.collate()</div><div>&nbsp;&nbsp;&nbsp;</div><div><br></div><blockquote type="cite"><div><span class="Apple-style-span" style="color: rgb(84, 0, 0); ">* Similarly, Collator.add() should just need the address and the</span><br><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">reduced result from each node (each node would only produce 1 result!)<br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">DistExec<br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">* Why do you have execute() and executeAsync() with no params? &nbsp;What<br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">do these methods do?<br></blockquote></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">In case user provided Factory for DistributedCallable. We have to handle<br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">cases where simple no parameter constructor for callables is not<br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">sufficient - hence factory.<br></blockquote></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">Why are we constructing DistributedCallables? &nbsp;Surely the user passes in an instance?<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Ok, so we need to serialize/migrate across JVMs this instance of<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">DistributedCallable and invoke it on a target Infinispan node, right? If<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">so, then we need to add K...input as a parameter to call function since<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">each migrated instance (on execution node) needs to have different input<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">for invocation.<br></blockquote></blockquote><blockquote type="cite">Yeah good point. &nbsp;My bad. &nbsp;:) &nbsp;We'd need to document this appropriately in the DistributedCallable javadocs.<br></blockquote><blockquote type="cite"><br></blockquote><br>:-) What is more elegant and accommodating for interface implementers - <br>passing parameter K to call of DistributedCallable or using factories <br>for DistributedCallable?<br></div></blockquote><div><br></div><div>Hmm. &nbsp;I think both approaches are best, to allow for the most flexibility. &nbsp;So perhaps overload execute() with the following:</div><div><br></div><div>execute(DistributedCallable c); // Javadoc says DistributedCallable must have a no arg ctor</div><div>execute(DistributedCallableFactory cf); &nbsp;// Javadoc says DistributedCallable must have a no arg ctor</div><div>execute(Class&lt;? extends DistributedCallable&gt; cc);&nbsp;</div><div>execute(Class&lt;? extends DistributedCallableFactory&gt; cfc);&nbsp;</div><div><div><br></div><div>Also, wrt. names and methods on the API on the Distributed Exec part of things, wdyt about aligning it with JDK executors (see separate email from me)?</div><div><br></div><div>And - not trying to confuse you, promise! &nbsp;- here's some scope for additional work later on as well: network classloaders to deal with non-homogenous deployments with remote tasks like these. &nbsp;;)</div><div><br></div><div>Cheers</div><div>Manik</div></div><br><blockquote type="cite"><div><br>Cheers,<br>Vladimir<br>_______________________________________________<br>infinispan-dev mailing list<br><a href="mailto:infinispan-dev@lists.jboss.org">infinispan-dev@lists.jboss.org</a><br>https://lists.jboss.org/mailman/listinfo/infinispan-dev<br></div></blockquote></div><br><div>
<span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; font-size: medium; "><div><div>--</div><div>Manik Surtani</div><div><a href="mailto:manik@jboss.org">manik@jboss.org</a></div><div><a href="http://twitter.com/maniksurtani">twitter.com/maniksurtani</a></div><div><br></div><div>Lead, Infinispan</div><div><a href="http://www.infinispan.org">http://www.infinispan.org</a></div><div><br></div></div></span><br class="Apple-interchange-newline">
</div>
<br></body></html>