コード例 #1
0
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

}
コード例 #2
0
// 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
}
コード例 #3
0
ファイル: database.go プロジェクト: couchbase/sync_gateway
// 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
}