package waymaker.top.android; // Copyright © 2015 Michael Allan. Licence MIT.
import java.util.Map;
import waymaker.gen.ThreadSafe;
import waymaker.spec.*;
/** A pollar count at the remote count server.
*/
public final @ThreadSafe class ServerCount
{
/** Asynchronously requests the initial data for a group of peers. The result set will include all
* major peers of the group, if any. Optionally it may be padded with minor peers to a convenient
* size. Subsequent {@linkplain #enqueuePeersRequest(VotingID,PeersReceiver,int,int) range
* requests} may be used to complete the data, as necessary.
*
* @param rootwardID The identity of the common node immediately to the rootward of the
* peers, or null if the peers themselves are roots.
* @param receiver The agent to handle any eventual response from the remote count server;
* normally this will be either the {@linkplain Forest#receivePeersResponse(Object)
* forest}, or an intermediary that delegates to it.
* @param paddedLimit The maximum size of the result set when padded by minor peers, or zero to
* prevent any such padding. The actual size may exceed the paddedLimit when the result set
* comprises major peers alone, in which case the absolute size limit is determined by the
* count engine’s definition of ‘major’ versus ‘minor’.
*
* @throws IllegalArgumentException if paddedLimit is less than zero.
*
* @see ‘peer’
*/
public void enqueuePeersRequest( final VotingID rootwardID, final PeersReceiver receiver,
final int paddedLimit )
{
if( paddedLimit < 0 ) throw new IllegalArgumentException();
receiver.receivePeersResponse( rootwardID );
// sending an immediate default response in lieu of a real response from the remote server
}
/* * *
- count server may implement by querying for all peers of ordinal <= paddedLimit
- then calculate from result count the highest ordinal to return,
and immediately stream the response by filtering out any higher ones
- major/minor distinction in count engine
- purpose is to enable efficient paging together with a rough sorting
- initial page contains all major peers
- client can present these in sorted order as desired
- subsequent pages contain only minor, relatively uninteresting peers
- no matter then if client presents page boundaries to user for paging convenience,
rather than attempt a total sorting of all peers across all pages
- maintenance
- calculate threshold as gFlow/128 (integer)
- where gFlow is total flow of peer group
( for voter group, inflow of candidate
( for root group, total inflow of roots, viz. turnout
( not using ground flow registers to calculate turnout, notebook 2015.9.30
- major node has inflow > threshold
- as threshold changes it should be easy to isolate range of nodes affected by change
and adjust their peer ordinals accordingly
*/
/** Asynchronously requests the data for a range of minor peers. The order of peers in the result
* set is undefined.
*
* @param rootwardID The identity of the node immediately to the rootward, or null if the
* peers themselves are roots.
* @param receiver The agent to handle any eventual response from the remote count server; normally
* this will be either the {@linkplain Forest#receivePeersResponse(Object) forest}, or an
* intermediary that delegates to it.
* @param peersStart The start ordinal of the range, inclusive.
* @param peersEndBound The end ordinal of the range, exclusive.
*
* @throws IndexOutOfBoundsException if pStart is less than 1 or greater than pEndBound.
*/
public void enqueuePeersRequest( VotingID rootwardID, PeersReceiver receiver,
int peersStart, int peersEndBound )
{
if( peersStart < 1 || peersStart > peersEndBound ) throw new IndexOutOfBoundsException();
// WaykitUI.setRemotelyUsable();
/// when this is coded
throw new UnsupportedOperationException( "Server counts not yet coded" );
}
/* * *
- maintenance of ordinals for minor peers in count engine
- kept unique and contiguous with minimal effort
- deletion of minor accomplished by swapping in final minor
- requires tracking highest ordinal
( stored in candidate node for voters | in poll-wide store for roots
- an upper limit (< Integer.MAX_VALUE) is imposed
- thence all remaining peers share same ordinal
( not worth using long values here when the only purpose is paging in UI
*/
/** Synchronously connects to the remote count server and returns from the latest count the identified
* node complete with its {@linkplain CountNode#rootwardInThis() candidates}, constructing those too as
* necessary; or returns null if the node is uncounted there.
*
* @see CountNode#id()
* @param nodeMap A map of nodes keyed by identity tag. Any candidate in the map is reused
* rather than constructed anew, while all newly constructed candidates are added to the map.
*
* @throws AssertionError if assertions are enabled and nodeMap already keys the given tag.
*/
public UnadjustedNode fetchNode( final VotingID id, final Map nodeMap )
{
assert !nodeMap.containsKey(id): "Not fetching an already fetched node";
return null; // server counts not yet coded
// will also have to detect and throw exception on serial inconsitency (RepocastSer)
}
/** Answers whether the given string is a well formed poll name, that is a well formed rep
* {@linkplain ID#isSerialForm(String) serial number}.
*/
public static boolean isPollNameForm( final String string ) { return ID.isSerialForm( string ); }
}