// initIndexPartitions first attempts to initialize the index partitions using the partition map document in // the index bucket. If that hasn't been created yet, tries to generate the partition information from CBGT. // If unsuccessful on both of these, returns error and leaves k.indexPartitions as 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 } // First attempt to load from the bucket partitionDef, err := k.loadIndexPartitionsFromBucket() if err != nil { return nil, err } indexExpvars.Add("get_indexPartitionMap", 1) // If unable to load from index bucket - attempt to initialize based on cbgt partitions if partitionDef == nil { partitionDef, err = k.retrieveCBGTPartitions() if err != nil { return nil, errors.New(fmt.Sprintf("Unable to determine partition map for index - not found in index, and not available from cbgt: %v", err)) } // Add to the bucket value, err := json.Marshal(partitionDef) if err != nil { return nil, err } added, err := k.reader.indexReadBucket.AddRaw(base.KIndexPartitionKey, 0, value) if err != nil { return nil, err } // If add fails, it may have been written by another node since the last read attempt. Make // another attempt to use the version from the bucket, to ensure consistency. if added == false { partitionDef, err = k.loadIndexPartitionsFromBucket() if err != nil { return nil, err } } } // Create k.indexPartitions based on partitionDef k.indexPartitions = base.NewIndexPartitions(partitionDef) return k.indexPartitions, nil }
func testPartitionMap() *base.IndexPartitions { partitions := make([]base.PartitionStorage, 64) numPartitions := uint16(64) vbPerPartition := 1024 / numPartitions for partition := uint16(0); partition < numPartitions; partition++ { pStorage := base.PartitionStorage{ Index: partition, Uuid: fmt.Sprintf("partition_%d", partition), VbNos: make([]uint16, vbPerPartition), } for index := uint16(0); index < vbPerPartition; index++ { vb := partition*vbPerPartition + index pStorage.VbNos[index] = vb } partitions[partition] = pStorage } indexPartitions := base.NewIndexPartitions(partitions) return indexPartitions }
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 }