doc

package
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2022 License: Apache-2.0 Imports: 10 Imported by: 32

Documentation

Overview

Package doc is a generated GoMock package.

Index

Constants

This section is empty.

Variables

View Source
var (

	// ErrEmptyDocument is an error for an empty document.
	ErrEmptyDocument = errors.New("document cannot be empty")
)
View Source
var IDReservedFieldName = []byte("_m3ninx_id")

IDReservedFieldName is the field name reserved for IDs.

Functions

This section is empty.

Types

type Document

type Document struct {
	// contains filtered or unexported fields
}

Document contains either metadata or an encoded metadata but never both.

func NewDocumentFromEncoded added in v1.0.1

func NewDocumentFromEncoded(e Encoded) Document

NewDocumentFromEncoded creates a Document from an Encoded.

func NewDocumentFromMetadata added in v1.0.1

func NewDocumentFromMetadata(m Metadata) Document

NewDocumentFromMetadata creates a Document from a Metadata.

func (*Document) Encoded added in v1.0.1

func (d *Document) Encoded() (Encoded, bool)

Encoded returns the encoded metadata it contains, if it has one. Otherwise returns an empty encoded metadata and false.

func (*Document) Metadata added in v1.0.1

func (d *Document) Metadata() (Metadata, bool)

Metadata returns the metadata it contains, if it has one. Otherwise returns an empty metadata and false.

type DocumentArr added in v0.5.0

type DocumentArr []Document

type DocumentArrPool added in v0.5.0

type DocumentArrPool struct {
	// contains filtered or unexported fields
}

func (*DocumentArrPool) Get added in v0.5.0

func (p *DocumentArrPool) Get() []Document

func (*DocumentArrPool) Init added in v0.5.0

func (p *DocumentArrPool) Init()

func (*DocumentArrPool) Put added in v0.5.0

func (p *DocumentArrPool) Put(arr []Document)

type DocumentArrayPool added in v0.5.0

type DocumentArrayPool interface {
	// Init initializes the array pool, it needs to be called
	// before Get/Put use.
	Init()

	// Get returns the a slice from the pool.
	Get() []Document

	// Put returns the provided slice to the pool.
	Put(elems []Document)
}

DocumentArrayPool provides a pool for document slices.

func NewDocumentArrayPool added in v0.5.0

func NewDocumentArrayPool(opts DocumentArrayPoolOpts) DocumentArrayPool

type DocumentArrayPoolOpts added in v0.5.0

type DocumentArrayPoolOpts struct {
	Options     pool.ObjectPoolOptions
	Capacity    int
	MaxCapacity int
	FinalizeFn  DocumentFinalizeFn
}

type DocumentFinalizeFn added in v0.5.0

type DocumentFinalizeFn func([]Document) []Document

type DocumentMatcher

type DocumentMatcher interface {
	gomock.Matcher
}

DocumentMatcher matches a given document.

func NewDocumentMatcher

func NewDocumentMatcher(d Metadata) DocumentMatcher

NewDocumentMatcher returns a new DocumentMatcher.

type Documents

type Documents []Metadata

Documents is a list of documents.

func (Documents) Len

func (ds Documents) Len() int

func (Documents) Less

func (ds Documents) Less(i, j int) bool

func (Documents) Swap

func (ds Documents) Swap(i, j int)

type Encoded added in v1.0.1

type Encoded struct {
	Bytes []byte
}

Encoded is a serialized document metadata.

type EntryIndexBlockState added in v1.4.2

type EntryIndexBlockState struct {
	// Attempt indicates that indexing has been attempted.
	Attempt bool
	// Success indicates that indexing has succeeded.
	Success bool
}

EntryIndexBlockState is used to capture the state of indexing for a single shard entry for a given index block start. It's used to prevent attempts at double indexing for the same block start.

type EntryIndexBlockStates added in v1.4.2

type EntryIndexBlockStates map[xtime.UnixNano]EntryIndexBlockState

EntryIndexBlockStates captures the indexing for a single shard entry, across all block starts.

type Field

type Field struct {
	Name  []byte
	Value []byte
}

Field represents a field in a document. It is composed of a name and a value.

type Fields

type Fields []Field

Fields is a list of fields.

func (Fields) Len

