func (context *DatabaseContext) GetCBGTIndexNameForBucket(bucket base.Bucket) (indexName string) { // Real Couchbase buckets use an index name that includes UUID. cbBucket, ok := bucket.(base.CouchbaseBucket) if ok { indexName = cbBucket.GetCBGTIndexName() } else { indexName = bucket.GetName() } return indexName }
// Starts a changeListener on a given Bucket. func (listener *changeListener) Start(bucket base.Bucket, trackDocs bool, notify sgbucket.BucketNotifyFn) error { listener.bucket = bucket listener.bucketName = bucket.GetName() listener.TapArgs = sgbucket.TapArguments{ Backfill: sgbucket.TapNoBackfill, Notify: notify, } tapFeed, err := bucket.StartTapFeed(listener.TapArgs) if err != nil { return err } listener.tapFeed = tapFeed if trackDocs { listener.DocChannel = make(chan sgbucket.TapEvent, 100) } // Start a goroutine to broadcast to the tapNotifier whenever a channel or user/role changes: go func() { defer func() { listener.notifyStopping() if listener.DocChannel != nil { close(listener.DocChannel) } }() for event := range tapFeed.Events() { if event.Opcode == sgbucket.TapMutation || event.Opcode == sgbucket.TapDeletion { key := string(event.Key) if strings.HasPrefix(key, auth.UserKeyPrefix) || strings.HasPrefix(key, auth.RoleKeyPrefix) { if listener.OnDocChanged != nil { listener.OnDocChanged(key, event.Value, event.Sequence, event.VbNo) } listener.Notify(base.SetOf(key)) } else if !strings.HasPrefix(key, KSyncKeyPrefix) && !strings.HasPrefix(key, base.KIndexPrefix) { if listener.OnDocChanged != nil { listener.OnDocChanged(key, event.Value, event.Sequence, event.VbNo) } if trackDocs { listener.DocChannel <- event } } } } }() return nil }
// Creates a new DatabaseContext on a bucket. The bucket will be closed when this context closes. func NewDatabaseContext(dbName string, bucket base.Bucket, autoImport bool, options DatabaseContextOptions) (*DatabaseContext, error) { if err := ValidateDatabaseName(dbName); err != nil { return nil, err } context := &DatabaseContext{ Name: dbName, Bucket: bucket, StartTime: time.Now(), RevsLimit: DefaultRevsLimit, autoImport: autoImport, Options: options, } context.revisionCache = NewRevisionCache(int(options.RevisionCacheCapacity), context.revCacheLoader) context.EventMgr = NewEventManager() var err error context.sequences, err = newSequenceAllocator(bucket) if err != nil { return nil, err } lastSeq, err := context.sequences.lastSequence() if err != nil { return nil, err } if options.IndexOptions == nil { // In-memory channel cache context.SequenceType = IntSequenceType context.changeCache = &changeCache{} } else { // KV channel index context.SequenceType = ClockSequenceType context.changeCache = &kvChangeIndex{} context.SequenceHasher, err = NewSequenceHasher(options.SequenceHashOptions) if err != nil { return nil, err } } context.changeCache.Init(context, SequenceID{Seq: lastSeq}, func(changedChannels base.Set) { context.tapListener.Notify(changedChannels) }, options.CacheOptions, options.IndexOptions) context.SetOnChangeCallback(context.changeCache.DocChanged) // Initialize the tap Listener for notify handling context.tapListener.Init(bucket.GetName()) // If not using channel index, start the tap feed if options.IndexOptions == nil { if err = context.tapListener.Start(bucket, options.TrackDocs, func(bucket string, err error) { context.TakeDbOffline("Lost TAP Feed") }); err != nil { return nil, err } } // Load providers into provider map. Does basic validation on the provider definition, and identifies the default provider. if options.OIDCOptions != nil { context.OIDCProviders = make(auth.OIDCProviderMap) for name, provider := range options.OIDCOptions.Providers { if provider.Issuer == "" || provider.ClientID == nil { base.Warn("Issuer and ClientID required for OIDC Provider - skipping provider %q", name) continue } if provider.ValidationKey == nil { base.Warn("Validation Key not defined in config for provider %q - auth code flow will not be supported for this provider", name) } if strings.Contains(name, "_") { return nil, fmt.Errorf("OpenID Connect provider names cannot contain underscore:%s", name) } provider.Name = name if _, ok := context.OIDCProviders[provider.Issuer]; ok { base.Warn("Multiple OIDC providers defined for issuer %v", provider.Issuer) return nil, fmt.Errorf("Multiple OIDC providers defined for issuer %v", provider.Issuer) } // If this is the default provider, or there's only one provider defined, set IsDefault if (options.OIDCOptions.DefaultProvider != nil && name == *options.OIDCOptions.DefaultProvider) || len(options.OIDCOptions.Providers) == 1 { provider.IsDefault = true } // If this isn't the default provider, add the provider to the callback URL (needed to identify provider to _oidc_callback) if !provider.IsDefault && provider.CallbackURL != nil { var updatedCallback string if strings.Contains(*provider.CallbackURL, "?") { updatedCallback = fmt.Sprintf("%s&provider=%s", *provider.CallbackURL, name) } else { updatedCallback = fmt.Sprintf("%s?provider=%s", *provider.CallbackURL, name) } provider.CallbackURL = &updatedCallback } context.OIDCProviders[name] = provider } if len(context.OIDCProviders) == 0 { return nil, errors.New("OpenID Connect defined in config, but no valid OpenID Connect providers specified.") } } go context.watchDocChanges() return context, nil }