Code view:

A painting is a person's account of this edit as text, recorded independently of the node mapping - a rendering often has several equally defensible answers where the mapping has one. Deletions and insertions carry no position on the opposite side in a painting, so that panel draws no caret for them.

Before

1// Copyright 2023 The Cockroach Authors.
2//
3// Use of this software is governed by the CockroachDB Software License
4// included in the /LICENSE file.
5
6package nodelocal
7
8import (
9 "context"
10 "net/url"
11
12 "github.com/cockroachdb/cockroach/pkg/base"
13 "github.com/cockroachdb/cockroach/pkg/blobs"
14 "github.com/cockroachdb/cockroach/pkg/cloud"
15 "github.com/cockroachdb/cockroach/pkg/cloud/cloudpb"
16 "github.com/cockroachdb/cockroach/pkg/settings/cluster"
17 "github.com/cockroachdb/cockroach/pkg/util/buildutil"
18)
19
20// ReplaceNodeLocalForTesting replaces the implementation of of
21// nodelocal with one reads and writes directly from the given
22// directory.
23//
24// The returned func restores the prooduction implementation.
…lines 25–62 unchanged (38 lines)
63 base: es.LocalFileConfig.Path,
64 blobClient: c,
65 settings: settings,
66 uri: es.URI,
67 }
68}
69

After

1// Copyright 2023 The Cockroach Authors.
2//
3// Use of this software is governed by the CockroachDB Software License
4// included in the /LICENSE file.
5
6package nodelocal
7
8import (
9 "context"
10 "io"
11 "net/url"
12
13 "github.com/cockroachdb/cockroach/pkg/base"
14 "github.com/cockroachdb/cockroach/pkg/blobs"
15 "github.com/cockroachdb/cockroach/pkg/cloud"
16 "github.com/cockroachdb/cockroach/pkg/cloud/cloudpb"
17 "github.com/cockroachdb/cockroach/pkg/settings/cluster"
18 "github.com/cockroachdb/cockroach/pkg/util/buildutil"
19 "github.com/cockroachdb/cockroach/pkg/util/ioctx"
20)
21
22// ReplaceNodeLocalForTesting replaces the implementation of of
23// nodelocal with one reads and writes directly from the given
24// directory.
25//
…lines 26–65 unchanged (40 lines)
66 blobClient: c,
67 settings: settings,
68 uri: es.URI,
69 }
70}
71
72// ReplaceNodeLocalForTestingWithInterceptor is like ReplaceNodeLocalForTesting
73// but calls interceptRead before each ReadFile call. The interceptor receives
74// the basename of the file being read. This can be used to inject blocking or
75// delays for specific files, e.g. to block reads of data SSTs during online
76// restore testing. Size calls are not intercepted so that Pebble can still
77// query external file sizes for disk usage accounting.
78func ReplaceNodeLocalForTestingWithInterceptor(
79 root string, interceptRead func(context.Context, string),
80) func() {
81 makeFn := func(ctx context.Context, conf cloud.EarlyBootExternalStorageContext, es cloudpb.ExternalStorage) (cloud.ExternalStorage, error) {
82 inner := TestingMakeNodelocalStorage(root, conf.Settings, es)
83 return &interceptingStorage{inner: inner, interceptRead: interceptRead}, nil
84 }
85 parserFn := func(uri *url.URL) (cloudpb.ExternalStorage, error) {
86 if !buildutil.CrdbTestBuild {
87 panic("nodelocal test implementation in non-test build")
88 }
89 return cloudpb.ExternalStorage{
90 Provider: cloudpb.ExternalStorageProvider_nodelocal,
91 LocalFileConfig: cloudpb.ExternalStorage_LocalFileConfig{
92 Path: uri.Path,
93 },
94 URI: uri.String(),
95 }, nil
96 }
97 return cloud.ReplaceProviderForTesting(cloudpb.ExternalStorageProvider_nodelocal, cloud.RegisteredProvider{
98 EarlyBootConstructFn: makeFn,
99 EarlyBootParseFn: parserFn,
100 Schemes: []string{scheme},
101 })
102}
103
104// interceptingStorage wraps a cloud.ExternalStorage and calls an interceptor
105// before ReadFile operations.
106type interceptingStorage struct {
107 inner cloud.ExternalStorage
108 interceptRead func(context.Context, string)
109}
110
111var _ cloud.ExternalStorage = &interceptingStorage{}
112
113func (s *interceptingStorage) Close() error { return s.inner.Close() }
114func (s *interceptingStorage) Conf() cloudpb.ExternalStorage {
115 return s.inner.Conf()
116}
117func (s *interceptingStorage) ExternalIOConf() base.ExternalIODirConfig {
118 return s.inner.ExternalIOConf()
119}
120func (s *interceptingStorage) RequiresExternalIOAccounting() bool {
121 return s.inner.RequiresExternalIOAccounting()
122}
123func (s *interceptingStorage) Settings() *cluster.Settings {
124 return s.inner.Settings()
125}
126func (s *interceptingStorage) Writer(ctx context.Context, basename string) (io.WriteCloser, error) {
127 return s.inner.Writer(ctx, basename)
128}
129func (s *interceptingStorage) List(
130 ctx context.Context, prefix string, opts cloud.ListOptions, fn cloud.ListingFn,
131) error {
132 return s.inner.List(ctx, prefix, opts, fn)
133}
134func (s *interceptingStorage) Delete(ctx context.Context, basename string) error {
135 return s.inner.Delete(ctx, basename)
136}
137func (s *interceptingStorage) ReadFile(
138 ctx context.Context, basename string, opts cloud.ReadOptions,
139) (ioctx.ReadCloserCtx, int64, error) {
140 s.interceptRead(ctx, basename)
141 return s.inner.ReadFile(ctx, basename, opts)
142}
143func (s *interceptingStorage) Size(ctx context.Context, basename string) (int64, error) {
144 return s.inner.Size(ctx, basename)
145}
146

