Phoenix 180

First revision for review.  There are some open points here.  Still no test case added to consume the stats.  Will do the performance test once the system is available with me.
Good point. The best way to ensure other clients will re-read the metadata from the server is to update a timestamp on a Cell in the row. Jeffrey made a change like this to "force" clients to do this by doing a Put of the empty key value. See MetaDataEndPointImpl.updateIndexState() line 1538:

                    if(dataTableKey != null) {
                        // make a copy of tableMetadata
                        tableMetadata = new ArrayList<Mutation>(tableMetadata);
                        // insert an empty KV to trigger time stamp update on data table row
                        Put p = new Put(dataTableKey);
                        p.add(TABLE_FAMILY_BYTES, QueryConstants.EMPTY_COLUMN_BYTES, timeStamp, ByteUtil.EMPTY_BYTE_ARRAY);
                        tableMetadata.add(p);
                    }

How about having your invalidate method do that instead? In this case, the client makes a getTable() call in MetaDataClient.updateCache() and the new PTable is sent across (which would include the stats).