func (f Fields) Len() int

func (Fields) Less

func (f Fields) Less(i, j int) bool

func (Fields) Swap

func (f Fields) Swap(i, j int)

type Iterator

type Iterator interface {

	// Next returns a bool indicating if the iterator has any more documents
	// to return.
	Next() bool

	// Current returns the current document. It is only safe to call Current immediately
	// after a call to Next confirms there are more elements remaining. The Document
	// returned from Current is only valid until the following call to Next(). Callers
	// should copy the Document if they need it live longer.
	Current() Document

	// Err returns any errors encountered during iteration.
	Err() error

	// Close releases any internal resources used by the iterator.
	Close() error
}

Iterator provides an iterator over a collection of documents. It is NOT safe for multiple goroutines to invoke methods on an Iterator simultaneously.

type Metadata added in v1.0.1

type Metadata struct {
	ID            []byte
	Fields        []Field
	OnIndexSeries OnIndexSeries
}

Metadata represents a document to be indexed.

func (Metadata) Compare added in v1.0.1

func (m Metadata) Compare(other Metadata) int

Compare returns an integer comparing two documents. The result will be 0 if the documents are equal, -1 if d is ordered before other, and 1 if d is ordered aftered other.

func (Metadata) Equal added in v1.0.1

func (m Metadata) Equal(other Metadata) bool

Equal returns a bool indicating whether d is equal to other.

func (Metadata) Get added in v1.0.1

func (m Metadata) Get(fieldName []byte) ([]byte, bool)

Get returns the value of the specified field name in the document if it exists.

func (Metadata) HasID added in v1.0.1

func (m Metadata) HasID() bool

HasID returns a bool indicating whether the document has an ID or not.

func (Metadata) String added in v1.0.1

func (m Metadata) String() string

func (Metadata) Validate added in v1.0.1

func (m Metadata) Validate() error

Validate returns a bool indicating whether the document is valid.

type MetadataArr added in v1.0.1

type MetadataArr []Metadata

type MetadataArrPool added in v1.0.1

type MetadataArrPool struct {
	// contains filtered or unexported fields
}

func (*MetadataArrPool) Get added in v1.0.1

func (p *MetadataArrPool) Get() []Metadata

func (*MetadataArrPool) Init added in v1.0.1

func (p *MetadataArrPool) Init()

func (*MetadataArrPool) Put added in v1.0.1

func (p *MetadataArrPool) Put(arr []Metadata)

type MetadataArrayPool added in v1.0.1

type MetadataArrayPool interface {
	// Init initializes the array pool, it needs to be called
	// before Get/Put use.
	Init()

	// Get returns the a slice from the pool.
	Get() []Metadata

	// Put returns the provided slice to the pool.
	Put(elems []Metadata)
}

MetadataArrayPool provides a pool for metadata slices.

func NewMetadataArrayPool added in v1.0.1

func NewMetadataArrayPool(opts MetadataArrayPoolOpts) MetadataArrayPool

type MetadataArrayPoolOpts added in v1.0.1

type MetadataArrayPoolOpts struct {
	Options     pool.ObjectPoolOptions
	Capacity    int
	MaxCapacity int
	FinalizeFn  MetadataFinalizeFn
}

type MetadataFinalizeFn added in v1.0.1

type MetadataFinalizeFn func([]Metadata) []Metadata

type MetadataIterator added in v1.0.1

type MetadataIterator interface {
	// Next returns a bool indicating if the iterator has any more metadata
	// to return.
	Next() bool

	// Current returns the current metadata. It is only safe to call Current immediately
	// after a call to Next confirms there are more elements remaining. The Metadata
	// returned from Current is only valid until the following call to Next(). Callers
	// should copy the Metadata if they need it live longer.
	Current() Metadata

	// Err returns any errors encountered during iteration.
	Err() error

	// Close releases any internal resources used by the iterator.
	Close() error
}

MetadataIterator provides an iterator over a collection of document metadata. It is NOT safe for multiple goroutines to invoke methods on an MetadataIterator simultaneously.

type MockIterator

type MockIterator struct {
	// contains filtered or unexported fields
}

MockIterator is a mock of Iterator interface.

func NewMockIterator

func NewMockIterator(ctrl *gomock.Controller) *MockIterator

