Skip to content

Commit

Permalink
Avoid using go:linkname (#222)
Browse files Browse the repository at this point in the history
* Modify logs

* Avoid using go:linkname to Go std library

* Exclude app/server/conversion/itoa.go from linting
  • Loading branch information
vitalyisaev2 authored Dec 16, 2024
1 parent 360660b commit a93a3b2
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 13 deletions.
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -514,10 +514,13 @@ issues:
- path: ".go"
text: "var-naming: don't use an underscore in package name"


run:
timeout: 5m
skip-dirs:
- test/testdata_etc # test files
- internal/cache # extracted from Go code
- internal/renameio # extracted from Go code
- internal/robustio # extracted from Go code
skip-files:
- app/server/conversion/itoa.go # copied from Go std lib
42 changes: 42 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
NOTICE file for fq-connector-go

This product includes software developed by Yandex LLC and other contributors.
The entire project is licensed under the Apache License, Version 2.0.

===============================================================================

Portions of this product include software licensed under the BSD 3-Clause License.

BSD 3-Clause License:

* ./app/server/conversion/itoa.go:
Copyright (c) 2009 The Go Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the [Original Author/Organization] nor the names of
its contributors may be used to endorse or promote products derived from
this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

===============================================================================

Please see the accompanying LICENSE file for details relating to the Apache License, Version 2.0.
13 changes: 4 additions & 9 deletions app/server/conversion/converters_unsafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,15 @@ func absInt(x int) int {
return x
}

//go:linkname decomposeDate time.(*Time).date
func decomposeDate(*time.Time, bool) (year int, month int, day int, dayOfYear int)

//go:linkname formatBits strconv.formatBits
func formatBits([]byte, uint64, int, bool, bool) (b []byte, s string)

type dateToStringConverterUnsafe struct{}

func (dateToStringConverterUnsafe) Convert(in *time.Time) (string, error) {
buf := make([]byte, 0, 11)

year, month, day, _ := decomposeDate(in, true)

// year
// We used to call the unexported method *Time.date() directly before,
// but since Go 1.23 it's restricted to use go:linkname,
// so now we spend 3x more time here:
year, month, day := in.Year(), in.Month(), in.Day()

if year < 0 {
buf = append(buf, byte('-'))
Expand Down
140 changes: 140 additions & 0 deletions app/server/conversion/itoa.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package conversion

import "math/bits"

const smallsString = "00010203040506070809" +
"10111213141516171819" +
"20212223242526272829" +
"30313233343536373839" +
"40414243444546474849" +
"50515253545556575859" +
"60616263646566676869" +
"70717273747576777879" +
"80818283848586878889" +
"90919293949596979899"

const host32bit = ^uint(0)>>32 == 0

const digits = "0123456789abcdefghijklmnopqrstuvwxyz"

// formatBits computes the string representation of u in the given base.
// If neg is set, u is treated as negative int64 value. If append_ is
// set, the string is appended to dst and the resulting byte slice is
// returned as the first result value; otherwise the string is returned
// as the second result value.
func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) {
if base < 2 || base > len(digits) {
panic("strconv: illegal AppendInt/FormatInt base")
}
// 2 <= base && base <= len(digits)

var a [64 + 1]byte // +1 for sign of 64bit value in base 2
i := len(a)

if neg {
u = -u
}

// convert bits
// We use uint values where we can because those will
// fit into a single register even on a 32bit machine.
if base == 10 {
// common case: use constants for / because
// the compiler can optimize it into a multiply+shift

if host32bit {
// convert the lower digits using 32bit operations
for u >= 1e9 {
// Avoid using r = a%b in addition to q = a/b
// since 64bit division and modulo operations
// are calculated by runtime functions on 32bit machines.
q := u / 1e9
us := uint(u - q*1e9) // u % 1e9 fits into a uint
for j := 4; j > 0; j-- {
is := us % 100 * 2
us /= 100
i -= 2
a[i+1] = smallsString[is+1]
a[i+0] = smallsString[is+0]
}

// us < 10, since it contains the last digit
// from the initial 9-digit us.
i--
a[i] = smallsString[us*2+1]

u = q
}
// u < 1e9
}

// u guaranteed to fit into a uint
us := uint(u)
for us >= 100 {
is := us % 100 * 2
us /= 100
i -= 2
a[i+1] = smallsString[is+1]
a[i+0] = smallsString[is+0]
}

// us < 100
is := us * 2
i--
a[i] = smallsString[is+1]
if us >= 10 {
i--
a[i] = smallsString[is]
}

} else if isPowerOfTwo(base) {
// Use shifts and masks instead of / and %.
shift := uint(bits.TrailingZeros(uint(base)))
b := uint64(base)
m := uint(base) - 1 // == 1<<shift - 1
for u >= b {
i--
a[i] = digits[uint(u)&m]
u >>= shift
}
// u < base
i--
a[i] = digits[uint(u)]
} else {
// general case
b := uint64(base)
for u >= b {
i--
// Avoid using r = a%b in addition to q = a/b
// since 64bit division and modulo operations
// are calculated by runtime functions on 32bit machines.
q := u / b
a[i] = digits[uint(u-q*b)]
u = q
}
// u < base
i--
a[i] = digits[uint(u)]
}

// add sign, if any
if neg {
i--
a[i] = '-'
}

if append_ {
d = append(dst, a[i:]...)
return
}
s = string(a[i:])
return
}

func isPowerOfTwo(x int) bool {
return x&(x-1) == 0
}
14 changes: 10 additions & 4 deletions app/server/datasource/rdbms/ydb/connection_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,24 @@ func (c *connectionManager) Make(
var cred ydb_sdk.Option

if c.cfg.ServiceAccountKeyFileCredentials != "" {
logger.Debug("YDB Connector will use service account key file credentials")
logger.Debug("connector will use service account key file credentials for authorization")

cred = yc.WithServiceAccountKeyFileCredentials(c.cfg.ServiceAccountKeyFileCredentials)
} else if dsi.Credentials.GetToken() != nil {
logger.Debug("connector will use token for authorization")

cred = ydb_sdk.WithAccessTokenCredentials(dsi.Credentials.GetToken().Value)
} else if dsi.Credentials.GetBasic() != nil {
logger.Debug("connector will use base auth credentials for authorization")

cred = ydb_sdk.WithStaticCredentials(dsi.Credentials.GetBasic().Username, dsi.Credentials.GetBasic().Password)
} else {
logger.Warn("connector will not use any credentials for authorization")

cred = ydb_sdk.WithAnonymousCredentials()
}

logger.Debug("Trying to open YDB SDK connection", zap.String("dsn", dsn))
logger.Debug("trying to open YDB SDK connection", zap.String("dsn", dsn))

openCtx, openCtxCancel := context.WithTimeout(ctx, common.MustDurationFromString(c.cfg.OpenConnectionTimeout))
defer openCtxCancel()
Expand Down Expand Up @@ -86,10 +92,10 @@ func (c *connectionManager) Make(
case config.TYdbConfig_MODE_UNSPECIFIED:
fallthrough
case config.TYdbConfig_MODE_QUERY_SERVICE_NATIVE:
logger.Debug("YDB Connector will use Native SDK over Query Service")
logger.Debug("connector will use Native SDK over Query Service")
ydbConn = newConnectionNative(ctx, c.QueryLoggerFactory.Make(logger), dsi, ydbDriver)
case config.TYdbConfig_MODE_TABLE_SERVICE_STDLIB_SCAN_QUERIES:
logger.Debug("YDB Connector will use database/sql SDK with scan queries over Table Service")
logger.Debug("connector will use database/sql SDK with scan queries over Table Service")
ydbConn, err = newConnectionDatabaseSQL(ctx, logger, c.QueryLoggerFactory.Make(logger), c.cfg, dsi, ydbDriver)
default:
return nil, fmt.Errorf("unknown mode: %v", c.cfg.Mode)
Expand Down

0 comments on commit a93a3b2

Please sign in to comment.