Before

source_file
comment "// Copyright 2023 The Cockroach Authors."
comment "//"
comment "// Use of this software is governed by the CockroachDB Softw"...
comment "// included in the /LICENSE file."
package_clause
package "package"
package_identifier "nodelocal"
import_declaration
import "import"
import_spec_list
( "("
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "context"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "net/url"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/base"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/blobs"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/cloud"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/cloud/cloudpb"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/settings/cluster"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/util/buildutil"
" "\""
) ")"
comment "// ReplaceNodeLocalForTesting replaces the implementation of"...
comment "// nodelocal with one reads and writes directly from the giv"...
comment "// directory."
comment "//"
comment "// The returned func restores the prooduction implementation"...
function_declaration (+251 nodes collapsed)
comment "// TestingMakeNodelocalStorage constructs a nodelocal storag"...
function_declaration (+160 nodes collapsed)

After

source_file
comment "// Copyright 2023 The Cockroach Authors."
comment "//"
comment "// Use of this software is governed by the CockroachDB Softw"...
comment "// included in the /LICENSE file."
package_clause
package "package"
package_identifier "nodelocal"
import_declaration
import "import"
import_spec_list
( "("
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "context"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "io"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "net/url"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/base"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/blobs"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/cloud"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/cloud/cloudpb"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/settings/cluster"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/util/buildutil"
" "\""
import_spec
interpreted_string_literal
" "\""
interpreted_string_literal_content "github.com/cockroachdb/cockroach/pkg/util/ioctx"
" "\""
) ")"
comment "// ReplaceNodeLocalForTesting replaces the implementation of"...
comment "// nodelocal with one reads and writes directly from the giv"...
comment "// directory."
comment "//"
comment "// The returned func restores the prooduction implementation"...
function_declaration (+251 nodes collapsed)
comment "// TestingMakeNodelocalStorage constructs a nodelocal storag"...
function_declaration (+160 nodes collapsed)
comment "// ReplaceNodeLocalForTestingWithInterceptor is like Replace"...
comment "// but calls interceptRead before each ReadFile call. The in"...
comment "// the basename of the file being read. This can be used to "...
comment "// delays for specific files, e.g. to block reads of data SS"...
comment "// restore testing. Size calls are not intercepted so that P"...
comment "// query external file sizes for disk usage accounting."
function_declaration
func "func"
identifier "ReplaceNodeLocalForTestingWithInterceptor"
parameter_list
( "("
parameter_declaration
identifier "root"
type_identifier "string"
, ","
parameter_declaration
identifier "interceptRead"
function_type
func "func"
parameter_list
( "("
parameter_declaration
qualified_type
package_identifier "context"
. "."
type_identifier "Context"
, ","
parameter_declaration
type_identifier "string"
) ")"
, ","
) ")"
function_type
func "func"
parameter_list
( "("
) ")"
block
{ "{"
statement_list
short_var_declaration
expression_list
identifier "makeFn"
:= ":="
expression_list
func_literal
func "func"
parameter_list
( "("
parameter_declaration
identifier "ctx"
qualified_type
package_identifier "context"
. "."
type_identifier "Context"
, ","
parameter_declaration
identifier "conf"
qualified_type
package_identifier "cloud"
. "."
type_identifier "EarlyBootExternalStorageContext"
, ","
parameter_declaration
identifier "es"
qualified_type
package_identifier "cloudpb"
. "."
type_identifier "ExternalStorage"
) ")"
parameter_list
( "("
parameter_declaration
qualified_type
package_identifier "cloud"
. "."
type_identifier "ExternalStorage"
, ","
parameter_declaration
type_identifier "error"
) ")"
block
{ "{"
statement_list
short_var_declaration
expression_list
identifier "inner"
:= ":="
expression_list
call_expression
identifier "TestingMakeNodelocalStorage"
argument_list
( "("
identifier "root"
, ","
selector_expression
identifier "conf"
. "."
field_identifier "Settings"
, ","
identifier "es"
) ")"
return_statement
return "return"
expression_list
unary_expression
& "&"
composite_literal
type_identifier "interceptingStorage"
literal_value
{ "{"
keyed_element
literal_element
identifier "inner"
: ":"
literal_element
identifier "inner"
, ","
keyed_element
literal_element
identifier "interceptRead"
: ":"
literal_element
identifier "interceptRead"
} "}"
, ","
nil "nil"
} "}"
short_var_declaration
expression_list
identifier "parserFn"
:= ":="
expression_list
func_literal
func "func"
parameter_list
( "("
parameter_declaration
identifier "uri"
pointer_type
* "*"
qualified_type
package_identifier "url"
. "."
type_identifier "URL"
) ")"
parameter_list
( "("
parameter_declaration
qualified_type
package_identifier "cloudpb"
. "."
type_identifier "ExternalStorage"
, ","
parameter_declaration
type_identifier "error"
) ")"
block
{ "{"
statement_list
if_statement
if "if"
unary_expression
! "!"
selector_expression
identifier "buildutil"
. "."
field_identifier "CrdbTestBuild"
block
{ "{"
statement_list
expression_statement
call_expression
identifier "panic"
argument_list
( "("
interpreted_string_literal
" "\""
interpreted_string_literal_content "nodelocal test implementation in non-test build"
" "\""
) ")"
} "}"
return_statement
return "return"
expression_list
composite_literal
qualified_type
package_identifier "cloudpb"
. "."
type_identifier "ExternalStorage"
literal_value
{ "{"
keyed_element
literal_element
identifier "Provider"
: ":"
literal_element
selector_expression
identifier "cloudpb"
. "."
field_identifier "ExternalStorageProvider_nodelocal"
, ","
keyed_element
literal_element
identifier "LocalFileConfig"
: ":"
literal_element
composite_literal
qualified_type
package_identifier "cloudpb"
. "."
type_identifier "ExternalStorage_LocalFileConfig"
literal_value
{ "{"
keyed_element
literal_element
identifier "Path"
: ":"
literal_element
selector_expression
identifier "uri"
. "."
field_identifier "Path"
, ","
} "}"
, ","
keyed_element
literal_element
identifier "URI"
: ":"
literal_element
call_expression
selector_expression
identifier "uri"
. "."
field_identifier "String"
argument_list
( "("
) ")"
, ","
} "}"
, ","
nil "nil"
} "}"
return_statement
return "return"
expression_list
call_expression
selector_expression
identifier "cloud"
. "."
field_identifier "ReplaceProviderForTesting"
argument_list
( "("
selector_expression
identifier "cloudpb"
. "."
field_identifier "ExternalStorageProvider_nodelocal"
, ","
composite_literal
qualified_type
package_identifier "cloud"
. "."
type_identifier "RegisteredProvider"
literal_value
{ "{"
keyed_element
literal_element
identifier "EarlyBootConstructFn"
: ":"
literal_element
identifier "makeFn"
, ","
keyed_element
literal_element
identifier "EarlyBootParseFn"
: ":"
literal_element
identifier "parserFn"
, ","
keyed_element
literal_element
identifier "Schemes"
: ":"
literal_element
composite_literal
slice_type
[ "["
] "]"
type_identifier "string"
literal_value
{ "{"
literal_element
identifier "scheme"
} "}"
, ","
} "}"
) ")"
} "}"
comment "// interceptingStorage wraps a cloud.ExternalStorage and cal"...
comment "// before ReadFile operations."
type_declaration
type "type"
type_spec
type_identifier "interceptingStorage"
struct_type
struct "struct"
field_declaration_list
{ "{"
field_declaration
field_identifier "inner"
qualified_type
package_identifier "cloud"
. "."
type_identifier "ExternalStorage"
field_declaration
field_identifier "interceptRead"
function_type
func "func"
parameter_list
( "("
parameter_declaration
qualified_type
package_identifier "context"
. "."
type_identifier "Context"
, ","
parameter_declaration
type_identifier "string"
) ")"
} "}"
var_declaration
var "var"
var_spec
identifier "_"
qualified_type
package_identifier "cloud"
. "."
type_identifier "ExternalStorage"
= "="
expression_list
unary_expression
& "&"
composite_literal
type_identifier "interceptingStorage"
literal_value
{ "{"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "Close"
parameter_list
( "("
) ")"
type_identifier "error"
block
{ "{"
statement_list
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "Close"
argument_list
( "("
) ")"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "Conf"
parameter_list
( "("
) ")"
qualified_type
package_identifier "cloudpb"
. "."
type_identifier "ExternalStorage"
block
{ "{"
statement_list
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "Conf"
argument_list
( "("
) ")"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "ExternalIOConf"
parameter_list
( "("
) ")"
qualified_type
package_identifier "base"
. "."
type_identifier "ExternalIODirConfig"
block
{ "{"
statement_list
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "ExternalIOConf"
argument_list
( "("
) ")"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "RequiresExternalIOAccounting"
parameter_list
( "("
) ")"
type_identifier "bool"
block
{ "{"
statement_list
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "RequiresExternalIOAccounting"
argument_list
( "("
) ")"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "Settings"
parameter_list
( "("
) ")"
pointer_type
* "*"
qualified_type
package_identifier "cluster"
. "."
type_identifier "Settings"
block
{ "{"
statement_list
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "Settings"
argument_list
( "("
) ")"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "Writer"
parameter_list
( "("
parameter_declaration
identifier "ctx"
qualified_type
package_identifier "context"
. "."
type_identifier "Context"
, ","
parameter_declaration
identifier "basename"
type_identifier "string"
) ")"
parameter_list
( "("
parameter_declaration
qualified_type
package_identifier "io"
. "."
type_identifier "WriteCloser"
, ","
parameter_declaration
type_identifier "error"
) ")"
block
{ "{"
statement_list
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "Writer"
argument_list
( "("
identifier "ctx"
, ","
identifier "basename"
) ")"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "List"
parameter_list
( "("
parameter_declaration
identifier "ctx"
qualified_type
package_identifier "context"
. "."
type_identifier "Context"
, ","
parameter_declaration
identifier "prefix"
type_identifier "string"
, ","
parameter_declaration
identifier "opts"
qualified_type
package_identifier "cloud"
. "."
type_identifier "ListOptions"
, ","
parameter_declaration
identifier "fn"
qualified_type
package_identifier "cloud"
. "."
type_identifier "ListingFn"
, ","
) ")"
type_identifier "error"
block
{ "{"
statement_list
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "List"
argument_list
( "("
identifier "ctx"
, ","
identifier "prefix"
, ","
identifier "opts"
, ","
identifier "fn"
) ")"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "Delete"
parameter_list
( "("
parameter_declaration
identifier "ctx"
qualified_type
package_identifier "context"
. "."
type_identifier "Context"
, ","
parameter_declaration
identifier "basename"
type_identifier "string"
) ")"
type_identifier "error"
block
{ "{"
statement_list
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "Delete"
argument_list
( "("
identifier "ctx"
, ","
identifier "basename"
) ")"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "ReadFile"
parameter_list
( "("
parameter_declaration
identifier "ctx"
qualified_type
package_identifier "context"
. "."
type_identifier "Context"
, ","
parameter_declaration
identifier "basename"
type_identifier "string"
, ","
parameter_declaration
identifier "opts"
qualified_type
package_identifier "cloud"
. "."
type_identifier "ReadOptions"
, ","
) ")"
parameter_list
( "("
parameter_declaration
qualified_type
package_identifier "ioctx"
. "."
type_identifier "ReadCloserCtx"
, ","
parameter_declaration
type_identifier "int64"
, ","
parameter_declaration
type_identifier "error"
) ")"
block
{ "{"
statement_list
expression_statement
call_expression
selector_expression
identifier "s"
. "."
field_identifier "interceptRead"
argument_list
( "("
identifier "ctx"
, ","
identifier "basename"
) ")"
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "ReadFile"
argument_list
( "("
identifier "ctx"
, ","
identifier "basename"
, ","
identifier "opts"
) ")"
} "}"
method_declaration
func "func"
parameter_list
( "("
parameter_declaration
identifier "s"
pointer_type
* "*"
type_identifier "interceptingStorage"
) ")"
field_identifier "Size"
parameter_list
( "("
parameter_declaration
identifier "ctx"
qualified_type
package_identifier "context"
. "."
type_identifier "Context"
, ","
parameter_declaration
identifier "basename"
type_identifier "string"
) ")"
parameter_list
( "("
parameter_declaration
type_identifier "int64"
, ","
parameter_declaration
type_identifier "error"
) ")"
block
{ "{"
statement_list
return_statement
return "return"
expression_list
call_expression
selector_expression
selector_expression
identifier "s"
. "."
field_identifier "inner"
. "."
field_identifier "Size"
argument_list
( "("
identifier "ctx"
, ","
identifier "basename"
) ")"
} "}"