NewMockIterator creates a new mock instance.

func (*MockIterator) Close

func (m *MockIterator) Close() error

Close mocks base method.

func (*MockIterator) Current

func (m *MockIterator) Current() Document

Current mocks base method.

func (*MockIterator) EXPECT

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockIterator) Err

func (m *MockIterator) Err() error

Err mocks base method.

func (*MockIterator) Next

func (m *MockIterator) Next() bool

Next mocks base method.

type MockIteratorMockRecorder

type MockIteratorMockRecorder struct {
	// contains filtered or unexported fields
}

MockIteratorMockRecorder is the mock recorder for MockIterator.

func (*MockIteratorMockRecorder) Close

func (mr *MockIteratorMockRecorder) Close() *gomock.Call

Close indicates an expected call of Close.

func (*MockIteratorMockRecorder) Current

func (mr *MockIteratorMockRecorder) Current() *gomock.Call

Current indicates an expected call of Current.

func (*MockIteratorMockRecorder) Err

Err indicates an expected call of Err.

func (*MockIteratorMockRecorder) Next

func (mr *MockIteratorMockRecorder) Next() *gomock.Call

Next indicates an expected call of Next.

type MockMetadataIterator added in v1.0.1

type MockMetadataIterator struct {
	// contains filtered or unexported fields
}

MockMetadataIterator is a mock of MetadataIterator interface.

func NewMockMetadataIterator added in v1.0.1

func NewMockMetadataIterator(ctrl *gomock.Controller) *MockMetadataIterator

NewMockMetadataIterator creates a new mock instance.

func (*MockMetadataIterator) Close added in v1.0.1

func (m *MockMetadataIterator) Close() error

Close mocks base method.

func (*MockMetadataIterator) Current added in v1.0.1

func (m *MockMetadataIterator) Current() Metadata

Current mocks base method.

func (*MockMetadataIterator) EXPECT added in v1.0.1

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockMetadataIterator) Err added in v1.0.1

func (m *MockMetadataIterator) Err() error

Err mocks base method.

func (*MockMetadataIterator) Next added in v1.0.1

func (m *MockMetadataIterator) Next() bool

Next mocks base method.

type MockMetadataIteratorMockRecorder added in v1.0.1

type MockMetadataIteratorMockRecorder struct {
	// contains filtered or unexported fields
}

MockMetadataIteratorMockRecorder is the mock recorder for MockMetadataIterator.

func (*MockMetadataIteratorMockRecorder) Close added in v1.0.1

Close indicates an expected call of Close.

func (*MockMetadataIteratorMockRecorder) Current added in v1.0.1

Current indicates an expected call of Current.

func (*MockMetadataIteratorMockRecorder) Err added in v1.0.1

Err indicates an expected call of Err.

func (*MockMetadataIteratorMockRecorder) Next added in v1.0.1

Next indicates an expected call of Next.

type MockOnIndexSeries added in v1.2.0

type MockOnIndexSeries struct {
	// contains filtered or unexported fields
}

MockOnIndexSeries is a mock of OnIndexSeries interface.

func NewMockOnIndexSeries added in v1.2.0

func NewMockOnIndexSeries(ctrl *gomock.Controller) *MockOnIndexSeries

NewMockOnIndexSeries creates a new mock instance.

func (*MockOnIndexSeries) EXPECT added in v1.2.0

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockOnIndexSeries) IfAlreadyIndexedMarkIndexSuccessAndFinalize added in v1.2.0

func (m *MockOnIndexSeries) IfAlreadyIndexedMarkIndexSuccessAndFinalize(blockStart time.UnixNano) bool

IfAlreadyIndexedMarkIndexSuccessAndFinalize mocks base method.

func (*MockOnIndexSeries) IndexedForBlockStart added in v1.2.0

func (m *MockOnIndexSeries) IndexedForBlockStart(blockStart time.UnixNano) bool

IndexedForBlockStart mocks base method.

func (*MockOnIndexSeries) IndexedRange added in v1.3.0

func (m *MockOnIndexSeries) IndexedRange() (time.UnixNano, time.UnixNano)

IndexedRange mocks base method.

func (*MockOnIndexSeries) MergeEntryIndexBlockStates added in v1.4.2

