func (k *kvChangeIndex) retrieveCBGTPartitions() (partitionDef base.PartitionStorageSet, err error) {

	var manager *cbgt.Manager
	if k.context != nil {
		manager = k.context.BucketSpec.CbgtContext.Manager
	} else {
		return nil, errors.New("Unable to retrieve CBGT partitions - no database context")
	}

	if manager == nil {
		return nil, errors.New("Unable to retrieve CBGT partitions - no CBGT manager")
	}

	_, planPIndexesByName, _ := manager.GetPlanPIndexes(true)
	indexName := k.context.GetCBGTIndexNameForBucket(k.context.Bucket)
	pindexes := planPIndexesByName[indexName]

	for _, pIndex := range pindexes {
		vbStrings := strings.Split(pIndex.SourcePartitions, ",")
		// convert string vbNos to uint16
		vbNos := make([]uint16, len(vbStrings))
		for i := 0; i < len(vbStrings); i++ {
			vbNumber, err := strconv.ParseUint(vbStrings[i], 10, 16)
			if err != nil {
				base.LogFatal("Error creating index partition definition - unable to parse vbucket number %s as integer:%v", vbStrings[i], err)
			}
			vbNos[i] = uint16(vbNumber)
		}
		entry := base.PartitionStorage{
			Index: uint16(0), // see below for index assignment
			Uuid:  pIndex.UUID,
			VbNos: vbNos,
		}
		partitionDef = append(partitionDef, entry)
	}

	// NOTE: the ordering of pindexes returned by manager.GetPlanPIndexes isn't fixed (it's doing a map iteration somewhere).
	//    The mapping from UUID to VbNos will always be consistent.  Sorting by UUID to maintain a consistent index ordering,
	// then assigning index values.
	partitionDef.Sort()
	for i := 0; i < len(partitionDef); i++ {
		partitionDef[i].Index = uint16(i)
	}
	return partitionDef, nil
}
func (k *kvChangeIndex) initIndexPartitions() (*base.IndexPartitions, error) {

	k.indexPartitionsLock.Lock()
	defer k.indexPartitionsLock.Unlock()

	// Check if it's been initialized while we waited for the lock
	if k.indexPartitions != nil {
		return k.indexPartitions, nil
	}

	var partitionDef []base.PartitionStorage
	// First attempt to load from the bucket
	value, _, err := k.reader.indexReadBucket.GetRaw(base.KIndexPartitionKey)
	indexExpvars.Add("get_indexPartitionMap", 1)
	if err == nil {
		if err = json.Unmarshal(value, &partitionDef); err != nil {
			return nil, err
		}
	}

	// If unable to load from index bucket - attempt to initialize based on cbgt partitions
	if partitionDef == nil {
		var manager *cbgt.Manager
		if k.context != nil {
			manager = k.context.BucketSpec.CbgtContext.Manager
		} else {
			return nil, errors.New("Unable to determine partition map for index - not found in index, and no database context")
		}

		if manager == nil {
			return nil, errors.New("Unable to determine partition map for index - not found in index, and no CBGT manager")
		}

		_, planPIndexesByName, _ := manager.GetPlanPIndexes(true)
		indexName := k.context.GetCBGTIndexNameForBucket(k.context.Bucket)
		pindexes := planPIndexesByName[indexName]

		for index, pIndex := range pindexes {
			vbStrings := strings.Split(pIndex.SourcePartitions, ",")
			// convert string vbNos to uint16
			vbNos := make([]uint16, len(vbStrings))
			for i := 0; i < len(vbStrings); i++ {
				vbNumber, err := strconv.ParseUint(vbStrings[i], 10, 16)
				if err != nil {
					base.LogFatal("Error creating index partition definition - unable to parse vbucket number %s as integer:%v", vbStrings[i], err)
				}
				vbNos[i] = uint16(vbNumber)
			}
			entry := base.PartitionStorage{
				Index: uint16(index),
				Uuid:  pIndex.UUID,
				VbNos: vbNos,
			}
			partitionDef = append(partitionDef, entry)
		}

		// Persist to bucket
		value, err = json.Marshal(partitionDef)
		if err != nil {
			return nil, err
		}
		k.reader.indexReadBucket.SetRaw(base.KIndexPartitionKey, 0, value)
	}

	// Create k.indexPartitions based on partitionDef
	k.indexPartitions = base.NewIndexPartitions(partitionDef)
	return k.indexPartitions, nil
}