// Copyright 2015 The LUCI Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.25.0-devel
// 	protoc        v3.12.1
// source: go.chromium.org/luci/logdog/api/config/svcconfig/archival.proto

package svcconfig

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

// ArchiveIndexConfig specifies how archive indexes should be generated.
//
// By default, each log entry will be present in the index. This is generally
// overkill; instead, the index can be more sparse at the expense of a slightly
// higher data load.
type ArchiveIndexConfig struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	// If not zero, the maximum number of stream indices between index entries.
	StreamRange int32 `protobuf:"varint,1,opt,name=stream_range,json=streamRange,proto3" json:"stream_range,omitempty"`
	// If not zero, the maximum number of prefix indices between index entries.
	PrefixRange int32 `protobuf:"varint,2,opt,name=prefix_range,json=prefixRange,proto3" json:"prefix_range,omitempty"`
	// If not zero, the maximum number of log data bytes between index entries.
	ByteRange int32 `protobuf:"varint,3,opt,name=byte_range,json=byteRange,proto3" json:"byte_range,omitempty"`
}

func (x *ArchiveIndexConfig) Reset() {
	*x = ArchiveIndexConfig{}
	if protoimpl.UnsafeEnabled {
		mi := &file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_msgTypes[0]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *ArchiveIndexConfig) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*ArchiveIndexConfig) ProtoMessage() {}

func (x *ArchiveIndexConfig) ProtoReflect() protoreflect.Message {
	mi := &file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_msgTypes[0]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use ArchiveIndexConfig.ProtoReflect.Descriptor instead.
func (*ArchiveIndexConfig) Descriptor() ([]byte, []int) {
	return file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDescGZIP(), []int{0}
}

func (x *ArchiveIndexConfig) GetStreamRange() int32 {
	if x != nil {
		return x.StreamRange
	}
	return 0
}

func (x *ArchiveIndexConfig) GetPrefixRange() int32 {
	if x != nil {
		return x.PrefixRange
	}
	return 0
}

func (x *ArchiveIndexConfig) GetByteRange() int32 {
	if x != nil {
		return x.ByteRange
	}
	return 0
}

var File_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto protoreflect.FileDescriptor

var file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDesc = []byte{
	0x0a, 0x3f, 0x67, 0x6f, 0x2e, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72,
	0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f, 0x6c, 0x6f, 0x67, 0x64, 0x6f, 0x67, 0x2f, 0x61, 0x70,
	0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x73, 0x76, 0x63, 0x63, 0x6f, 0x6e, 0x66,
	0x69, 0x67, 0x2f, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74,
	0x6f, 0x12, 0x09, 0x73, 0x76, 0x63, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x79, 0x0a, 0x12,
	0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x43, 0x6f, 0x6e, 0x66,
	0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x72, 0x61, 0x6e,
	0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
	0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f,
	0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x70, 0x72, 0x65,
	0x66, 0x69, 0x78, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x79, 0x74, 0x65,
	0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x62, 0x79,
	0x74, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x32, 0x5a, 0x30, 0x67, 0x6f, 0x2e, 0x63, 0x68,
	0x72, 0x6f, 0x6d, 0x69, 0x75, 0x6d, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x6c, 0x75, 0x63, 0x69, 0x2f,
	0x6c, 0x6f, 0x67, 0x64, 0x6f, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
	0x67, 0x2f, 0x73, 0x76, 0x63, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f,
	0x74, 0x6f, 0x33,
}

var (
	file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDescOnce sync.Once
	file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDescData = file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDesc
)

func file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDescGZIP() []byte {
	file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDescOnce.Do(func() {
		file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDescData = protoimpl.X.CompressGZIP(file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDescData)
	})
	return file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDescData
}

var file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_goTypes = []interface{}{
	(*ArchiveIndexConfig)(nil), // 0: svcconfig.ArchiveIndexConfig
}
var file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_depIdxs = []int32{
	0, // [0:0] is the sub-list for method output_type
	0, // [0:0] is the sub-list for method input_type
	0, // [0:0] is the sub-list for extension type_name
	0, // [0:0] is the sub-list for extension extendee
	0, // [0:0] is the sub-list for field type_name
}

func init() { file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_init() }
func file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_init() {
	if File_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto != nil {
		return
	}
	if !protoimpl.UnsafeEnabled {
		file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*ArchiveIndexConfig); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDesc,
			NumEnums:      0,
			NumMessages:   1,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_goTypes,
		DependencyIndexes: file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_depIdxs,
		MessageInfos:      file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_msgTypes,
	}.Build()
	File_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto = out.File
	file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_rawDesc = nil
	file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_goTypes = nil
	file_go_chromium_org_luci_logdog_api_config_svcconfig_archival_proto_depIdxs = nil
}