func (m *MockOnIndexSeries) MergeEntryIndexBlockStates(states EntryIndexBlockStates)

MergeEntryIndexBlockStates mocks base method.

func (*MockOnIndexSeries) NeedsIndexGarbageCollected added in v1.2.0

func (m *MockOnIndexSeries) NeedsIndexGarbageCollected() bool

NeedsIndexGarbageCollected mocks base method.

func (*MockOnIndexSeries) NeedsIndexUpdate added in v1.2.0

func (m *MockOnIndexSeries) NeedsIndexUpdate(indexBlockStartForWrite time.UnixNano) bool

NeedsIndexUpdate mocks base method.

func (*MockOnIndexSeries) OnIndexFinalize added in v1.2.0

func (m *MockOnIndexSeries) OnIndexFinalize(blockStart time.UnixNano)

OnIndexFinalize mocks base method.

func (*MockOnIndexSeries) OnIndexPrepare added in v1.2.0

func (m *MockOnIndexSeries) OnIndexPrepare(blockStart time.UnixNano)

OnIndexPrepare mocks base method.

func (*MockOnIndexSeries) OnIndexSuccess added in v1.2.0

func (m *MockOnIndexSeries) OnIndexSuccess(blockStart time.UnixNano)

OnIndexSuccess mocks base method.

func (*MockOnIndexSeries) ReconciledOnIndexSeries added in v1.4.0

func (m *MockOnIndexSeries) ReconciledOnIndexSeries() (OnIndexSeries, resource.SimpleCloser, bool)

ReconciledOnIndexSeries mocks base method.

func (*MockOnIndexSeries) StringID added in v1.4.2

func (m *MockOnIndexSeries) StringID() string

StringID mocks base method.

func (*MockOnIndexSeries) TryMarkIndexGarbageCollected added in v1.2.0

func (m *MockOnIndexSeries) TryMarkIndexGarbageCollected() bool

TryMarkIndexGarbageCollected mocks base method.

func (*MockOnIndexSeries) TryReconcileDuplicates added in v1.4.2

func (m *MockOnIndexSeries) TryReconcileDuplicates()

TryReconcileDuplicates mocks base method.

type MockOnIndexSeriesMockRecorder added in v1.2.0

type MockOnIndexSeriesMockRecorder struct {
	// contains filtered or unexported fields
}

MockOnIndexSeriesMockRecorder is the mock recorder for MockOnIndexSeries.

func (*MockOnIndexSeriesMockRecorder) IfAlreadyIndexedMarkIndexSuccessAndFinalize added in v1.2.0

func (mr *MockOnIndexSeriesMockRecorder) IfAlreadyIndexedMarkIndexSuccessAndFinalize(blockStart interface{}) *gomock.Call

IfAlreadyIndexedMarkIndexSuccessAndFinalize indicates an expected call of IfAlreadyIndexedMarkIndexSuccessAndFinalize.

func (*MockOnIndexSeriesMockRecorder) IndexedForBlockStart added in v1.2.0

func (mr *MockOnIndexSeriesMockRecorder) IndexedForBlockStart(blockStart interface{}) *gomock.Call

IndexedForBlockStart indicates an expected call of IndexedForBlockStart.

func (*MockOnIndexSeriesMockRecorder) IndexedRange added in v1.3.0

func (mr *MockOnIndexSeriesMockRecorder) IndexedRange() *gomock.Call

IndexedRange indicates an expected call of IndexedRange.

func (*MockOnIndexSeriesMockRecorder) MergeEntryIndexBlockStates added in v1.4.2

func (mr *MockOnIndexSeriesMockRecorder) MergeEntryIndexBlockStates(states interface{}) *gomock.Call

MergeEntryIndexBlockStates indicates an expected call of MergeEntryIndexBlockStates.

func (*MockOnIndexSeriesMockRecorder) NeedsIndexGarbageCollected added in v1.2.0

func (mr *MockOnIndexSeriesMockRecorder) NeedsIndexGarbageCollected() *gomock.Call

NeedsIndexGarbageCollected indicates an expected call of NeedsIndexGarbageCollected.

func (*MockOnIndexSeriesMockRecorder) NeedsIndexUpdate added in v1.2.0

