// The indexName/indexUUID is for a user-defined index alias. // // TODO: One day support user-defined aliases for non-bleve indexes. func bleveIndexAliasForUserIndexAlias(mgr *cbgt.Manager, indexName, indexUUID string, ensureCanRead bool, consistencyParams *cbgt.ConsistencyParams, cancelCh <-chan bool, groupByNode bool) ( bleve.IndexAlias, error) { alias := bleve.NewIndexAlias() indexDefs, _, err := mgr.GetIndexDefs(false) if err != nil { return nil, fmt.Errorf("alias: could not get indexDefs,"+ " indexName: %s, err: %v", indexName, err) } num := 0 var fillAlias func(aliasName, aliasUUID string) error fillAlias = func(aliasName, aliasUUID string) error { aliasDef := indexDefs.IndexDefs[aliasName] if aliasDef == nil { return fmt.Errorf("alias: could not get aliasDef,"+ " aliasName: %s, indexName: %s", aliasName, indexName) } if aliasDef.Type != "fulltext-alias" { return fmt.Errorf("alias: not fulltext-alias type: %s,"+ " aliasName: %s, indexName: %s", aliasDef.Type, aliasName, indexName) } if aliasUUID != "" && aliasUUID != aliasDef.UUID { return fmt.Errorf("alias: mismatched aliasUUID: %s,"+ " aliasDef.UUID: %s, aliasName: %s, indexName: %s", aliasUUID, aliasDef.UUID, aliasName, indexName) } params, err := parseAliasParams(aliasDef.Params) if err != nil { return fmt.Errorf("alias: could not parse aliasDef.Params: %s,"+ " aliasName: %s, indexName: %s", aliasDef.Params, aliasName, indexName) } for targetName, targetSpec := range params.Targets { if num > maxAliasTargets { return fmt.Errorf("alias: too many alias targets,"+ " perhaps there's a cycle,"+ " aliasName: %s, indexName: %s", aliasName, indexName) } targetDef := indexDefs.IndexDefs[targetName] if targetDef == nil { return fmt.Errorf("alias: the alias depends upon"+ " a target index that does not exist,"+ " targetName: %q, aliasName: %q", targetName, aliasName) } if targetSpec.IndexUUID != "" && targetSpec.IndexUUID != targetDef.UUID { return fmt.Errorf("alias: mismatched targetSpec.UUID: %s,"+ " targetDef.UUID: %s, targetName: %s,"+ " aliasName: %s, indexName: %s", targetSpec.IndexUUID, targetDef.UUID, targetName, aliasName, indexName) } // TODO: Convert to registered callbacks instead of if-else-if. if targetDef.Type == "fulltext-alias" { err = fillAlias(targetName, targetSpec.IndexUUID) if err != nil { return err } } else if strings.HasPrefix(targetDef.Type, "fulltext-index") { subAlias, _, err := bleveIndexAlias(mgr, targetName, targetSpec.IndexUUID, ensureCanRead, consistencyParams, cancelCh, true, nil) if err != nil { return err } alias.Add(subAlias) num += 1 } else { return fmt.Errorf("alias: unsupported target type: %s,"+ " targetName: %s, aliasName: %s, indexName: %s", targetDef.Type, targetName, aliasName, indexName) } } return nil } err = fillAlias(indexName, indexUUID) if err != nil { return nil, err } return alias, nil }
func RunRecentInfoCache(mgr *cbgt.Manager) { cfg := mgr.Cfg() cfgChangedCh := make(chan struct{}, 10) go func() { // Debounce cfg events to feed into the cfgChangedCh. ech := make(chan cbgt.CfgEvent) cfg.Subscribe(cbgt.PLAN_PINDEXES_KEY, ech) for { <-ech // First, wait for a cfg event. debounceTimeCh := time.After(500 * time.Millisecond) DEBOUNCE_LOOP: for { select { case <-ech: // NO-OP when there are more, spammy cfg events. case <-debounceTimeCh: break DEBOUNCE_LOOP } } cfgChangedCh <- struct{}{} } }() tickCh := time.Tick(1 * time.Minute) for { var nodeDefs *cbgt.NodeDefs var planPIndexes *cbgt.PlanPIndexes indexDefs, indexDefsMap, err := mgr.GetIndexDefs(false) if err == nil { nodeDefs, _, err = cbgt.CfgGetNodeDefs(cfg, cbgt.NODE_DEFS_WANTED) if err == nil { planPIndexes, _, err = cbgt.CfgGetPlanPIndexes(cfg) } } rd := &recentInfo{ indexDefs: indexDefs, indexDefsMap: indexDefsMap, nodeDefs: nodeDefs, planPIndexes: planPIndexes, err: err, } runtime.ReadMemStats(&rd.memStats) REUSE_CACHE: for { select { case <-cfgChangedCh: break REUSE_CACHE case <-tickCh: break REUSE_CACHE case recentInfoCh <- rd: if rd.err != nil { break REUSE_CACHE } } } } }