Implementation of Range Splitting

Using the new range stat counters, range splitting can now be
evaluated after each write, according to the range max bytes value
in the zone config.

Removed previous InternalSplitRange method in favor of a new
AdminSplit method, the first of a new class of methods which do not
go through Raft, but still need to run at a particular range. Because
it doesn't go through Raft, it is not allowed to modify the underlying
state machine directly. Instead, it effects the split via a distributed
transaction which modifies the meta addressing records as well as the
updated & new range descriptors. In order to allow the range descriptors
to be modified in a transaction, they're now being written as MVCC values.

The busy work of bookkeeping due to the split includes copying the
entries in the original range's response cache and recomputing stats
for the two derivative ranges. This is done in a "split trigger". This
is available as an option in a new method, InternalEndTxn. I chose to
make this new method (and duplicate some code) because I intent the
api.proto protocol buffer interface to be public, and wanted to separate
all node-only, internal methods into internal.proto.

In order to write the RangeDescriptor as part of a distributed txn,
the range descriptor had to be exactly the same for each replica. This
method that the previous use of RangeMetadata, containing a range ID
and redundant cluster ID had no purpose and I decided to remove it to
avoid confusion. So RangeMetadata is gone, and I've changed all of the
code to refer to RangeDescriptor only. The range ID is determined by
looking at the replicas and finding the one matching the current store.

At startup, the store scans all range metadata using a new MVCC method
which iterates only over the committed entries and skips all pending
write intents.
Yes, you're right. Changed.

On Mon, Oct 20, 2014 at 3:26 PM, Ben Darnell <notifications@github.com>
wrote:

> In kv/split_test.go:
>
> > +					EndKey: engine.KeyMetaMax,
> > +				},
> > +			})
> > +			if scanR.GoError() != nil {
> > +				return scanR.GoError()
> > +			}
> > +			kvs = scanR.Rows
> > +			return nil
> > +		}); err != nil {
> > +			t.Fatalf("failed to scan meta1 keys: %s", err)
> > +		}
> > +		return len(kvs) >= 5
> > +	}, 500*time.Millisecond); err != nil {
> > +		t.Errorf("failed to split 5 times: %s", err)
> > +	}
> > +	close(done)
>
> I think you always need to wait on a WaitGroup after closing the channel.
> Otherwise the write task might be busy and have the database closed out
> from under it when the deferred db.Close fires.
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/cockroachdb/cockroach/pull/134/files#r19107324>.
>