func (mr *MockOnIndexSeriesMockRecorder) NeedsIndexUpdate(indexBlockStartForWrite interface{}) *gomock.Call

NeedsIndexUpdate indicates an expected call of NeedsIndexUpdate.

func (*MockOnIndexSeriesMockRecorder) OnIndexFinalize added in v1.2.0

func (mr *MockOnIndexSeriesMockRecorder) OnIndexFinalize(blockStart interface{}) *gomock.Call

OnIndexFinalize indicates an expected call of OnIndexFinalize.

func (*MockOnIndexSeriesMockRecorder) OnIndexPrepare added in v1.2.0

func (mr *MockOnIndexSeriesMockRecorder) OnIndexPrepare(blockStart interface{}) *gomock.Call

OnIndexPrepare indicates an expected call of OnIndexPrepare.

func (*MockOnIndexSeriesMockRecorder) OnIndexSuccess added in v1.2.0

func (mr *MockOnIndexSeriesMockRecorder) OnIndexSuccess(blockStart interface{}) *gomock.Call

OnIndexSuccess indicates an expected call of OnIndexSuccess.

func (*MockOnIndexSeriesMockRecorder) ReconciledOnIndexSeries added in v1.4.0

func (mr *MockOnIndexSeriesMockRecorder) ReconciledOnIndexSeries() *gomock.Call

ReconciledOnIndexSeries indicates an expected call of ReconciledOnIndexSeries.

func (*MockOnIndexSeriesMockRecorder) StringID added in v1.4.2

func (mr *MockOnIndexSeriesMockRecorder) StringID() *gomock.Call

StringID indicates an expected call of StringID.

func (*MockOnIndexSeriesMockRecorder) TryMarkIndexGarbageCollected added in v1.2.0

func (mr *MockOnIndexSeriesMockRecorder) TryMarkIndexGarbageCollected() *gomock.Call

TryMarkIndexGarbageCollected indicates an expected call of TryMarkIndexGarbageCollected.

func (*MockOnIndexSeriesMockRecorder) TryReconcileDuplicates added in v1.4.2

func (mr *MockOnIndexSeriesMockRecorder) TryReconcileDuplicates() *gomock.Call

TryReconcileDuplicates indicates an expected call of TryReconcileDuplicates.

type MockQueryDocIterator added in v1.2.0

type MockQueryDocIterator struct {
	// contains filtered or unexported fields
}

MockQueryDocIterator is a mock of QueryDocIterator interface.

func NewMockQueryDocIterator added in v1.2.0

func NewMockQueryDocIterator(ctrl *gomock.Controller) *MockQueryDocIterator

NewMockQueryDocIterator creates a new mock instance.

func (*MockQueryDocIterator) Close added in v1.2.0

func (m *MockQueryDocIterator) Close() error

Close mocks base method.

func (*MockQueryDocIterator) Current added in v1.2.0

func (m *MockQueryDocIterator) Current() Document

Current mocks base method.

func (*MockQueryDocIterator) Done added in v1.2.0

func (m *MockQueryDocIterator) Done() bool

Done mocks base method.

func (*MockQueryDocIterator) EXPECT added in v1.2.0

EXPECT returns an object that allows the caller to indicate expected use.

func (*MockQueryDocIterator) Err added in v1.2.0

func (m *MockQueryDocIterator) Err() error

Err mocks base method.

func (*MockQueryDocIterator) Next added in v1.2.0

func (m *MockQueryDocIterator) Next() bool

Next mocks base method.

type MockQueryDocIteratorMockRecorder added in v1.2.0

type MockQueryDocIteratorMockRecorder struct {
	// contains filtered or unexported fields
}

MockQueryDocIteratorMockRecorder is the mock recorder for MockQueryDocIterator.

func (*MockQueryDocIteratorMockRecorder) Close added in v1.2.0

Close indicates an expected call of Close.

func (*MockQueryDocIteratorMockRecorder) Current added in v1.2.0

Current indicates an expected call of Current.

func (*MockQueryDocIteratorMockRecorder) Done added in v1.2.0

Done indicates an expected call of Done.

func (*MockQueryDocIteratorMockRecorder) Err added in v1.2.0

Err indicates an expected call of Err.

func (*MockQueryDocIteratorMockRecorder) Next added in v1.2.0

Next indicates an expected call of Next.

type OnIndexSeries added in v1.2.0

type OnIndexSeries interface {
	// StringID returns the index series ID, as a string.
	StringID() string

	// OnIndexSuccess is executed when an entry is successfully indexed. The
	// provided value for `blockStart` is the blockStart for which the write
	// was indexed.
	OnIndexSuccess(blockStart xtime.UnixNano)

	// OnIndexFinalize is executed when the index no longer holds any references
	// to the provided resources. It can be used to cleanup any resources held
	// during the course of indexing. `blockStart` is the startTime of the index
	// block for which the write was attempted.
	OnIndexFinalize(blockStart xtime.UnixNano)

	// OnIndexPrepare prepares the Entry to be handed off to the indexing sub-system.
	// NB(prateek): we retain the ref count on the entry while the indexing is pending,
	// the callback executed on the entry once the indexing is completed releases this
	// reference.
	OnIndexPrepare(blockStart xtime.UnixNano)

	// NeedsIndexUpdate returns a bool to indicate if the Entry needs to be indexed
	// for the provided blockStart. It only allows a single index attempt at a time
	// for a single entry.
	// NB(prateek): NeedsIndexUpdate is a CAS, i.e. when this method returns true, it
	// also sets state on the entry to indicate that a write for the given blockStart
	// is going to be sent to the index, and other go routines should not attempt the
	// same write. Callers are expected to ensure they follow this guideline.
	// Further, every call to NeedsIndexUpdate which returns true needs to have a corresponding
	// OnIndexFinalze() call. This is required for correct lifecycle maintenance.
	NeedsIndexUpdate(indexBlockStartForWrite xtime.UnixNano) bool

	// IfAlreadyIndexedMarkIndexSuccessAndFinalize checks if the blockStart has been indexed.
	// If indexed, it will be marked as such and finalized, and then return true. Otherwise false.
	IfAlreadyIndexedMarkIndexSuccessAndFinalize(
		blockStart xtime.UnixNano,
	) bool

	// TryMarkIndexGarbageCollected checks if the entry is eligible to be garbage collected
	// from the index. If so, it marks the entry as GCed and returns true. Otherwise returns false.
	TryMarkIndexGarbageCollected() bool

	// NeedsIndexGarbageCollected returns if the entry is eligible to be garbage collected
	// from the index.
	NeedsIndexGarbageCollected() bool

	// IndexedForBlockStart returns true if the blockStart has been indexed.
	IndexedForBlockStart(blockStart xtime.UnixNano) bool

	// IndexedRange returns minimum and maximum blockStart values covered by index entry.
	// The range is inclusive. Note that there may be uncovered gaps within the range.
	// Returns (0, 0) for an empty range.
	IndexedRange() (xtime.UnixNano, xtime.UnixNano)

	// ReconciledOnIndexSeries attempts to retrieve the most recent index entry from the
	// shard if the entry this method was called on was never inserted there. If there
	// is an error during retrieval, simply returns the current entry. Additionally,
	// returns a cleanup function to run once finished using the reconciled entry and
	// a boolean value indicating whether the result came from reconciliation or not.
	// Cleanup function must be called once done with the reconciled entry so that
	// reader and writer counts are accurately updated.
	ReconciledOnIndexSeries() (OnIndexSeries, resource.SimpleCloser, bool)

	// MergeEntryIndexBlockStates merges the given states into the current
	// indexed entry.
	MergeEntryIndexBlockStates(states EntryIndexBlockStates)

	// TryReconcileDuplicates attempts to reconcile the index states of this entry.
	TryReconcileDuplicates()
}

OnIndexSeries provides a set of callback hooks to allow the reverse index to do lifecycle management of any resources retained during indexing.

type QueryDocIterator added in v1.2.0

type QueryDocIterator interface {
	Iterator

	// Done returns true if iterator is done and Next will return false on the next call. On the first call this will
	// always return false and Next may still return false for an empty iterator. Callers still need to check for an
	// Err after Done returns true.
	// This is used by the index query path to check if there are more docs to process before waiting for an index
	// worker.
	Done() bool
}

QueryDocIterator is an Iterator for all documents returned for a query. See Iterator for more details.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL