diff --git a/Gopkg.lock b/Gopkg.lock index 563485179..128582fbf 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -19,7 +19,7 @@ [[projects]] branch = "master" - digest = "1:599cc68328d92a329d9ec7fd516ed5ac2abfaaafd5f824001adafcb0cf10fe49" + digest = "1:9552f97d556ffa281b8d5c23280aad519e9792a02222cded90467882ff675063" name = "github.com/CovenantSQL/sqlparser" packages = [ ".", @@ -29,7 +29,7 @@ "dependency/sqltypes", ] pruneopts = "UT" - revision = "fb543cee920387ed5e85a2f098eba2dcc12b13c7" + revision = "21a792a5b3b3ecddc9a836fb3da0468f0bd0434f" [[projects]] branch = "master" @@ -443,12 +443,12 @@ source = "github.com/CovenantSQL/go-mysql" [[projects]] - digest = "1:3f53e9e4dfbb664cd62940c9c4b65a2171c66acd0b7621a1a6b8e78513525a52" + digest = "1:69b1cc331fca23d702bd72f860c6a647afd0aa9fcbc1d0659b1365e26546dd70" name = "github.com/sirupsen/logrus" packages = ["."] pruneopts = "UT" - revision = "ad15b42461921f1fb3529b058c6786c6a45d5162" - version = "v1.1.1" + revision = "bcd833dfe83d3cebad139e4a29ed79cb2318bf95" + version = "v1.2.0" [[projects]] digest = "1:cc1c574c9cb5e99b123888c12b828e2d19224ab6c2244bda34647f230bf33243" @@ -606,7 +606,7 @@ "ssh/terminal", ] pruneopts = "UT" - revision = "45a5f77698d342a8c2ef8423abdf0ba6880b008a" + revision = "4d3f4d9ffa16a13f451c3b2999e9c49e9750bf06" [[projects]] branch = "master" @@ -622,18 +622,18 @@ "ipv6", ] pruneopts = "UT" - revision = "c44066c5c816ec500d459a2a324a753f78531ae0" + revision = "b7e296877c6e5e01665044d943c8e6d10ce72a99" [[projects]] branch = "master" - digest = "1:d2605ed96ca0244a457fa8e6c37d5c370ce98ea09dcc21e5e07d967bfcb78878" + digest = "1:417d27a82efb8473554234a282be33d23b0d6adc121e636b55950f913ac071d6" name = "golang.org/x/sys" packages = [ "unix", "windows", ] pruneopts = "UT" - revision = "95b1ffbd15a57cc5abb3f04402b9e8ec0016a52c" + revision = "9b800f95dbbc54abff0acf7ee32d88ba4e328c89" [[projects]] digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202" diff --git a/cleanupDB.sh b/cleanupDB.sh index caf5dc037..ff4110925 100755 --- a/cleanupDB.sh +++ b/cleanupDB.sh @@ -2,10 +2,10 @@ PROJECT_DIR=$(cd $(dirname $0)/; pwd) -cd ${PROJECT_DIR} && find . -name '*.db' -exec rm -f {} \; -cd ${PROJECT_DIR} && find . -name '*.db-shm' -exec rm -f {} \; -cd ${PROJECT_DIR} && find . -name '*.db-wal' -exec rm -f {} \; -cd ${PROJECT_DIR} && find . -name 'db.meta' -exec rm -f {} \; -cd ${PROJECT_DIR} && find . -name 'public.keystore' -exec rm -f {} \; -cd ${PROJECT_DIR} && find . -name '*.public.keystore' -exec rm -f {} \; -cd ${PROJECT_DIR} && find . -type d -name '*.ldb' -prune -exec rm -rf {} \; +cd ${PROJECT_DIR} && find . -name '*.db' -exec rm -vf {} \; +cd ${PROJECT_DIR} && find . -name '*.db-shm' -exec rm -vf {} \; +cd ${PROJECT_DIR} && find . -name '*.db-wal' -exec rm -vf {} \; +cd ${PROJECT_DIR} && find . -name 'db.meta' -exec rm -vf {} \; +cd ${PROJECT_DIR} && find . -name 'public.keystore' -exec rm -vf {} \; +cd ${PROJECT_DIR} && find . -name '*.public.keystore' -exec rm -vf {} \; +cd ${PROJECT_DIR} && find . -type d -name '*.ldb' -prune -exec rm -vrf {} \; diff --git a/client/conn.go b/client/conn.go index a91de5258..74ef9d431 100644 --- a/client/conn.go +++ b/client/conn.go @@ -202,11 +202,16 @@ func (c *conn) ExecContext(ctx context.Context, query string, args []driver.Name // TODO(xq262144): make use of the ctx argument sq := convertQuery(query, args) - if _, err = c.addQuery(wt.WriteQuery, sq); err != nil { + + var affectedRows, lastInsertID int64 + if affectedRows, lastInsertID, _, err = c.addQuery(wt.WriteQuery, sq); err != nil { return } - result = driver.ResultNoRows + result = &execResult{ + affectedRows: affectedRows, + lastInsertID: lastInsertID, + } return } @@ -220,7 +225,9 @@ func (c *conn) QueryContext(ctx context.Context, query string, args []driver.Nam // TODO(xq262144): make use of the ctx argument sq := convertQuery(query, args) - return c.addQuery(wt.ReadQuery, sq) + _, _, rows, err = c.addQuery(wt.ReadQuery, sq) + + return } // Commit implements the driver.Tx.Commit method. @@ -240,7 +247,7 @@ func (c *conn) Commit() (err error) { if len(c.queries) > 0 { // send query - if _, err = c.sendQuery(wt.WriteQuery, c.queries); err != nil { + if _, _, _, err = c.sendQuery(wt.WriteQuery, c.queries); err != nil { return } } @@ -270,7 +277,7 @@ func (c *conn) Rollback() error { return nil } -func (c *conn) addQuery(queryType wt.QueryType, query *wt.Query) (rows driver.Rows, err error) { +func (c *conn) addQuery(queryType wt.QueryType, query *wt.Query) (affectedRows int64, lastInsertID int64, rows driver.Rows, err error) { if c.inTransaction { // check query type, enqueue query if queryType == wt.ReadQuery { @@ -298,7 +305,7 @@ func (c *conn) addQuery(queryType wt.QueryType, query *wt.Query) (rows driver.Ro return c.sendQuery(queryType, []wt.Query{*query}) } -func (c *conn) sendQuery(queryType wt.QueryType, queries []wt.Query) (rows driver.Rows, err error) { +func (c *conn) sendQuery(queryType wt.QueryType, queries []wt.Query) (affectedRows int64, lastInsertID int64, rows driver.Rows, err error) { var peers *kayak.Peers if peers, err = cacheGetPeers(c.dbID, c.privKey); err != nil { return @@ -352,6 +359,11 @@ func (c *conn) sendQuery(queryType wt.QueryType, queries []wt.Query) (rows drive } rows = newRows(&response) + if queryType == wt.WriteQuery { + affectedRows = response.Header.AffectedRows + lastInsertID = response.Header.LastInsertID + } + // build ack c.ackCh <- &wt.Ack{ Header: wt.SignedAckHeader{ diff --git a/client/conn_test.go b/client/conn_test.go index 29022e9e4..c65679210 100644 --- a/client/conn_test.go +++ b/client/conn_test.go @@ -159,10 +159,18 @@ func TestTransaction(t *testing.T) { So(db, ShouldNotBeNil) So(err, ShouldBeNil) + var execResult sql.Result + var lastInsertID, affectedRows int64 + _, err = db.Exec("create table test (test int)") So(err, ShouldBeNil) - _, err = db.Exec("insert into test values (1)") + execResult, err = db.Exec("insert into test values (1)") + So(err, ShouldBeNil) + lastInsertID, err = execResult.LastInsertId() So(err, ShouldBeNil) + So(lastInsertID, ShouldEqual, 1) + affectedRows, err = execResult.RowsAffected() + So(affectedRows, ShouldEqual, 1) // test start transaction var tx *sql.Tx diff --git a/client/result.go b/client/result.go new file mode 100644 index 000000000..5faa21deb --- /dev/null +++ b/client/result.go @@ -0,0 +1,32 @@ +/* + * Copyright 2018 The CovenantSQL Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package client + +type execResult struct { + affectedRows int64 + lastInsertID int64 +} + +// LastInsertId teturn last inserted ID. +func (r *execResult) LastInsertId() (int64, error) { + return r.lastInsertID, nil +} + +// RowsAffected return how many rows affected. +func (r *execResult) RowsAffected() (int64, error) { + return r.affectedRows, nil +} diff --git a/cmd/cql-adapter/api/query.go b/cmd/cql-adapter/api/query.go index aed0b15de..abf0d9fc1 100644 --- a/cmd/cql-adapter/api/query.go +++ b/cmd/cql-adapter/api/query.go @@ -139,10 +139,15 @@ func (a *queryAPI) Write(rw http.ResponseWriter, r *http.Request) { log.WithField("db", dbID).WithField("query", query).Info("got exec") var err error - if err = config.GetConfig().StorageInstance.Exec(dbID, query); err != nil { + var affectedRows int64 + var lastInsertID int64 + if affectedRows, lastInsertID, err = config.GetConfig().StorageInstance.Exec(dbID, query); err != nil { sendResponse(http.StatusInternalServerError, false, err, nil, rw) return } - sendResponse(http.StatusOK, true, nil, nil, rw) + sendResponse(http.StatusOK, true, nil, map[string]interface{}{ + "last_insert_id": lastInsertID, + "affected_rows": affectedRows, + }, rw) } diff --git a/cmd/cql-adapter/storage/covenantsql.go b/cmd/cql-adapter/storage/covenantsql.go index f5847d7b8..e32f0a7ad 100644 --- a/cmd/cql-adapter/storage/covenantsql.go +++ b/cmd/cql-adapter/storage/covenantsql.go @@ -92,14 +92,18 @@ func (s *CovenantSQLStorage) Query(dbID string, query string) (columns []string, } // Exec implements the Storage abstraction interface. -func (s *CovenantSQLStorage) Exec(dbID string, query string) (err error) { +func (s *CovenantSQLStorage) Exec(dbID string, query string) (affectedRows int64, lastInsertID int64, err error) { var conn *sql.DB if conn, err = s.getConn(dbID); err != nil { return } defer conn.Close() - _, err = conn.Exec(query) + var result sql.Result + result, err = conn.Exec(query) + + affectedRows, _ = result.RowsAffected() + lastInsertID, _ = result.LastInsertId() return } diff --git a/cmd/cql-adapter/storage/sqlite3.go b/cmd/cql-adapter/storage/sqlite3.go index f3a80f1af..aac13f94d 100644 --- a/cmd/cql-adapter/storage/sqlite3.go +++ b/cmd/cql-adapter/storage/sqlite3.go @@ -115,14 +115,18 @@ func (s *SQLite3Storage) Query(dbID string, query string) (columns []string, typ } // Exec implements the Storage abstraction interface. -func (s *SQLite3Storage) Exec(dbID string, query string) (err error) { +func (s *SQLite3Storage) Exec(dbID string, query string) (affectedRows int64, lastInsertID int64, err error) { var conn *sql.DB if conn, err = s.getConn(dbID, false); err != nil { return } defer conn.Close() - _, err = conn.Exec(query) + var result sql.Result + result, err = conn.Exec(query) + + affectedRows, _ = result.RowsAffected() + lastInsertID, _ = result.LastInsertId() return } diff --git a/cmd/cql-adapter/storage/storage.go b/cmd/cql-adapter/storage/storage.go index f10640166..c35dbfbfa 100644 --- a/cmd/cql-adapter/storage/storage.go +++ b/cmd/cql-adapter/storage/storage.go @@ -30,7 +30,7 @@ type Storage interface { // Query for result. Query(dbID string, query string) (columns []string, types []string, rows [][]interface{}, err error) // Exec for update. - Exec(dbID string, query string) (err error) + Exec(dbID string, query string) (affectedRows int64, lastInsertID int64, err error) } // golang does trick convert, use rowScanner to return the original result type in sqlite3 driver diff --git a/cmd/cqld/adapter.go b/cmd/cqld/adapter.go index af8d5ad4c..c8b4c442a 100644 --- a/cmd/cqld/adapter.go +++ b/cmd/cqld/adapter.go @@ -94,13 +94,14 @@ func (s *LocalStorage) Prepare(ctx context.Context, wb twopc.WriteBatch) (err er } // Commit implements twopc Worker.Commit -func (s *LocalStorage) Commit(ctx context.Context, wb twopc.WriteBatch) (err error) { +func (s *LocalStorage) Commit(ctx context.Context, wb twopc.WriteBatch) (_ interface{}, err error) { payload, err := s.decodeLog(wb) if err != nil { log.WithError(err).Error("decode log failed") return } - return s.commit(ctx, payload) + err = s.commit(ctx, payload) + return } func (s *LocalStorage) commit(ctx context.Context, payload *KayakPayload) (err error) { @@ -132,7 +133,8 @@ func (s *LocalStorage) commit(ctx context.Context, payload *KayakPayload) (err e s.consistent.AddCache(nodeToSet) } - return s.Storage.Commit(ctx, execLog) + _, err = s.Storage.Commit(ctx, execLog) + return } // Rollback implements twopc Worker.Rollback @@ -300,7 +302,7 @@ func (s *KayakKVServer) SetNode(node *proto.Node) (err error) { return err } - _, err = s.Runtime.Apply(writeData.Bytes()) + _, _, err = s.Runtime.Apply(writeData.Bytes()) if err != nil { log.Errorf("Apply set node failed: %#v\nPayload:\n %#v", err, writeData) } @@ -371,7 +373,7 @@ func (s *KayakKVServer) SetDatabase(meta wt.ServiceInstance) (err error) { return err } - _, err = s.Runtime.Apply(writeData.Bytes()) + _, _, err = s.Runtime.Apply(writeData.Bytes()) if err != nil { log.Errorf("Apply set database failed: %#v\nPayload:\n %#v", err, writeData) } @@ -400,7 +402,7 @@ func (s *KayakKVServer) DeleteDatabase(dbID proto.DatabaseID) (err error) { return err } - _, err = s.Runtime.Apply(writeData.Bytes()) + _, _, err = s.Runtime.Apply(writeData.Bytes()) if err != nil { log.Errorf("Apply set database failed: %#v\nPayload:\n %#v", err, writeData) } diff --git a/kayak/api/twopc_integ_test.go b/kayak/api/twopc_integ_test.go index 1fa52ab38..7014a810e 100644 --- a/kayak/api/twopc_integ_test.go +++ b/kayak/api/twopc_integ_test.go @@ -47,22 +47,31 @@ type MockWorker struct { } // Commit provides a mock function with given fields: ctx, wb -func (_m *MockWorker) Commit(ctx context.Context, wb twopc.WriteBatch) error { - ret := _m.Called(ctx, wb) +func (_m *MockWorker) Commit(ctx context.Context, wb twopc.WriteBatch) (interface{}, error) { + ret := _m.Called(context.Background(), wb) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) error); ok { + var r0 interface{} + if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) interface{}); ok { r0 = rf(ctx, wb) } else { - r0 = ret.Error(0) + if ret.Get(0) != nil { + r0 = ret.Get(0).(interface{}) + } } - return r0 + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, twopc.WriteBatch) error); ok { + r1 = rf(ctx, wb) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // Prepare provides a mock function with given fields: ctx, wb func (_m *MockWorker) Prepare(ctx context.Context, wb twopc.WriteBatch) error { - ret := _m.Called(ctx, wb) + ret := _m.Called(context.Background(), wb) var r0 error if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) error); ok { @@ -76,7 +85,7 @@ func (_m *MockWorker) Prepare(ctx context.Context, wb twopc.WriteBatch) error { // Rollback provides a mock function with given fields: ctx, wb func (_m *MockWorker) Rollback(ctx context.Context, wb twopc.WriteBatch) error { - ret := _m.Called(ctx, wb) + ret := _m.Called(context.Background(), wb) var r0 error if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) error); ok { @@ -295,27 +304,27 @@ func TestExampleTwoPCCommit(t *testing.T) { callOrder := &CallCollector{} f1Mock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f2Mock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f1Mock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) f2Mock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) lMock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_prepare") + callOrder.Append("prepare") }) lMock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) // start server @@ -337,28 +346,28 @@ func TestExampleTwoPCCommit(t *testing.T) { }() // process the encoded data - _, err = lMock.runtime.Apply(testPayload) + _, _, err = lMock.runtime.Apply(testPayload) So(err, ShouldBeNil) So(callOrder.Get(), ShouldResemble, []string{ - "f_prepare", - "f_prepare", - "l_prepare", - "f_commit", - "f_commit", - "l_commit", + "prepare", + "prepare", + "prepare", + "commit", + "commit", + "commit", }) // process the encoded data again callOrder.Reset() - _, err = lMock.runtime.Apply(testPayload) + _, _, err = lMock.runtime.Apply(testPayload) So(err, ShouldBeNil) So(callOrder.Get(), ShouldResemble, []string{ - "f_prepare", - "f_prepare", - "l_prepare", - "f_commit", - "f_commit", - "l_commit", + "prepare", + "prepare", + "prepare", + "commit", + "commit", + "commit", }) // shutdown diff --git a/kayak/mock_Runner_test.go b/kayak/mock_Runner_test.go index 34ccefb6f..66706324d 100644 --- a/kayak/mock_Runner_test.go +++ b/kayak/mock_Runner_test.go @@ -10,24 +10,33 @@ type MockRunner struct { } // Apply provides a mock function with given fields: data -func (_m *MockRunner) Apply(data []byte) (uint64, error) { +func (_m *MockRunner) Apply(data []byte) (interface{}, uint64, error) { ret := _m.Called(data) - var r0 uint64 - if rf, ok := ret.Get(0).(func([]byte) uint64); ok { + var r0 interface{} + if rf, ok := ret.Get(0).(func([]byte) interface{}); ok { r0 = rf(data) } else { - r0 = ret.Get(0).(uint64) + if ret.Get(0) != nil { + r0 = ret.Get(0).(interface{}) + } } - var r1 error - if rf, ok := ret.Get(1).(func([]byte) error); ok { + var r1 uint64 + if rf, ok := ret.Get(1).(func([]byte) uint64); ok { r1 = rf(data) } else { - r1 = ret.Error(1) + r1 = ret.Get(1).(uint64) } - return r0, r1 + var r2 error + if rf, ok := ret.Get(2).(func([]byte) error); ok { + r2 = rf(data) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 } // Init provides a mock function with given fields: config, peers, logs, stable, transport diff --git a/kayak/mock_Worker_test.go b/kayak/mock_Worker_test.go index 07b94afd6..b6dcc5e2e 100644 --- a/kayak/mock_Worker_test.go +++ b/kayak/mock_Worker_test.go @@ -30,22 +30,31 @@ type MockWorker struct { } // Commit provides a mock function with given fields: ctx, wb -func (_m *MockWorker) Commit(ctx context.Context, wb twopc.WriteBatch) error { - ret := _m.Called(ctx, wb) +func (_m *MockWorker) Commit(ctx context.Context, wb twopc.WriteBatch) (interface{}, error) { + ret := _m.Called(context.Background(), wb) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) error); ok { + var r0 interface{} + if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) interface{}); ok { r0 = rf(ctx, wb) } else { - r0 = ret.Error(0) + if ret.Get(0) != nil { + r0 = ret.Get(0).(interface{}) + } } - return r0 + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, twopc.WriteBatch) error); ok { + r1 = rf(ctx, wb) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // Prepare provides a mock function with given fields: ctx, wb func (_m *MockWorker) Prepare(ctx context.Context, wb twopc.WriteBatch) error { - ret := _m.Called(ctx, wb) + ret := _m.Called(context.Background(), wb) var r0 error if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) error); ok { @@ -59,7 +68,7 @@ func (_m *MockWorker) Prepare(ctx context.Context, wb twopc.WriteBatch) error { // Rollback provides a mock function with given fields: ctx, wb func (_m *MockWorker) Rollback(ctx context.Context, wb twopc.WriteBatch) error { - ret := _m.Called(ctx, wb) + ret := _m.Called(context.Background(), wb) var r0 error if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) error); ok { diff --git a/kayak/mock_kayak_test.go b/kayak/mock_kayak_test.go index 08b4121c2..d3ca04405 100644 --- a/kayak/mock_kayak_test.go +++ b/kayak/mock_kayak_test.go @@ -210,20 +210,20 @@ func (w *MockTwoPCWorker) Prepare(ctx context.Context, wb twopc.WriteBatch) erro return nil } -func (w *MockTwoPCWorker) Commit(ctx context.Context, wb twopc.WriteBatch) error { +func (w *MockTwoPCWorker) Commit(ctx context.Context, wb twopc.WriteBatch) (interface{}, error) { // test commit if w.state != "prepared" { - return errors.New("invalid state") + return nil, errors.New("invalid state") } if !reflect.DeepEqual(wb, w.data) { - return errors.New("commit data not same as last") + return nil, errors.New("commit data not same as last") } w.total += w.data w.state = "" - return nil + return nil, nil } func (w *MockTwoPCWorker) Rollback(ctx context.Context, wb twopc.WriteBatch) error { diff --git a/kayak/runtime.go b/kayak/runtime.go index 68213698b..3f300bacd 100644 --- a/kayak/runtime.go +++ b/kayak/runtime.go @@ -119,15 +119,15 @@ func (r *Runtime) Shutdown() (err error) { } // Apply defines common process logic. -func (r *Runtime) Apply(data []byte) (offset uint64, err error) { +func (r *Runtime) Apply(data []byte) (result interface{}, offset uint64, err error) { // validate if myself is leader if !r.isLeader { - return 0, ErrNotLeader + return nil, 0, ErrNotLeader } - offset, err = r.config.Runner.Apply(data) + result, offset, err = r.config.Runner.Apply(data) if err != nil { - return 0, err + return nil, 0, err } return diff --git a/kayak/runtime_test.go b/kayak/runtime_test.go index b0735744a..d704b9fa0 100644 --- a/kayak/runtime_test.go +++ b/kayak/runtime_test.go @@ -187,9 +187,9 @@ func TestRuntimeAll(t *testing.T) { So(r.logStore, ShouldNotBeNil) // run process - runner.On("Apply", mock.Anything).Return(uint64(1), nil) + runner.On("Apply", mock.Anything).Return(nil, uint64(1), nil) - _, err = r.Apply([]byte("test")) + _, _, err = r.Apply([]byte("test")) So(err, ShouldBeNil) // test get log @@ -245,13 +245,13 @@ func TestRuntimeAll(t *testing.T) { ).Return(nil) runner.On("Shutdown", mock.Anything). Return(nil) - runner.On("Apply", mock.Anything).Return(uint64(1), nil) + runner.On("Apply", mock.Anything).Return(nil, uint64(1), nil) err = r.Init() So(err, ShouldBeNil) defer r.Shutdown() - _, err = r.Apply([]byte("test")) + _, _, err = r.Apply([]byte("test")) So(err, ShouldNotBeNil) So(err, ShouldEqual, ErrNotLeader) }) diff --git a/kayak/transport/etls_transport_test.go b/kayak/transport/etls_transport_test.go index 61eb385a8..98e0283cd 100644 --- a/kayak/transport/etls_transport_test.go +++ b/kayak/transport/etls_transport_test.go @@ -281,52 +281,52 @@ func TestETLSIntegration(t *testing.T) { callOrder := &CallCollector{} f1Mock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f2Mock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f1Mock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) f2Mock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) lMock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_prepare") + callOrder.Append("prepare") }) lMock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) // process the encoded data - _, err = lMock.runtime.Apply(testPayload) + _, _, err = lMock.runtime.Apply(testPayload) So(err, ShouldBeNil) So(callOrder.Get(), ShouldResemble, []string{ - "f_prepare", - "f_prepare", - "l_prepare", - "f_commit", - "f_commit", - "l_commit", + "prepare", + "prepare", + "prepare", + "commit", + "commit", + "commit", }) // process the encoded data again callOrder.Reset() - _, err = lMock.runtime.Apply(testPayload) + _, _, err = lMock.runtime.Apply(testPayload) So(err, ShouldBeNil) So(callOrder.Get(), ShouldResemble, []string{ - "f_prepare", - "f_prepare", - "l_prepare", - "f_commit", - "f_commit", - "l_commit", + "prepare", + "prepare", + "prepare", + "commit", + "commit", + "commit", }) // shutdown diff --git a/kayak/transport/network_transport_test.go b/kayak/transport/network_transport_test.go index 9ed230f68..e797032c0 100644 --- a/kayak/transport/network_transport_test.go +++ b/kayak/transport/network_transport_test.go @@ -118,22 +118,31 @@ type MockWorker struct { } // Commit provides a mock function with given fields: ctx, wb -func (_m *MockWorker) Commit(ctx context.Context, wb twopc.WriteBatch) error { - ret := _m.Called(ctx, wb) +func (_m *MockWorker) Commit(ctx context.Context, wb twopc.WriteBatch) (interface{}, error) { + ret := _m.Called(context.Background(), wb) - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) error); ok { + var r0 interface{} + if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) interface{}); ok { r0 = rf(ctx, wb) } else { - r0 = ret.Error(0) + if ret.Get(0) != nil { + r0 = ret.Get(0).(interface{}) + } } - return r0 + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, twopc.WriteBatch) error); ok { + r1 = rf(ctx, wb) + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // Prepare provides a mock function with given fields: ctx, wb func (_m *MockWorker) Prepare(ctx context.Context, wb twopc.WriteBatch) error { - ret := _m.Called(ctx, wb) + ret := _m.Called(context.Background(), wb) var r0 error if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) error); ok { @@ -147,7 +156,7 @@ func (_m *MockWorker) Prepare(ctx context.Context, wb twopc.WriteBatch) error { // Rollback provides a mock function with given fields: ctx, wb func (_m *MockWorker) Rollback(ctx context.Context, wb twopc.WriteBatch) error { - ret := _m.Called(ctx, wb) + ret := _m.Called(context.Background(), wb) var r0 error if rf, ok := ret.Get(0).(func(context.Context, twopc.WriteBatch) error); ok { @@ -398,52 +407,52 @@ func TestIntegration(t *testing.T) { callOrder := &CallCollector{} f1Mock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f2Mock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f1Mock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) f2Mock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) lMock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_prepare") + callOrder.Append("prepare") }) lMock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) // process the encoded data - _, err = lMock.runtime.Apply(testPayload) + _, _, err = lMock.runtime.Apply(testPayload) So(err, ShouldBeNil) So(callOrder.Get(), ShouldResemble, []string{ - "f_prepare", - "f_prepare", - "l_prepare", - "f_commit", - "f_commit", - "l_commit", + "prepare", + "prepare", + "prepare", + "commit", + "commit", + "commit", }) // process the encoded data again callOrder.Reset() - _, err = lMock.runtime.Apply(testPayload) + _, _, err = lMock.runtime.Apply(testPayload) So(err, ShouldBeNil) So(callOrder.Get(), ShouldResemble, []string{ - "f_prepare", - "f_prepare", - "l_prepare", - "f_commit", - "f_commit", - "l_commit", + "prepare", + "prepare", + "prepare", + "commit", + "commit", + "commit", }) // shutdown diff --git a/kayak/twopc_runner.go b/kayak/twopc_runner.go index 3f9c75069..e49f27ff7 100644 --- a/kayak/twopc_runner.go +++ b/kayak/twopc_runner.go @@ -17,15 +17,16 @@ package kayak import ( + "bytes" "context" "fmt" "runtime/trace" "sync" - "time" "github.com/CovenantSQL/CovenantSQL/crypto/hash" "github.com/CovenantSQL/CovenantSQL/proto" "github.com/CovenantSQL/CovenantSQL/twopc" + "github.com/CovenantSQL/CovenantSQL/utils" "github.com/CovenantSQL/CovenantSQL/utils/log" ) @@ -46,6 +47,7 @@ type TwoPCConfig struct { } type logProcessResult struct { + result interface{} offset uint64 err error } @@ -279,17 +281,17 @@ func (r *TwoPCRunner) UpdatePeers(peers *Peers) error { } // Apply implements Runner.Apply. -func (r *TwoPCRunner) Apply(data []byte) (uint64, error) { +func (r *TwoPCRunner) Apply(data []byte) (result interface{}, offset uint64, err error) { // check leader privilege if r.role != proto.Leader { - return 0, ErrNotLeader + return nil, 0, ErrNotLeader } //TODO(auxten): need throughput optimization r.processReq <- data res := <-r.processRes - return res.offset, res.err + return res.result, res.offset, res.err } // Shutdown implements Runner.Shutdown. @@ -367,8 +369,8 @@ func (r *TwoPCRunner) processNewLog(data []byte) (res logProcessResult) { return r.config.Storage.Rollback(ctx, l.Data) } - localCommit := func(ctx context.Context) (err error) { - err = r.config.Storage.Commit(ctx, l.Data) + localCommit := func(ctx context.Context) (result interface{}, err error) { + result, err = r.config.Storage.Commit(ctx, l.Data) r.stableStore.SetUint64(keyCommittedIndex, l.Index) r.lastLogHash = &l.Hash @@ -380,7 +382,12 @@ func (r *TwoPCRunner) processNewLog(data []byte) (res logProcessResult) { // build 2PC workers if len(r.peers.Servers) > 1 { - nodes := make([]twopc.Worker, 0, len(r.peers.Servers)-1) + nodes := make([]twopc.Worker, 0, len(r.peers.Servers)) + nodes = append(nodes, newLocalWrapper( + localPrepare, + localRollback, + localCommit, + )) for _, s := range r.peers.Servers { if s.ID != r.config.LocalID { @@ -389,15 +396,8 @@ func (r *TwoPCRunner) processNewLog(data []byte) (res logProcessResult) { } // start coordination - c := twopc.NewCoordinator(twopc.NewOptionsWithCallback( - r.config.ProcessTimeout, - nil, - localPrepare, // after all remote nodes prepared - localRollback, // before all remote nodes rollback - localCommit, // after all remote nodes commit - )) - - res.err = c.Put(nodes, l) + c := twopc.NewCoordinator(twopc.NewOptions(r.config.ProcessTimeout)) + res.result, res.err = c.Put(nodes, l) res.offset = r.lastLogIndex } else { // single node short cut @@ -413,7 +413,7 @@ func (r *TwoPCRunner) processNewLog(data []byte) (res logProcessResult) { // Commit myself // return commit err but still commit - res.err = localCommit(ctx) + res.result, res.err = localCommit(ctx) res.offset = r.lastLogIndex } @@ -517,6 +517,7 @@ func (r *TwoPCRunner) processPrepare(req Request) { if r.getState() != Idle { // TODO(xq262144): has running transaction // TODO(xq262144): abort previous or failed current + log.Warning("runner status not available for new prepare request") } // init context @@ -527,6 +528,7 @@ func (r *TwoPCRunner) processPrepare(req Request) { // get log var l *Log if l, err = r.verifyLog(req); err != nil { + log.WithError(err).Debug("verify log failed") return } @@ -534,33 +536,51 @@ func (r *TwoPCRunner) processPrepare(req Request) { var lastIndex uint64 if lastIndex, err = r.logStore.LastIndex(); err != nil || lastIndex >= l.Index { // already prepared or failed + log.WithFields(log.Fields{ + "lastIndex": lastIndex, + "index": l.Index, + }).WithError(err).Debug("check log existence failed") + return } // check prepare hash with last log hash if l.LastHash != nil && lastIndex == 0 { // invalid - return ErrInvalidLog + err = ErrInvalidLog + log.WithFields(log.Fields{ + "lastIndex": lastIndex, + "hash": l.LastHash, + }).WithError(err).Debug("invalid log parent hash") + return } if lastIndex > 0 { var lastLog Log if err = r.logStore.GetLog(lastIndex, &lastLog); err != nil { + log.WithError(err).Debug("get last log failed") return } if !l.LastHash.IsEqual(&lastLog.Hash) { - return ErrInvalidLog + err = ErrInvalidLog + log.WithFields(log.Fields{ + "expected": lastLog.Hash, + "actual": l.LastHash, + }).WithError(err).Debug("parent hash not matched") + return } } // prepare on storage if err = r.config.Storage.Prepare(r.currentContext, l.Data); err != nil { + log.WithError(err).Debug("call storage prepare failed") return } // write log to storage if err = r.logStore.StoreLog(l); err != nil { + log.WithError(err).Debug("record log to log storage failed") return } @@ -573,41 +593,71 @@ func (r *TwoPCRunner) processPrepare(req Request) { func (r *TwoPCRunner) processCommit(req Request) { // commit log - req.SendResponse(nil, func() (err error) { + req.SendResponse(func() (resp []byte, err error) { // TODO(xq262144): check current running transaction index if r.getState() != Prepared { // not prepared, failed directly - return ErrInvalidRequest + err = ErrInvalidRequest + log.WithError(err).Warning("runner status not prepared to commit") + return } // get log var l *Log if l, err = r.verifyLog(req); err != nil { + log.WithError(err).Debug("verify log failed") return } var lastIndex uint64 if lastIndex, err = r.logStore.LastIndex(); err != nil { + log.WithError(err).Debug("get last log index failed") return } else if lastIndex < l.Index { // not logged, need re-prepare - return ErrInvalidLog + err = ErrInvalidLog + log.WithFields(log.Fields{ + "lastIndex": lastIndex, + "index": l.Index, + }).WithError(err).Debug("check log index correctness failed") + return } if r.lastLogIndex+1 != l.Index { // not at the head of the commit position - return ErrInvalidLog + err = ErrInvalidLog + log.WithFields(log.Fields{ + "lastLogIndex": r.lastLogIndex, + "index": l.Index, + }).WithError(err).Debug("check log index correctness failed") + return } // get log var lastLog Log if err = r.logStore.GetLog(l.Index, &lastLog); err != nil { + log.WithError(err).Debug("get last log failed") return } // commit on storage // return err but still commit local index - err = r.config.Storage.Commit(r.currentContext, l.Data) + var respData interface{} + respData, err = r.config.Storage.Commit(r.currentContext, l.Data) + + // encode response + if err == nil { + var encodeBuf *bytes.Buffer + if encodeBuf, err = utils.EncodeMsgPack(respData); err == nil { + resp = encodeBuf.Bytes() + } else { + log.WithError(err).Warning("encode response failed") + // clear error + err = nil + } + } else { + log.WithError(err).Warning("call storage commit failed") + } // commit log r.stableStore.SetUint64(keyCommittedIndex, l.Index) @@ -628,36 +678,51 @@ func (r *TwoPCRunner) processRollback(req Request) { // TODO(xq262144): check current running transaction index if r.getState() != Prepared { // not prepared, failed directly - return ErrInvalidRequest + err = ErrInvalidRequest + log.WithError(err).Warning("runner status not prepared to rollback") + return } // get log var l *Log if l, err = r.verifyLog(req); err != nil { + log.WithError(err).Debug("verify log failed") return } var lastIndex uint64 if lastIndex, err = r.logStore.LastIndex(); err != nil { + log.WithError(err).Debug("get last log index failed") return } else if lastIndex < l.Index { // not logged, no rollback required, maybe previous initiated rollback + log.WithFields(log.Fields{ + "lastIndex": lastIndex, + "index": l.Index, + }).Debug("index beyond max index, rollback request ignored") return } if r.lastLogIndex+1 != l.Index { // not at the head of the commit position - return ErrInvalidLog + err = ErrInvalidLog + log.WithFields(log.Fields{ + "lastLogIndex": r.lastLogIndex, + "index": l.Index, + }).WithError(err).Debug("check log index correctness failed") + return } // get log var lastLog Log if err = r.logStore.GetLog(l.Index, &lastLog); err != nil { + log.WithError(err).Debug("get last log failed") return } // rollback on storage if err = r.config.Storage.Rollback(r.currentContext, l.Data); err != nil { + log.WithError(err).Warning("call storage rollback failed") return } @@ -681,6 +746,35 @@ func (r *TwoPCRunner) goFunc(f func()) { }() } +type localFunc func(context.Context) error +type localCommitFunc func(context.Context) (interface{}, error) + +type localWrapper struct { + prepare localFunc + rollback localFunc + commit localCommitFunc +} + +func newLocalWrapper(prepare localFunc, rollback localFunc, commit localCommitFunc) *localWrapper { + return &localWrapper{ + prepare: prepare, + rollback: rollback, + commit: commit, + } +} + +func (lw *localWrapper) Prepare(ctx context.Context, _ twopc.WriteBatch) error { + return lw.prepare(ctx) +} + +func (lw *localWrapper) Commit(ctx context.Context, _ twopc.WriteBatch) (interface{}, error) { + return lw.commit(ctx) +} + +func (lw *localWrapper) Rollback(ctx context.Context, _ twopc.WriteBatch) error { + return lw.rollback(ctx) +} + // NewTwoPCWorkerWrapper returns a wrapper for remote worker. func NewTwoPCWorkerWrapper(runner *TwoPCRunner, nodeID proto.NodeID) *TwoPCWorkerWrapper { return &TwoPCWorkerWrapper{ @@ -697,15 +791,16 @@ func (tpww *TwoPCWorkerWrapper) Prepare(ctx context.Context, wb twopc.WriteBatch return ErrInvalidLog } - return tpww.callRemote(ctx, "Prepare", l) + _, err := tpww.callRemote(ctx, "Prepare", l) + return err } // Commit implements twopc.Worker.Commit. -func (tpww *TwoPCWorkerWrapper) Commit(ctx context.Context, wb twopc.WriteBatch) error { +func (tpww *TwoPCWorkerWrapper) Commit(ctx context.Context, wb twopc.WriteBatch) (interface{}, error) { // extract log l, ok := wb.(*Log) if !ok { - return ErrInvalidLog + return nil, ErrInvalidLog } return tpww.callRemote(ctx, "Commit", l) @@ -719,19 +814,12 @@ func (tpww *TwoPCWorkerWrapper) Rollback(ctx context.Context, wb twopc.WriteBatc return ErrInvalidLog } - return tpww.callRemote(ctx, "Rollback", l) -} - -func (tpww *TwoPCWorkerWrapper) callRemote(ctx context.Context, method string, log *Log) (err error) { - // TODO(xq262144): handle retry - _, err = tpww.runner.transport.Request(ctx, tpww.nodeID, method, log) - return + _, err := tpww.callRemote(ctx, "Rollback", l) + return err } -func nestedTimeoutCtx(ctx context.Context, timeout time.Duration, process func(context.Context) error) error { - nestedCtx, cancel := context.WithTimeout(ctx, timeout) - defer cancel() - return process(nestedCtx) +func (tpww *TwoPCWorkerWrapper) callRemote(ctx context.Context, method string, log *Log) (res []byte, err error) { + return tpww.runner.transport.Request(ctx, tpww.nodeID, method, log) } var ( diff --git a/kayak/twopc_runner_test.go b/kayak/twopc_runner_test.go index c7fd5e839..1423db66d 100644 --- a/kayak/twopc_runner_test.go +++ b/kayak/twopc_runner_test.go @@ -24,6 +24,7 @@ import ( "time" "github.com/CovenantSQL/CovenantSQL/proto" + "github.com/CovenantSQL/CovenantSQL/twopc" "github.com/CovenantSQL/CovenantSQL/utils/log" . "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/mock" @@ -280,7 +281,7 @@ func TestTwoPCRunner_Apply(t *testing.T) { // try call process testPayload := []byte("test data") - _, err = mockRes.runner.Apply(testPayload) + _, _, err = mockRes.runner.Apply(testPayload) So(err, ShouldNotBeNil) So(err, ShouldEqual, ErrNotLeader) }) @@ -317,7 +318,7 @@ func TestTwoPCRunner_Apply(t *testing.T) { callOrder.Append("store_log") }) mockRes.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { + Return(nil, nil).Run(func(args mock.Arguments) { callOrder.Append("commit") }) mockRes.stableStore.On("SetUint64", keyCommittedIndex, uint64(1)). @@ -327,7 +328,7 @@ func TestTwoPCRunner_Apply(t *testing.T) { // try call process var offset uint64 - offset, err = mockRes.runner.Apply(testPayload) + _, offset, err = mockRes.runner.Apply(testPayload) So(err, ShouldBeNil) So(offset, ShouldEqual, uint64(1)) @@ -364,7 +365,7 @@ func TestTwoPCRunner_Apply(t *testing.T) { }) // try call process - _, err = mockRes.runner.Apply(testPayload) + _, _, err = mockRes.runner.Apply(testPayload) So(err, ShouldNotBeNil) // no log should be written to local log store after failed preparing @@ -380,15 +381,15 @@ func TestTwoPCRunner_Apply(t *testing.T) { testPayload := []byte("test data") unknownErr := errors.New("unknown error") mockRes.worker.On("Prepare", mock.Anything, testPayload). - Return(unknownErr).After(time.Millisecond * 400).Run(func(args mock.Arguments) { - ctx := args.Get(0).(context.Context) - c.So(ctx.Err(), ShouldNotBeNil) - }) + Return(func(ctx context.Context, _ twopc.WriteBatch) error { + c.So(ctx.Err(), ShouldNotBeNil) + return unknownErr + }).After(time.Millisecond * 400) mockRes.worker.On("Rollback", mock.Anything, testPayload).Return(nil) mockRes.logStore.On("DeleteRange", uint64(1), uint64(1)).Return(nil) // try call process - _, err = mockRes.runner.Apply(testPayload) + _, _, err = mockRes.runner.Apply(testPayload) So(err, ShouldNotBeNil) }) @@ -401,15 +402,15 @@ func TestTwoPCRunner_Apply(t *testing.T) { mockRes.logStore.On("StoreLog", mock.AnythingOfType("*kayak.Log")). Return(nil) mockRes.worker.On("Commit", mock.Anything, testPayload). - Return(unknownErr).After(time.Millisecond * 400).Run(func(args mock.Arguments) { - ctx := args.Get(0).(context.Context) - c.So(ctx.Err(), ShouldNotBeNil) - }) + Return(nil, func(ctx context.Context, _ twopc.WriteBatch) error { + c.So(ctx.Err(), ShouldNotBeNil) + return unknownErr + }).After(time.Millisecond * 400) mockRes.stableStore.On("SetUint64", keyCommittedIndex, uint64(1)). Return(nil) // try call process - _, err = mockRes.runner.Apply(testPayload) + _, _, err = mockRes.runner.Apply(testPayload) So(err, ShouldNotBeNil) }) @@ -423,14 +424,14 @@ func TestTwoPCRunner_Apply(t *testing.T) { mockRes.logStore.On("StoreLog", mock.AnythingOfType("*kayak.Log")). Return(nil) mockRes.worker.On("Rollback", mock.Anything, testPayload). - Return(rollbackErr).After(time.Millisecond * 400).Run(func(args mock.Arguments) { - ctx := args.Get(0).(context.Context) - c.So(ctx.Err(), ShouldNotBeNil) - }) + Return(func(ctx context.Context, _ twopc.WriteBatch) error { + c.So(ctx.Err(), ShouldNotBeNil) + return rollbackErr + }).After(time.Millisecond * 400) mockRes.logStore.On("DeleteRange", uint64(1), uint64(1)).Return(nil) // try call process - _, err = mockRes.runner.Apply(testPayload) + _, _, err = mockRes.runner.Apply(testPayload) // rollback error is ignored So(err, ShouldNotBeNil) @@ -476,42 +477,42 @@ func TestTwoPCRunner_Apply(t *testing.T) { callOrder := &CallCollector{} f1Mock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f2Mock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f1Mock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) f2Mock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) lMock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_prepare") + callOrder.Append("prepare") }) lMock.worker.On("Commit", mock.Anything, testPayload). - Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_commit") + Return(nil, nil).Run(func(args mock.Arguments) { + callOrder.Append("commit") }) // try call process - _, err := lMock.runner.Apply(testPayload) + _, _, err := lMock.runner.Apply(testPayload) So(err, ShouldBeNil) // test call orders So(callOrder.Get(), ShouldResemble, []string{ - "f_prepare", - "f_prepare", - "l_prepare", - "f_commit", - "f_commit", - "l_commit", + "prepare", + "prepare", + "prepare", + "commit", + "commit", + "commit", }) lastLogHash := lMock.runner.lastLogHash @@ -535,18 +536,18 @@ func TestTwoPCRunner_Apply(t *testing.T) { // commit second log callOrder.Reset() - _, err = lMock.runner.Apply(testPayload) + _, _, err = lMock.runner.Apply(testPayload) So(err, ShouldBeNil) // test call orders So(callOrder.Get(), ShouldResemble, []string{ - "f_prepare", - "f_prepare", - "l_prepare", - "f_commit", - "f_commit", - "l_commit", + "prepare", + "prepare", + "prepare", + "commit", + "commit", + "commit", }) // check with log @@ -572,46 +573,48 @@ func TestTwoPCRunner_Apply(t *testing.T) { // f1 prepare with error f1Mock.worker.On("Prepare", mock.Anything, testPayload). Return(unknownErr).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f1Mock.worker.On("Rollback", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_rollback") + callOrder.Append("rollback") }) // f2 prepare with no error f2Mock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_prepare") + callOrder.Append("prepare") }) f2Mock.worker.On("Rollback", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("f_rollback") + callOrder.Append("rollback") }) lMock.worker.On("Prepare", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_prepare") + callOrder.Append("prepare") }) lMock.worker.On("Rollback", mock.Anything, testPayload). Return(nil).Run(func(args mock.Arguments) { - callOrder.Append("l_rollback") + callOrder.Append("rollback") }) // try call process - _, err := lMock.runner.Apply(testPayload) + origLevel := log.GetLevel() + log.SetLevel(log.DebugLevel) + _, _, err := lMock.runner.Apply(testPayload) + log.SetLevel(origLevel) So(err, ShouldNotBeNil) So(err, ShouldEqual, unknownErr) // test call orders - // prepare failed, so no l_prepare is called - // since one prepare failed, only one f_rollback with be triggered + // FIXME, one prepare error worker will not trigger rollback function on storage So(callOrder.Get(), ShouldResemble, []string{ - "f_prepare", - "f_prepare", - //"l_prepare", - "l_rollback", - "f_rollback", - //"f_rollback", + "prepare", + "prepare", + "prepare", + "rollback", + "rollback", + //"rollback", }) }) }) @@ -951,7 +954,7 @@ func TestTwoPCRunner_UpdatePeers(t *testing.T) { // test call process testPayload := []byte("test data") - _, err := lMock.runner.Apply(testPayload) + _, _, err := lMock.runner.Apply(testPayload) // no longer leader So(err, ShouldNotBeNil) diff --git a/kayak/types.go b/kayak/types.go index e71aa5872..fd0d2f6a5 100644 --- a/kayak/types.go +++ b/kayak/types.go @@ -320,7 +320,7 @@ type Runner interface { // Apply defines log replication and log commit logic // and should be called by Leader role only. - Apply(data []byte) (uint64, error) + Apply(data []byte) (interface{}, uint64, error) // Shutdown defines destruct logic. Shutdown(wait bool) error diff --git a/rpc/rpcutil.go b/rpc/rpcutil.go index cf971c554..cafd60d43 100644 --- a/rpc/rpcutil.go +++ b/rpc/rpcutil.go @@ -112,7 +112,7 @@ func (c *PersistentCaller) Call(method string, args interface{}, reply interface return } -// Close closes the stream and RPC client +// CloseStream closes the stream and RPC client func (c *PersistentCaller) CloseStream() { if c.client != nil { if c.client.Conn != nil { diff --git a/sqlchain/storage/storage.go b/sqlchain/storage/storage.go index d902b3e61..481e36b39 100644 --- a/sqlchain/storage/storage.go +++ b/sqlchain/storage/storage.go @@ -53,6 +53,12 @@ type ExecLog struct { Queries []Query } +// ExecResult represents the execution result of sqlite. +type ExecResult struct { + LastInsertID int64 + RowsAffected int64 +} + func openDB(dsn string) (db *sql.DB, err error) { // Rebuild DSN. d, err := NewDSN(dsn) @@ -163,11 +169,12 @@ func (s *Storage) Prepare(ctx context.Context, wb twopc.WriteBatch) (err error) } // Commit implements commit method of two-phase commit worker. -func (s *Storage) Commit(ctx context.Context, wb twopc.WriteBatch) (err error) { +func (s *Storage) Commit(ctx context.Context, wb twopc.WriteBatch) (result interface{}, err error) { el, ok := wb.(*ExecLog) if !ok { - return errors.New("unexpected WriteBatch type") + err = errors.New("unexpected WriteBatch type") + return } s.Lock() @@ -175,6 +182,9 @@ func (s *Storage) Commit(ctx context.Context, wb twopc.WriteBatch) (err error) { if s.tx != nil { if equalTxID(&s.id, &TxID{el.ConnectionID, el.SeqNo, el.Timestamp}) { + // get last insert id and affected rows result + execResult := ExecResult{} + for _, q := range s.queries { // convert arguments types args := make([]interface{}, len(q.Args)) @@ -183,7 +193,8 @@ func (s *Storage) Commit(ctx context.Context, wb twopc.WriteBatch) (err error) { args[i] = v } - _, err = s.tx.ExecContext(ctx, q.Pattern, args...) + var res sql.Result + res, err = s.tx.ExecContext(ctx, q.Pattern, args...) if err != nil { log.WithError(err).Debug("commit query failed") @@ -192,19 +203,29 @@ func (s *Storage) Commit(ctx context.Context, wb twopc.WriteBatch) (err error) { s.queries = nil return } + + lastInsertID, _ := res.LastInsertId() + rowsAffected, _ := res.RowsAffected() + + execResult.LastInsertID = lastInsertID + execResult.RowsAffected += rowsAffected } s.tx.Commit() s.tx = nil s.queries = nil - return nil + result = execResult + + return } - return fmt.Errorf("twopc: inconsistent state, currently in tx: "+ + err = fmt.Errorf("twopc: inconsistent state, currently in tx: "+ "conn = %d, seq = %d, time = %d", s.id.ConnectionID, s.id.SeqNo, s.id.Timestamp) + return } - return errors.New("twopc: tx not prepared") + err = errors.New("twopc: tx not prepared") + return } // Rollback implements rollback method of two-phase commit worker. diff --git a/sqlchain/storage/storage_test.go b/sqlchain/storage/storage_test.go index e72d57b26..0cb0a4459 100644 --- a/sqlchain/storage/storage_test.go +++ b/sqlchain/storage/storage_test.go @@ -71,7 +71,7 @@ func TestBadType(t *testing.T) { t.Logf("Error occurred as expected: %v", err) } - if err = st.Commit(context.Background(), struct{}{}); err == nil { + if _, err = st.Commit(context.Background(), struct{}{}); err == nil { t.Fatal("Unexpected result: returned nil while expecting an error") } else { t.Logf("Error occurred as expected: %v", err) @@ -135,7 +135,7 @@ func TestStorage(t *testing.T) { t.Logf("Error occurred as expected: %v", err) } - if err = st.Commit(context.Background(), el2); err == nil { + if _, err = st.Commit(context.Background(), el2); err == nil { t.Fatal("Unexpected result: returned nil while expecting an error") } else { t.Logf("Error occurred as expected: %v", err) @@ -147,8 +147,12 @@ func TestStorage(t *testing.T) { t.Logf("Error occurred as expected: %v", err) } - if err = st.Commit(context.Background(), el1); err != nil { + var res interface{} + if res, err = st.Commit(context.Background(), el1); err != nil { t.Fatalf("Error occurred: %v", err) + } else { + result := res.(ExecResult) + t.Logf("Result: %v", result) } // test query diff --git a/twopc/twopc.go b/twopc/twopc.go index 3912077d7..53c2f1b16 100644 --- a/twopc/twopc.go +++ b/twopc/twopc.go @@ -22,7 +22,6 @@ import ( "time" "github.com/CovenantSQL/CovenantSQL/utils/log" - "github.com/pkg/errors" ) // Hook are called during 2PC running @@ -40,7 +39,7 @@ type Options struct { // Worker represents a 2PC worker who implements Prepare, Commit, and Rollback. type Worker interface { Prepare(ctx context.Context, wb WriteBatch) error - Commit(ctx context.Context, wb WriteBatch) error + Commit(ctx context.Context, wb WriteBatch) (interface{}, error) Rollback(ctx context.Context, wb WriteBatch) error } @@ -78,96 +77,121 @@ func NewOptionsWithCallback(timeout time.Duration, } } -func (c *Coordinator) rollback(ctx context.Context, workers []Worker, wb WriteBatch) (err error) { +func (c *Coordinator) prepare(ctx context.Context, workers []Worker, wb WriteBatch) (err error) { errs := make([]error, len(workers)) wg := sync.WaitGroup{} + workerFunc := func(n Worker, e *error, wg *sync.WaitGroup) { + defer wg.Done() + + *e = n.Prepare(ctx, wb) + } for index, worker := range workers { wg.Add(1) - go func(n Worker, e *error) { - *e = n.Rollback(ctx, wb) - wg.Done() - }(worker, &errs[index]) + go workerFunc(worker, &errs[index], &wg) } wg.Wait() - for _, err = range errs { + var index int + for index, err = range errs { if err != nil { - return err + log.WithField("worker", workers[index]).WithError(err).Debug("prepare failed") + return } } - return errors.New("twopc: rollback") + return } -func (c *Coordinator) commit(ctx context.Context, workers []Worker, wb WriteBatch) (err error) { +func (c *Coordinator) rollback(ctx context.Context, workers []Worker, wb WriteBatch) (err error) { errs := make([]error, len(workers)) wg := sync.WaitGroup{} + workerFunc := func(n Worker, e *error, wg *sync.WaitGroup) { + defer wg.Done() + + *e = n.Rollback(ctx, wb) + } for index, worker := range workers { wg.Add(1) - go func(n Worker, e *error) { - *e = n.Commit(ctx, wb) - wg.Done() - }(worker, &errs[index]) + go workerFunc(worker, &errs[index], &wg) } wg.Wait() - for _, err = range errs { + var index int + for index, err = range errs { if err != nil { - return err + log.WithField("worker", workers[index]).WithError(err).Debug("rollback failed") + return } } - return nil + return } -// Put initiates a 2PC process to apply given WriteBatch on all workers. -func (c *Coordinator) Put(workers []Worker, wb WriteBatch) (err error) { - // Initiate phase one: ask nodes to prepare for progress - ctx, cancel := context.WithTimeout(context.Background(), c.option.timeout) - defer cancel() +func (c *Coordinator) commit(ctx context.Context, workers []Worker, wb WriteBatch) (result interface{}, err error) { + errs := make([]error, len(workers)) + wg := sync.WaitGroup{} + workerFunc := func(n Worker, resPtr *interface{}, e *error, wg *sync.WaitGroup) { + defer wg.Done() - if c.option.beforePrepare != nil { - if err := c.option.beforePrepare(ctx); err != nil { - return err + var res interface{} + res, *e = n.Commit(ctx, wb) + if resPtr != nil { + *resPtr = res } } - errs := make([]error, len(workers)) - wg := sync.WaitGroup{} - for index, worker := range workers { wg.Add(1) - go func(n Worker, e *error) { - *e = n.Prepare(ctx, wb) - wg.Done() - }(worker, &errs[index]) + if index == 0 { + go workerFunc(worker, &result, &errs[index], &wg) + } else { + go workerFunc(worker, nil, &errs[index], &wg) + } } wg.Wait() - // Check prepare results and initiate phase two - var returnErr error - for index, err := range errs { + var index int + for index, err = range errs { if err != nil { - returnErr = err - log.WithField("worker", workers[index]).WithError(err).Debug("prepare failed") - goto ROLLBACK + log.WithField("worker", workers[index]).WithError(err).Debug("commit failed") + return } } + return +} + +// Put initiates a 2PC process to apply given WriteBatch on all workers. +func (c *Coordinator) Put(workers []Worker, wb WriteBatch) (result interface{}, err error) { + // Initiate phase one: ask nodes to prepare for progress + ctx, cancel := context.WithTimeout(context.Background(), c.option.timeout) + defer cancel() + + if c.option.beforePrepare != nil { + if err = c.option.beforePrepare(ctx); err != nil { + log.WithError(err).Debug("before prepared failed") + return + } + } + + // Check prepare results and initiate phase two + if err = c.prepare(ctx, workers, wb); err != nil { + goto ROLLBACK + } + if c.option.beforeCommit != nil { - if err := c.option.beforeCommit(ctx); err != nil { - returnErr = err + if err = c.option.beforeCommit(ctx); err != nil { log.WithError(err).Debug("before commit failed") goto ROLLBACK } } - err = c.commit(ctx, workers, wb) + result, err = c.commit(ctx, workers, wb) if c.option.afterCommit != nil { if err = c.option.afterCommit(ctx); err != nil { @@ -185,5 +209,5 @@ ROLLBACK: c.rollback(ctx, workers, wb) - return returnErr + return } diff --git a/twopc/twopc_test.go b/twopc/twopc_test.go index dfb3504a8..9cb6dd0ba 100644 --- a/twopc/twopc_test.go +++ b/twopc/twopc_test.go @@ -22,6 +22,7 @@ import ( "fmt" "net" "os" + "strconv" "sync" "testing" "time" @@ -83,11 +84,13 @@ type RaftWriteBatchResp struct { type RaftCommitReq struct { TxID RaftTxID + Cmds []string } type RaftCommitResp struct { ErrCode int ErrString string + Result int64 } type RaftRollbackReq struct { @@ -185,6 +188,19 @@ func (r *RaftNodeRPCServer) RPCCommit(req *RaftCommitReq, resp *RaftCommitResp) return nil } + // calculate + var total int64 + var val int64 + for _, cmd := range req.Cmds { + if val, err = strconv.ParseInt(cmd, 10, 64); err != nil { + return + } + + total += val + } + + resp.Result = total + r.state = Committed return nil } @@ -256,7 +272,7 @@ func (r *RaftNode) Prepare(ctx context.Context, wb WriteBatch) (err error) { return err } -func (r *RaftNode) Commit(ctx context.Context, wb WriteBatch) (err error) { +func (r *RaftNode) Commit(ctx context.Context, wb WriteBatch) (result interface{}, err error) { log.Debugf("executing 2pc: addr = %s, phase = commit", r.addr) defer log.Debugf("2pc result: addr = %s, phase = commit, result = %v", r.addr, err) @@ -264,20 +280,20 @@ func (r *RaftNode) Commit(ctx context.Context, wb WriteBatch) (err error) { if !ok { err = errors.New("unexpected WriteBatch type") - return err + return } cipher := etls.NewCipher([]byte(pass)) conn, err := etls.Dial("tcp", r.addr, cipher) if err != nil { - return err + return } client, err := rpc.InitClientConn(conn) if err != nil { - return err + return } d, ok := ctx.Deadline() @@ -286,22 +302,23 @@ func (r *RaftNode) Commit(ctx context.Context, wb WriteBatch) (err error) { err = conn.SetDeadline(d) if err != nil { - return err + return } } resp := new(RaftCommitResp) - err = client.Call("Raft.RPCCommit", &RaftCommitReq{rwb.TxID}, resp) + err = client.Call("Raft.RPCCommit", &RaftCommitReq{TxID: rwb.TxID, Cmds: rwb.Cmds}, resp) + result = resp.Result if err != nil { - return err + return } if resp.ErrCode > 0 { err = fmt.Errorf(resp.ErrString) } - return err + return } func (r *RaftNode) Rollback(ctx context.Context, wb WriteBatch) (err error) { @@ -339,7 +356,7 @@ func (r *RaftNode) Rollback(ctx context.Context, wb WriteBatch) (err error) { } resp := new(RaftRollbackResp) - err = client.Call("Raft.RPCRollback", &RaftRollbackReq{rwb.TxID}, resp) + err = client.Call("Raft.RPCRollback", &RaftRollbackReq{TxID: rwb.TxID}, resp) if err != nil { return err @@ -405,16 +422,20 @@ func TestTwoPhaseCommit(t *testing.T) { testNodeReset() policy = AllGood - err := c.Put(nodes, &RaftWriteBatchReq{TxID: 0, Cmds: []string{"+1", "-3", "+10"}}) + res, err := c.Put(nodes, &RaftWriteBatchReq{TxID: 0, Cmds: []string{"+1", "-3", "+10"}}) if err != nil { t.Fatalf("Error occurred: %s", err.Error()) } + if res.(int64) != 8 { + t.Fatalf("TwoPC returns invalid result: %v", res) + } + testNodeReset() policy = FailOnPrepare - err = c.Put(nodes, &RaftWriteBatchReq{TxID: 1, Cmds: []string{"-3", "-4", "+1"}}) + res, err = c.Put(nodes, &RaftWriteBatchReq{TxID: 1, Cmds: []string{"-3", "-4", "+1"}}) if err == nil { t.Fatal("Unexpected result: returned nil while expecting an error") @@ -425,7 +446,7 @@ func TestTwoPhaseCommit(t *testing.T) { testNodeReset() policy = FailOnCommit - err = c.Put(nodes, &RaftWriteBatchReq{TxID: 2, Cmds: []string{"-5", "+9", "+1"}}) + res, err = c.Put(nodes, &RaftWriteBatchReq{TxID: 2, Cmds: []string{"-5", "+9", "+1"}}) if err == nil { t.Fatal("Unexpected result: returned nil while expecting an error") @@ -469,11 +490,15 @@ func TestTwoPhaseCommit_WithHooks(t *testing.T) { testNodeReset() - err := c.Put(nodes, &RaftWriteBatchReq{TxID: 0, Cmds: []string{"+1", "-3", "+10"}}) + res, err := c.Put(nodes, &RaftWriteBatchReq{TxID: 0, Cmds: []string{"+1", "-3", "+10"}}) if err != nil { t.Fatalf("Error occurred: %s", err.Error()) } + if res.(int64) != 8 { + t.Fatalf("TwoPC returns invalid result: %v", res) + } + // error before prepare errorBeforePrepare = true errorBeforeCommit = false @@ -481,7 +506,7 @@ func TestTwoPhaseCommit_WithHooks(t *testing.T) { testNodeReset() - err = c.Put(nodes, &RaftWriteBatchReq{TxID: 1, Cmds: []string{"+1", "-3", "+10"}}) + res, err = c.Put(nodes, &RaftWriteBatchReq{TxID: 1, Cmds: []string{"+1", "-3", "+10"}}) if err == nil { t.Fatal("Unexpected result: returned nil while expecting an error") } else if err != beforePrepareError { @@ -497,7 +522,7 @@ func TestTwoPhaseCommit_WithHooks(t *testing.T) { testNodeReset() - err = c.Put(nodes, &RaftWriteBatchReq{TxID: 2, Cmds: []string{"+1", "-3", "+10"}}) + res, err = c.Put(nodes, &RaftWriteBatchReq{TxID: 2, Cmds: []string{"+1", "-3", "+10"}}) if err == nil { t.Fatal("Unexpected result: returned nil while expecting an error") } else if err != beforeCommitError { @@ -513,7 +538,7 @@ func TestTwoPhaseCommit_WithHooks(t *testing.T) { testNodeReset() - err = c.Put(nodes, &RaftWriteBatchReq{TxID: 3, Cmds: []string{"+1", "-3", "+10"}}) + res, err = c.Put(nodes, &RaftWriteBatchReq{TxID: 3, Cmds: []string{"+1", "-3", "+10"}}) if err == nil { t.Fatal("Unexpected result: returned nil while expecting an error") } else if err != beforeCommitError { diff --git a/utils/net.go b/utils/net.go index 8648252ae..5c3a90f06 100644 --- a/utils/net.go +++ b/utils/net.go @@ -38,10 +38,10 @@ func testPortConnectable(addr string) bool { conn, err := net.Dial("tcp", addr) if err != nil { return false - } else { - conn.Close() - return true } + + conn.Close() + return true } func testPort(bindAddr string, port int, excludeAllocated bool) bool { diff --git a/vendor/github.com/CovenantSQL/sqlparser/token.go b/vendor/github.com/CovenantSQL/sqlparser/token.go index 8dfc057fa..74ed904e6 100644 --- a/vendor/github.com/CovenantSQL/sqlparser/token.go +++ b/vendor/github.com/CovenantSQL/sqlparser/token.go @@ -34,19 +34,20 @@ const ( // Tokenizer is the struct used to generate SQL // tokens for the parser. type Tokenizer struct { - InStream io.Reader - AllowComments bool - ForceEOF bool - lastChar uint16 - Position int - lastToken []byte - LastError error - posVarIndex int - ParseTree Statement - partialDDL *DDL - nesting int - multi bool - specialComment *Tokenizer + InStream io.Reader + AllowComments bool + AllowBackSlashEscape bool + ForceEOF bool + lastChar uint16 + Position int + lastToken []byte + LastError error + posVarIndex int + ParseTree Statement + partialDDL *DDL + nesting int + multi bool + specialComment *Tokenizer buf []byte bufPos int @@ -660,14 +661,14 @@ func (tkn *Tokenizer) scanString(delim uint16, typ int) (int, []byte) { return LEX_ERROR, buffer.Bytes() } - if ch != delim && ch != '\\' { + if ch != delim && (!tkn.AllowBackSlashEscape || ch != '\\') { buffer.WriteByte(byte(ch)) // Scan ahead to the next interesting character. start := tkn.bufPos for ; tkn.bufPos < tkn.bufSize; tkn.bufPos++ { ch = uint16(tkn.buf[tkn.bufPos]) - if ch == delim || ch == '\\' { + if ch == delim || (tkn.AllowBackSlashEscape && ch == '\\') { break } } @@ -687,7 +688,7 @@ func (tkn *Tokenizer) scanString(delim uint16, typ int) (int, []byte) { } tkn.next() // Read one past the delim or escape character. - if ch == '\\' { + if tkn.AllowBackSlashEscape && ch == '\\' { if tkn.lastChar == eofChar { // String terminates mid escape character. return LEX_ERROR, buffer.Bytes() diff --git a/vendor/github.com/sirupsen/logrus/.gitignore b/vendor/github.com/sirupsen/logrus/.gitignore index 66be63a00..6b7d7d1e8 100644 --- a/vendor/github.com/sirupsen/logrus/.gitignore +++ b/vendor/github.com/sirupsen/logrus/.gitignore @@ -1 +1,2 @@ logrus +vendor diff --git a/vendor/github.com/sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md index ff0471869..cb85d9f9f 100644 --- a/vendor/github.com/sirupsen/logrus/CHANGELOG.md +++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md @@ -1,3 +1,10 @@ +# 1.2.0 +This new release introduces: + * A new method `SetReportCaller` in the `Logger` to enable the file, line and calling function from which the trace has been issued + * A new trace level named `Trace` whose level is below `Debug` + * A configurable exit function to be called upon a Fatal trace + * The `Level` object now implements `encoding.TextUnmarshaler` interface + # 1.1.1 This is a bug fix release. * fix the build break on Solaris diff --git a/vendor/github.com/sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md index 072e99be3..093bb13f8 100644 --- a/vendor/github.com/sirupsen/logrus/README.md +++ b/vendor/github.com/sirupsen/logrus/README.md @@ -56,8 +56,39 @@ time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4 time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009 time="2015-03-26T01:27:38-04:00" level=fatal msg="The ice breaks!" err=&{0x2082280c0 map[animal:orca size:9009] 2015-03-26 01:27:38.441574009 -0400 EDT panic It's over 9000!} number=100 omg=true -exit status 1 ``` +To ensure this behaviour even if a TTY is attached, set your formatter as follows: + +```go + log.SetFormatter(&log.TextFormatter{ + DisableColors: true, + FullTimestamp: true, + }) +``` + +#### Logging Method Name + +If you wish to add the calling method as a field, instruct the logger via: +```go +log.SetReportCaller(true) +``` +This adds the caller as 'method' like so: + +```json +{"animal":"penguin","level":"fatal","method":"github.com/sirupsen/arcticcreatures.migrate","msg":"a penguin swims by", +"time":"2014-03-10 19:57:38.562543129 -0400 EDT"} +``` + +```text +time="2015-03-26T01:27:38-04:00" level=fatal method=github.com/sirupsen/arcticcreatures.migrate msg="a penguin swims by" animal=penguin +``` +Note that this does add measurable overhead - the cost will depend on the version of Go, but is +between 20 and 40% in recent tests with 1.6 and 1.7. You can validate this in your +environment via benchmarks: +``` +go test -bench=.*CallerTracing +``` + #### Case-sensitivity @@ -246,9 +277,10 @@ A list of currently known of service hook can be found in this wiki [page](https #### Level logging -Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic. +Logrus has seven logging levels: Trace, Debug, Info, Warning, Error, Fatal and Panic. ```go +log.Trace("Something very low level.") log.Debug("Useful debugging information.") log.Info("Something noteworthy happened!") log.Warn("You should probably take a look at this.") diff --git a/vendor/github.com/sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go index ca634a609..cc85d3aab 100644 --- a/vendor/github.com/sirupsen/logrus/entry.go +++ b/vendor/github.com/sirupsen/logrus/entry.go @@ -5,11 +5,29 @@ import ( "fmt" "os" "reflect" + "runtime" + "strings" "sync" "time" ) -var bufferPool *sync.Pool +var ( + bufferPool *sync.Pool + + // qualified package name, cached at first use + logrusPackage string + + // Positions in the call stack when tracing to report the calling method + minimumCallerDepth int + + // Used for caller information initialisation + callerInitOnce sync.Once +) + +const ( + maximumCallerDepth int = 25 + knownLogrusFrames int = 4 +) func init() { bufferPool = &sync.Pool{ @@ -17,15 +35,18 @@ func init() { return new(bytes.Buffer) }, } + + // start at the bottom of the stack before the package-name cache is primed + minimumCallerDepth = 1 } // Defines the key when adding errors using WithError. var ErrorKey = "error" // An entry is the final or intermediate Logrus logging entry. It contains all -// the fields passed with WithField{,s}. It's finally logged when Debug, Info, -// Warn, Error, Fatal or Panic is called on it. These objects can be reused and -// passed around as much as you wish to avoid field duplication. +// the fields passed with WithField{,s}. It's finally logged when Trace, Debug, +// Info, Warn, Error, Fatal or Panic is called on it. These objects can be +// reused and passed around as much as you wish to avoid field duplication. type Entry struct { Logger *Logger @@ -35,11 +56,14 @@ type Entry struct { // Time at which the log entry was created Time time.Time - // Level the log entry was logged at: Debug, Info, Warn, Error, Fatal or Panic + // Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic // This field will be set on entry firing and the value will be equal to the one in Logger struct field. Level Level - // Message passed to Debug, Info, Warn, Error, Fatal or Panic + // Calling method, with package name + Caller *runtime.Frame + + // Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic Message string // When formatter is called in entry.log(), a Buffer may be set to entry @@ -52,8 +76,8 @@ type Entry struct { func NewEntry(logger *Logger) *Entry { return &Entry{ Logger: logger, - // Default is five fields, give a little extra room - Data: make(Fields, 5), + // Default is three fields, plus one optional. Give a little extra room. + Data: make(Fields, 6), } } @@ -103,6 +127,57 @@ func (entry *Entry) WithTime(t time.Time) *Entry { return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t} } +// getPackageName reduces a fully qualified function name to the package name +// There really ought to be to be a better way... +func getPackageName(f string) string { + for { + lastPeriod := strings.LastIndex(f, ".") + lastSlash := strings.LastIndex(f, "/") + if lastPeriod > lastSlash { + f = f[:lastPeriod] + } else { + break + } + } + + return f +} + +// getCaller retrieves the name of the first non-logrus calling function +func getCaller() *runtime.Frame { + // Restrict the lookback frames to avoid runaway lookups + pcs := make([]uintptr, maximumCallerDepth) + depth := runtime.Callers(minimumCallerDepth, pcs) + frames := runtime.CallersFrames(pcs[:depth]) + + // cache this package's fully-qualified name + callerInitOnce.Do(func() { + logrusPackage = getPackageName(runtime.FuncForPC(pcs[0]).Name()) + + // now that we have the cache, we can skip a minimum count of known-logrus functions + // XXX this is dubious, the number of frames may vary store an entry in a logger interface + minimumCallerDepth = knownLogrusFrames + }) + + for f, again := frames.Next(); again; f, again = frames.Next() { + pkg := getPackageName(f.Function) + + // If the caller isn't part of this package, we're done + if pkg != logrusPackage { + return &f + } + } + + // if we got here, we failed to find the caller's context + return nil +} + +func (entry Entry) HasCaller() (has bool) { + return entry.Logger != nil && + entry.Logger.ReportCaller && + entry.Caller != nil +} + // This function is not declared with a pointer value because otherwise // race conditions will occur when using multiple goroutines func (entry Entry) log(level Level, msg string) { @@ -119,6 +194,9 @@ func (entry Entry) log(level Level, msg string) { entry.Level = level entry.Message = msg + if entry.Logger.ReportCaller { + entry.Caller = getCaller() + } entry.fireHooks() @@ -162,6 +240,12 @@ func (entry *Entry) write() { } } +func (entry *Entry) Trace(args ...interface{}) { + if entry.Logger.IsLevelEnabled(TraceLevel) { + entry.log(TraceLevel, fmt.Sprint(args...)) + } +} + func (entry *Entry) Debug(args ...interface{}) { if entry.Logger.IsLevelEnabled(DebugLevel) { entry.log(DebugLevel, fmt.Sprint(args...)) @@ -198,7 +282,7 @@ func (entry *Entry) Fatal(args ...interface{}) { if entry.Logger.IsLevelEnabled(FatalLevel) { entry.log(FatalLevel, fmt.Sprint(args...)) } - Exit(1) + entry.Logger.Exit(1) } func (entry *Entry) Panic(args ...interface{}) { @@ -210,6 +294,12 @@ func (entry *Entry) Panic(args ...interface{}) { // Entry Printf family functions +func (entry *Entry) Tracef(format string, args ...interface{}) { + if entry.Logger.IsLevelEnabled(TraceLevel) { + entry.Trace(fmt.Sprintf(format, args...)) + } +} + func (entry *Entry) Debugf(format string, args ...interface{}) { if entry.Logger.IsLevelEnabled(DebugLevel) { entry.Debug(fmt.Sprintf(format, args...)) @@ -246,7 +336,7 @@ func (entry *Entry) Fatalf(format string, args ...interface{}) { if entry.Logger.IsLevelEnabled(FatalLevel) { entry.Fatal(fmt.Sprintf(format, args...)) } - Exit(1) + entry.Logger.Exit(1) } func (entry *Entry) Panicf(format string, args ...interface{}) { @@ -257,6 +347,12 @@ func (entry *Entry) Panicf(format string, args ...interface{}) { // Entry Println family functions +func (entry *Entry) Traceln(args ...interface{}) { + if entry.Logger.IsLevelEnabled(TraceLevel) { + entry.Trace(entry.sprintlnn(args...)) + } +} + func (entry *Entry) Debugln(args ...interface{}) { if entry.Logger.IsLevelEnabled(DebugLevel) { entry.Debug(entry.sprintlnn(args...)) @@ -293,7 +389,7 @@ func (entry *Entry) Fatalln(args ...interface{}) { if entry.Logger.IsLevelEnabled(FatalLevel) { entry.Fatal(entry.sprintlnn(args...)) } - Exit(1) + entry.Logger.Exit(1) } func (entry *Entry) Panicln(args ...interface{}) { diff --git a/vendor/github.com/sirupsen/logrus/exported.go b/vendor/github.com/sirupsen/logrus/exported.go index fb2a7a1f0..7342613c3 100644 --- a/vendor/github.com/sirupsen/logrus/exported.go +++ b/vendor/github.com/sirupsen/logrus/exported.go @@ -24,6 +24,12 @@ func SetFormatter(formatter Formatter) { std.SetFormatter(formatter) } +// SetReportCaller sets whether the standard logger will include the calling +// method as a field. +func SetReportCaller(include bool) { + std.SetReportCaller(include) +} + // SetLevel sets the standard logger level. func SetLevel(level Level) { std.SetLevel(level) @@ -77,6 +83,11 @@ func WithTime(t time.Time) *Entry { return std.WithTime(t) } +// Trace logs a message at level Trace on the standard logger. +func Trace(args ...interface{}) { + std.Trace(args...) +} + // Debug logs a message at level Debug on the standard logger. func Debug(args ...interface{}) { std.Debug(args...) @@ -117,6 +128,11 @@ func Fatal(args ...interface{}) { std.Fatal(args...) } +// Tracef logs a message at level Trace on the standard logger. +func Tracef(format string, args ...interface{}) { + std.Tracef(format, args...) +} + // Debugf logs a message at level Debug on the standard logger. func Debugf(format string, args ...interface{}) { std.Debugf(format, args...) @@ -157,6 +173,11 @@ func Fatalf(format string, args ...interface{}) { std.Fatalf(format, args...) } +// Traceln logs a message at level Trace on the standard logger. +func Traceln(args ...interface{}) { + std.Traceln(args...) +} + // Debugln logs a message at level Debug on the standard logger. func Debugln(args ...interface{}) { std.Debugln(args...) diff --git a/vendor/github.com/sirupsen/logrus/formatter.go b/vendor/github.com/sirupsen/logrus/formatter.go index be2f3fcee..408883773 100644 --- a/vendor/github.com/sirupsen/logrus/formatter.go +++ b/vendor/github.com/sirupsen/logrus/formatter.go @@ -9,6 +9,8 @@ const ( FieldKeyLevel = "level" FieldKeyTime = "time" FieldKeyLogrusError = "logrus_error" + FieldKeyFunc = "func" + FieldKeyFile = "file" ) // The Formatter interface is used to implement a custom Formatter. It takes an @@ -25,7 +27,7 @@ type Formatter interface { Format(*Entry) ([]byte, error) } -// This is to not silently overwrite `time`, `msg` and `level` fields when +// This is to not silently overwrite `time`, `msg`, `func` and `level` fields when // dumping it. If this code wasn't there doing: // // logrus.WithField("level", 1).Info("hello") @@ -37,7 +39,7 @@ type Formatter interface { // // It's not exported because it's still using Data in an opinionated way. It's to // avoid code duplication between the two default formatters. -func prefixFieldClashes(data Fields, fieldMap FieldMap) { +func prefixFieldClashes(data Fields, fieldMap FieldMap, reportCaller bool) { timeKey := fieldMap.resolve(FieldKeyTime) if t, ok := data[timeKey]; ok { data["fields."+timeKey] = t @@ -61,4 +63,16 @@ func prefixFieldClashes(data Fields, fieldMap FieldMap) { data["fields."+logrusErrKey] = l delete(data, logrusErrKey) } + + // If reportCaller is not set, 'func' will not conflict. + if reportCaller { + funcKey := fieldMap.resolve(FieldKeyFunc) + if l, ok := data[funcKey]; ok { + data["fields."+funcKey] = l + } + fileKey := fieldMap.resolve(FieldKeyFile) + if l, ok := data[fileKey]; ok { + data["fields."+fileKey] = l + } + } } diff --git a/vendor/github.com/sirupsen/logrus/go.mod b/vendor/github.com/sirupsen/logrus/go.mod index f4fed02fb..94574cc63 100644 --- a/vendor/github.com/sirupsen/logrus/go.mod +++ b/vendor/github.com/sirupsen/logrus/go.mod @@ -2,8 +2,9 @@ module github.com/sirupsen/logrus require ( github.com/davecgh/go-spew v1.1.1 // indirect - github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe + github.com/konsorten/go-windows-terminal-sequences v1.0.1 github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/objx v0.1.1 // indirect github.com/stretchr/testify v1.2.2 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 diff --git a/vendor/github.com/sirupsen/logrus/go.sum b/vendor/github.com/sirupsen/logrus/go.sum index 1f0d71964..133d34ae1 100644 --- a/vendor/github.com/sirupsen/logrus/go.sum +++ b/vendor/github.com/sirupsen/logrus/go.sum @@ -2,8 +2,11 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe h1:CHRGQ8V7OlCYtwaKPJi3iA7J+YdNKdo8j7nG5IgDhjs= github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f2633dfe/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= diff --git a/vendor/github.com/sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go index ef8d07460..260575359 100644 --- a/vendor/github.com/sirupsen/logrus/json_formatter.go +++ b/vendor/github.com/sirupsen/logrus/json_formatter.go @@ -34,9 +34,10 @@ type JSONFormatter struct { // As an example: // formatter := &JSONFormatter{ // FieldMap: FieldMap{ - // FieldKeyTime: "@timestamp", + // FieldKeyTime: "@timestamp", // FieldKeyLevel: "@level", - // FieldKeyMsg: "@message", + // FieldKeyMsg: "@message", + // FieldKeyFunc: "@caller", // }, // } FieldMap FieldMap @@ -47,7 +48,7 @@ type JSONFormatter struct { // Format renders a single log entry func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { - data := make(Fields, len(entry.Data)+3) + data := make(Fields, len(entry.Data)+4) for k, v := range entry.Data { switch v := v.(type) { case error: @@ -65,7 +66,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { data = newData } - prefixFieldClashes(data, f.FieldMap) + prefixFieldClashes(data, f.FieldMap, entry.HasCaller()) timestampFormat := f.TimestampFormat if timestampFormat == "" { @@ -80,6 +81,10 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { } data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String() + if entry.HasCaller() { + data[f.FieldMap.resolve(FieldKeyFunc)] = entry.Caller.Function + data[f.FieldMap.resolve(FieldKeyFile)] = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) + } var b *bytes.Buffer if entry.Buffer != nil { diff --git a/vendor/github.com/sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go index b67bfcbd3..5ceca0eab 100644 --- a/vendor/github.com/sirupsen/logrus/logger.go +++ b/vendor/github.com/sirupsen/logrus/logger.go @@ -24,6 +24,10 @@ type Logger struct { // own that implements the `Formatter` interface, see the `README` or included // formatters for examples. Formatter Formatter + + // Flag for whether to log caller info (off by default) + ReportCaller bool + // The logging level the logger should log at. This is typically (and defaults // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be // logged. @@ -32,8 +36,12 @@ type Logger struct { mu MutexWrap // Reusable empty entry entryPool sync.Pool + // Function to exit the application, defaults to `os.Exit()` + ExitFunc exitFunc } +type exitFunc func(int) + type MutexWrap struct { lock sync.Mutex disabled bool @@ -69,10 +77,12 @@ func (mw *MutexWrap) Disable() { // It's recommended to make this a global instance called `log`. func New() *Logger { return &Logger{ - Out: os.Stderr, - Formatter: new(TextFormatter), - Hooks: make(LevelHooks), - Level: InfoLevel, + Out: os.Stderr, + Formatter: new(TextFormatter), + Hooks: make(LevelHooks), + Level: InfoLevel, + ExitFunc: os.Exit, + ReportCaller: false, } } @@ -121,6 +131,14 @@ func (logger *Logger) WithTime(t time.Time) *Entry { return entry.WithTime(t) } +func (logger *Logger) Tracef(format string, args ...interface{}) { + if logger.IsLevelEnabled(TraceLevel) { + entry := logger.newEntry() + entry.Tracef(format, args...) + logger.releaseEntry(entry) + } +} + func (logger *Logger) Debugf(format string, args ...interface{}) { if logger.IsLevelEnabled(DebugLevel) { entry := logger.newEntry() @@ -173,7 +191,7 @@ func (logger *Logger) Fatalf(format string, args ...interface{}) { entry.Fatalf(format, args...) logger.releaseEntry(entry) } - Exit(1) + logger.Exit(1) } func (logger *Logger) Panicf(format string, args ...interface{}) { @@ -184,6 +202,14 @@ func (logger *Logger) Panicf(format string, args ...interface{}) { } } +func (logger *Logger) Trace(args ...interface{}) { + if logger.IsLevelEnabled(TraceLevel) { + entry := logger.newEntry() + entry.Trace(args...) + logger.releaseEntry(entry) + } +} + func (logger *Logger) Debug(args ...interface{}) { if logger.IsLevelEnabled(DebugLevel) { entry := logger.newEntry() @@ -236,7 +262,7 @@ func (logger *Logger) Fatal(args ...interface{}) { entry.Fatal(args...) logger.releaseEntry(entry) } - Exit(1) + logger.Exit(1) } func (logger *Logger) Panic(args ...interface{}) { @@ -247,6 +273,14 @@ func (logger *Logger) Panic(args ...interface{}) { } } +func (logger *Logger) Traceln(args ...interface{}) { + if logger.IsLevelEnabled(TraceLevel) { + entry := logger.newEntry() + entry.Traceln(args...) + logger.releaseEntry(entry) + } +} + func (logger *Logger) Debugln(args ...interface{}) { if logger.IsLevelEnabled(DebugLevel) { entry := logger.newEntry() @@ -299,7 +333,7 @@ func (logger *Logger) Fatalln(args ...interface{}) { entry.Fatalln(args...) logger.releaseEntry(entry) } - Exit(1) + logger.Exit(1) } func (logger *Logger) Panicln(args ...interface{}) { @@ -310,6 +344,14 @@ func (logger *Logger) Panicln(args ...interface{}) { } } +func (logger *Logger) Exit(code int) { + runHandlers() + if logger.ExitFunc == nil { + logger.ExitFunc = os.Exit + } + logger.ExitFunc(code) +} + //When file is opened with appending mode, it's safe to //write concurrently to a file (within 4k message on Linux). //In these cases user can choose to disable the lock. @@ -357,6 +399,12 @@ func (logger *Logger) SetOutput(output io.Writer) { logger.Out = output } +func (logger *Logger) SetReportCaller(reportCaller bool) { + logger.mu.Lock() + defer logger.mu.Unlock() + logger.ReportCaller = reportCaller +} + // ReplaceHooks replaces the logger hooks and returns the old ones func (logger *Logger) ReplaceHooks(hooks LevelHooks) LevelHooks { logger.mu.Lock() diff --git a/vendor/github.com/sirupsen/logrus/logrus.go b/vendor/github.com/sirupsen/logrus/logrus.go index fa0b9dea8..4ef451866 100644 --- a/vendor/github.com/sirupsen/logrus/logrus.go +++ b/vendor/github.com/sirupsen/logrus/logrus.go @@ -15,6 +15,8 @@ type Level uint32 // Convert the Level to a string. E.g. PanicLevel becomes "panic". func (level Level) String() string { switch level { + case TraceLevel: + return "trace" case DebugLevel: return "debug" case InfoLevel: @@ -47,12 +49,26 @@ func ParseLevel(lvl string) (Level, error) { return InfoLevel, nil case "debug": return DebugLevel, nil + case "trace": + return TraceLevel, nil } var l Level return l, fmt.Errorf("not a valid logrus Level: %q", lvl) } +// UnmarshalText implements encoding.TextUnmarshaler. +func (level *Level) UnmarshalText(text []byte) error { + l, err := ParseLevel(string(text)) + if err != nil { + return err + } + + *level = Level(l) + + return nil +} + // A constant exposing all logging levels var AllLevels = []Level{ PanicLevel, @@ -61,6 +77,7 @@ var AllLevels = []Level{ WarnLevel, InfoLevel, DebugLevel, + TraceLevel, } // These are the different logging levels. You can set the logging level to log @@ -69,7 +86,7 @@ const ( // PanicLevel level, highest level of severity. Logs and then calls panic with the // message passed to Debug, Info, ... PanicLevel Level = iota - // FatalLevel level. Logs and then calls `os.Exit(1)`. It will exit even if the + // FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the // logging level is set to Panic. FatalLevel // ErrorLevel level. Logs. Used for errors that should definitely be noted. @@ -82,6 +99,8 @@ const ( InfoLevel // DebugLevel level. Usually only enabled when debugging. Very verbose logging. DebugLevel + // TraceLevel level. Designates finer-grained informational events than the Debug. + TraceLevel ) // Won't compile if StdLogger can't be realized by a log.Logger @@ -148,3 +167,12 @@ type FieldLogger interface { // IsFatalEnabled() bool // IsPanicEnabled() bool } + +// Ext1FieldLogger (the first extension to FieldLogger) is superfluous, it is +// here for consistancy. Do not use. Use Logger or Entry instead. +type Ext1FieldLogger interface { + FieldLogger + Tracef(format string, args ...interface{}) + Trace(args ...interface{}) + Traceln(args ...interface{}) +} diff --git a/vendor/github.com/sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go index d4663b8c2..49ec92f17 100644 --- a/vendor/github.com/sirupsen/logrus/text_formatter.go +++ b/vendor/github.com/sirupsen/logrus/text_formatter.go @@ -107,7 +107,7 @@ func (f *TextFormatter) isColored() bool { // Format renders a single log entry func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { - prefixFieldClashes(entry.Data, f.FieldMap) + prefixFieldClashes(entry.Data, f.FieldMap, entry.HasCaller()) keys := make([]string, 0, len(entry.Data)) for k := range entry.Data { @@ -125,6 +125,10 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { if entry.err != "" { fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyLogrusError)) } + if entry.HasCaller() { + fixedKeys = append(fixedKeys, + f.FieldMap.resolve(FieldKeyFunc), f.FieldMap.resolve(FieldKeyFile)) + } if !f.DisableSorting { if f.SortingFunc == nil { @@ -160,15 +164,19 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { } else { for _, key := range fixedKeys { var value interface{} - switch key { - case f.FieldMap.resolve(FieldKeyTime): + switch { + case key == f.FieldMap.resolve(FieldKeyTime): value = entry.Time.Format(timestampFormat) - case f.FieldMap.resolve(FieldKeyLevel): + case key == f.FieldMap.resolve(FieldKeyLevel): value = entry.Level.String() - case f.FieldMap.resolve(FieldKeyMsg): + case key == f.FieldMap.resolve(FieldKeyMsg): value = entry.Message - case f.FieldMap.resolve(FieldKeyLogrusError): + case key == f.FieldMap.resolve(FieldKeyLogrusError): value = entry.err + case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller(): + value = entry.Caller.Function + case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller(): + value = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line) default: value = entry.Data[key] } @@ -183,7 +191,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []string, timestampFormat string) { var levelColor int switch entry.Level { - case DebugLevel: + case DebugLevel, TraceLevel: levelColor = gray case WarnLevel: levelColor = yellow @@ -202,12 +210,19 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin // the behavior of logrus text_formatter the same as the stdlib log package entry.Message = strings.TrimSuffix(entry.Message, "\n") + caller := "" + + if entry.HasCaller() { + caller = fmt.Sprintf("%s:%d %s()", + entry.Caller.File, entry.Caller.Line, entry.Caller.Function) + } + if f.DisableTimestamp { - fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m %-44s ", levelColor, levelText, entry.Message) + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m%s %-44s ", levelColor, levelText, caller, entry.Message) } else if !f.FullTimestamp { - fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d] %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), entry.Message) + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%04d]%s %-44s ", levelColor, levelText, int(entry.Time.Sub(baseTimestamp)/time.Second), caller, entry.Message) } else { - fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s] %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), entry.Message) + fmt.Fprintf(b, "\x1b[%dm%s\x1b[0m[%s]%s %-44s ", levelColor, levelText, entry.Time.Format(timestampFormat), caller, entry.Message) } for _, k := range keys { v := entry.Data[k] diff --git a/vendor/github.com/sirupsen/logrus/writer.go b/vendor/github.com/sirupsen/logrus/writer.go index 7bdebedc6..9e1f75135 100644 --- a/vendor/github.com/sirupsen/logrus/writer.go +++ b/vendor/github.com/sirupsen/logrus/writer.go @@ -24,6 +24,8 @@ func (entry *Entry) WriterLevel(level Level) *io.PipeWriter { var printFunc func(args ...interface{}) switch level { + case TraceLevel: + printFunc = entry.Trace case DebugLevel: printFunc = entry.Debug case InfoLevel: diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index 6401e3a29..756510575 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -248,11 +248,13 @@ func Uname(uname *Utsname) error { //sys Dup(fd int) (nfd int, err error) //sys Dup2(from int, to int) (err error) //sys Exit(code int) +//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchdir(fd int) (err error) //sys Fchflags(fd int, flags int) (err error) //sys Fchmod(fd int, mode uint32) (err error) //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) +//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fstat(fd int, stat *Stat_t) (err error) @@ -280,11 +282,14 @@ func Uname(uname *Utsname) error { //sys Kqueue() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Link(path string, link string) (err error) +//sys Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) //sys Listen(s int, backlog int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) //sys Mkdir(path string, mode uint32) (err error) +//sys Mkdirat(dirfd int, path string, mode uint32) (err error) //sys Mkfifo(path string, mode uint32) (err error) //sys Mknod(path string, mode uint32, dev int) (err error) +//sys Mknodat(fd int, path string, mode uint32, dev int) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) //sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) @@ -313,11 +318,13 @@ func Uname(uname *Utsname) error { //sys Stat(path string, stat *Stat_t) (err error) //sys Statfs(path string, stat *Statfs_t) (err error) //sys Symlink(path string, link string) (err error) +//sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error) //sys Sync() (err error) //sys Truncate(path string, length int64) (err error) //sys Umask(newmask int) (oldmask int) //sys Undelete(path string) (err error) //sys Unlink(path string) (err error) +//sys Unlinkat(dirfd int, path string, flags int) (err error) //sys Unmount(path string, flags int) (err error) //sys write(fd int, p []byte) (n int, err error) //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_netbsd.go b/vendor/golang.org/x/sys/unix/syscall_netbsd.go index 871fe65c3..b711aca82 100644 --- a/vendor/golang.org/x/sys/unix/syscall_netbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_netbsd.go @@ -269,6 +269,7 @@ func Uname(uname *Utsname) error { //sys Fchmod(fd int, mode uint32) (err error) //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) +//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fstat(fd int, stat *Stat_t) (err error) @@ -293,11 +294,15 @@ func Uname(uname *Utsname) error { //sys Kqueue() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Link(path string, link string) (err error) +//sys Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) //sys Listen(s int, backlog int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) //sys Mkdir(path string, mode uint32) (err error) +//sys Mkdirat(dirfd int, path string, mode uint32) (err error) //sys Mkfifo(path string, mode uint32) (err error) +//sys Mkfifoat(dirfd int, path string, mode uint32) (err error) //sys Mknod(path string, mode uint32, dev int) (err error) +//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) //sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) @@ -306,7 +311,9 @@ func Uname(uname *Utsname) error { //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) +//sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) //sys Rename(from string, to string) (err error) +//sys Renameat(fromfd int, from string, tofd int, to string) (err error) //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK @@ -324,10 +331,12 @@ func Uname(uname *Utsname) error { //sysnb Setuid(uid int) (err error) //sys Stat(path string, stat *Stat_t) (err error) //sys Symlink(path string, link string) (err error) +//sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error) //sys Sync() (err error) //sys Truncate(path string, length int64) (err error) //sys Umask(newmask int) (oldmask int) //sys Unlink(path string) (err error) +//sys Unlinkat(dirfd int, path string, flags int) (err error) //sys Unmount(path string, flags int) (err error) //sys write(fd int, p []byte) (n int, err error) //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 2b9f26a63..5a398f817 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -233,6 +233,7 @@ func Uname(uname *Utsname) error { //sys Fchmod(fd int, mode uint32) (err error) //sys Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) //sys Fchown(fd int, uid int, gid int) (err error) +//sys Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) //sys Flock(fd int, how int) (err error) //sys Fpathconf(fd int, name int) (val int, err error) //sys Fstat(fd int, stat *Stat_t) (err error) @@ -259,11 +260,15 @@ func Uname(uname *Utsname) error { //sys Kqueue() (fd int, err error) //sys Lchown(path string, uid int, gid int) (err error) //sys Link(path string, link string) (err error) +//sys Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) //sys Listen(s int, backlog int) (err error) //sys Lstat(path string, stat *Stat_t) (err error) //sys Mkdir(path string, mode uint32) (err error) +//sys Mkdirat(dirfd int, path string, mode uint32) (err error) //sys Mkfifo(path string, mode uint32) (err error) +//sys Mkfifoat(dirfd int, path string, mode uint32) (err error) //sys Mknod(path string, mode uint32, dev int) (err error) +//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Open(path string, mode int, perm uint32) (fd int, err error) //sys Openat(dirfd int, path string, mode int, perm uint32) (fd int, err error) @@ -272,7 +277,9 @@ func Uname(uname *Utsname) error { //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) +//sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) //sys Rename(from string, to string) (err error) +//sys Renameat(fromfd int, from string, tofd int, to string) (err error) //sys Revoke(path string) (err error) //sys Rmdir(path string) (err error) //sys Seek(fd int, offset int64, whence int) (newoffset int64, err error) = SYS_LSEEK @@ -295,10 +302,12 @@ func Uname(uname *Utsname) error { //sys Stat(path string, stat *Stat_t) (err error) //sys Statfs(path string, stat *Statfs_t) (err error) //sys Symlink(path string, link string) (err error) +//sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error) //sys Sync() (err error) //sys Truncate(path string, length int64) (err error) //sys Umask(newmask int) (oldmask int) //sys Unlink(path string) (err error) +//sys Unlinkat(dirfd int, path string, flags int) (err error) //sys Unmount(path string, flags int) (err error) //sys write(fd int, p []byte) (n int, err error) //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) @@ -321,15 +330,11 @@ func Uname(uname *Utsname) error { // clock_settime // closefrom // execve -// faccessat -// fchmodat -// fchownat // fcntl // fhopen // fhstat // fhstatfs // fork -// fstatat // futimens // getfh // getgid @@ -343,12 +348,8 @@ func Uname(uname *Utsname) error { // lfs_markv // lfs_segclean // lfs_segwait -// linkat // mincore // minherit -// mkdirat -// mkfifoat -// mknodat // mount // mquery // msgctl @@ -361,7 +362,6 @@ func Uname(uname *Utsname) error { // profil // pwritev // quotactl -// readlinkat // readv // reboot // renameat @@ -382,13 +382,11 @@ func Uname(uname *Utsname) error { // sigprocmask // sigreturn // sigsuspend -// symlinkat // sysarch // syscall // threxit // thrsigdivert // thrsleep // thrwakeup -// unlinkat // vfork // writev diff --git a/vendor/golang.org/x/sys/unix/xattr_bsd.go b/vendor/golang.org/x/sys/unix/xattr_bsd.go index 930499324..30c1d71f4 100644 --- a/vendor/golang.org/x/sys/unix/xattr_bsd.go +++ b/vendor/golang.org/x/sys/unix/xattr_bsd.go @@ -81,7 +81,10 @@ func Lgetxattr(link string, attr string, dest []byte) (sz int, err error) { // flags are unused on FreeBSD func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) { - d := unsafe.Pointer(&data[0]) + var d unsafe.Pointer + if len(data) > 0 { + d = unsafe.Pointer(&data[0]) + } datasiz := len(data) nsid, a, err := xattrnamespace(attr) @@ -94,7 +97,10 @@ func Fsetxattr(fd int, attr string, data []byte, flags int) (err error) { } func Setxattr(file string, attr string, data []byte, flags int) (err error) { - d := unsafe.Pointer(&data[0]) + var d unsafe.Pointer + if len(data) > 0 { + d = unsafe.Pointer(&data[0]) + } datasiz := len(data) nsid, a, err := xattrnamespace(attr) @@ -107,7 +113,10 @@ func Setxattr(file string, attr string, data []byte, flags int) (err error) { } func Lsetxattr(link string, attr string, data []byte, flags int) (err error) { - d := unsafe.Pointer(&data[0]) + var d unsafe.Pointer + if len(data) > 0 { + d = unsafe.Pointer(&data[0]) + } datasiz := len(data) nsid, a, err := xattrnamespace(attr) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go index 12da7b41f..96a671344 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_dragonfly_amd64.go @@ -588,6 +588,21 @@ func Exit(code int) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Faccessat(dirfd int, path string, mode uint32, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FACCESSAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(flags), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fchdir(fd int) (err error) { _, _, e1 := Syscall(SYS_FCHDIR, uintptr(fd), 0, 0) if e1 != 0 { @@ -643,6 +658,21 @@ func Fchown(fd int, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -927,6 +957,26 @@ func Link(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Listen(s int, backlog int) (err error) { _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) if e1 != 0 { @@ -967,6 +1017,21 @@ func Mkdir(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mkfifo(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -997,6 +1062,21 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mknodat(fd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(fd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1361,6 +1441,26 @@ func Symlink(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Sync() (err error) { _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) if e1 != 0 { @@ -1424,6 +1524,21 @@ func Unlink(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Unmount(path string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go index c0d856c55..9ed7c71fb 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_386.go @@ -865,6 +865,21 @@ func Fchown(fd int, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -1114,6 +1129,26 @@ func Link(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Listen(s int, backlog int) (err error) { _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) if e1 != 0 { @@ -1154,6 +1189,21 @@ func Mkdir(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mkfifo(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1169,6 +1219,21 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mknod(path string, mode uint32, dev int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1184,6 +1249,21 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1315,6 +1395,28 @@ func Readlink(path string, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Rename(from string, to string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(from) @@ -1335,6 +1437,26 @@ func Rename(from string, to string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Revoke(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1532,6 +1654,26 @@ func Symlink(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Sync() (err error) { _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) if e1 != 0 { @@ -1580,6 +1722,21 @@ func Unlink(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Unmount(path string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go index 1466a8ca1..613b7fd99 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_amd64.go @@ -865,6 +865,21 @@ func Fchown(fd int, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -1114,6 +1129,26 @@ func Link(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Listen(s int, backlog int) (err error) { _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) if e1 != 0 { @@ -1154,6 +1189,21 @@ func Mkdir(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mkfifo(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1169,6 +1219,21 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mknod(path string, mode uint32, dev int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1184,6 +1249,21 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1315,6 +1395,28 @@ func Readlink(path string, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Rename(from string, to string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(from) @@ -1335,6 +1437,26 @@ func Rename(from string, to string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Revoke(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1532,6 +1654,26 @@ func Symlink(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Sync() (err error) { _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) if e1 != 0 { @@ -1580,6 +1722,21 @@ func Unlink(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Unmount(path string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go index 2ca54f029..084750878 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_netbsd_arm.go @@ -865,6 +865,21 @@ func Fchown(fd int, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -1114,6 +1129,26 @@ func Link(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Listen(s int, backlog int) (err error) { _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) if e1 != 0 { @@ -1154,6 +1189,21 @@ func Mkdir(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mkfifo(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1169,6 +1219,21 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mknod(path string, mode uint32, dev int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1184,6 +1249,21 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1315,6 +1395,28 @@ func Readlink(path string, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Rename(from string, to string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(from) @@ -1335,6 +1437,26 @@ func Rename(from string, to string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Revoke(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1532,6 +1654,26 @@ func Symlink(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Sync() (err error) { _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) if e1 != 0 { @@ -1580,6 +1722,21 @@ func Unlink(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Unmount(path string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index 082235681..414cd13c8 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -650,6 +650,21 @@ func Fchown(fd int, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -920,6 +935,26 @@ func Link(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Listen(s int, backlog int) (err error) { _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) if e1 != 0 { @@ -960,6 +995,21 @@ func Mkdir(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mkfifo(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -975,6 +1025,21 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mknod(path string, mode uint32, dev int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -990,6 +1055,21 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1121,6 +1201,28 @@ func Readlink(path string, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Rename(from string, to string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(from) @@ -1141,6 +1243,26 @@ func Rename(from string, to string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Revoke(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1398,6 +1520,26 @@ func Symlink(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Sync() (err error) { _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) if e1 != 0 { @@ -1446,6 +1588,21 @@ func Unlink(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Unmount(path string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index 3d0bae427..846f5fa64 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -650,6 +650,21 @@ func Fchown(fd int, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -920,6 +935,26 @@ func Link(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Listen(s int, backlog int) (err error) { _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) if e1 != 0 { @@ -960,6 +995,21 @@ func Mkdir(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mkfifo(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -975,6 +1025,21 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mknod(path string, mode uint32, dev int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -990,6 +1055,21 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1121,6 +1201,28 @@ func Readlink(path string, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Rename(from string, to string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(from) @@ -1141,6 +1243,26 @@ func Rename(from string, to string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Revoke(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1398,6 +1520,26 @@ func Symlink(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Sync() (err error) { _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) if e1 != 0 { @@ -1446,6 +1588,21 @@ func Unlink(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Unmount(path string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index 6422c4605..59911659d 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -650,6 +650,21 @@ func Fchown(fd int, uid int, gid int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_FCHOWNAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(uid), uintptr(gid), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Flock(fd int, how int) (err error) { _, _, e1 := Syscall(SYS_FLOCK, uintptr(fd), uintptr(how), 0) if e1 != 0 { @@ -920,6 +935,26 @@ func Link(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Linkat(pathfd int, path string, linkfd int, link string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(link) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_LINKAT, uintptr(pathfd), uintptr(unsafe.Pointer(_p0)), uintptr(linkfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Listen(s int, backlog int) (err error) { _, _, e1 := Syscall(SYS_LISTEN, uintptr(s), uintptr(backlog), 0) if e1 != 0 { @@ -960,6 +995,21 @@ func Mkdir(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkdirat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKDIRAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mkfifo(path string, mode uint32) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -975,6 +1025,21 @@ func Mkfifo(path string, mode uint32) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mkfifoat(dirfd int, path string, mode uint32) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_MKFIFOAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Mknod(path string, mode uint32, dev int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -990,6 +1055,21 @@ func Mknod(path string, mode uint32, dev int) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Mknodat(dirfd int, path string, mode uint32, dev int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_MKNODAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(dev), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Nanosleep(time *Timespec, leftover *Timespec) (err error) { _, _, e1 := Syscall(SYS_NANOSLEEP, uintptr(unsafe.Pointer(time)), uintptr(unsafe.Pointer(leftover)), 0) if e1 != 0 { @@ -1121,6 +1201,28 @@ func Readlink(path string, buf []byte) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Readlinkat(dirfd int, path string, buf []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(buf) > 0 { + _p1 = unsafe.Pointer(&buf[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_READLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(buf)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Rename(from string, to string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(from) @@ -1141,6 +1243,26 @@ func Rename(from string, to string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Renameat(fromfd int, from string, tofd int, to string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(from) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(to) + if err != nil { + return + } + _, _, e1 := Syscall6(SYS_RENAMEAT, uintptr(fromfd), uintptr(unsafe.Pointer(_p0)), uintptr(tofd), uintptr(unsafe.Pointer(_p1)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Revoke(path string) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1398,6 +1520,26 @@ func Symlink(path string, link string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Symlinkat(oldpath string, newdirfd int, newpath string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(oldpath) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(newpath) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_SYMLINKAT, uintptr(unsafe.Pointer(_p0)), uintptr(newdirfd), uintptr(unsafe.Pointer(_p1))) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Sync() (err error) { _, _, e1 := Syscall(SYS_SYNC, 0, 0, 0) if e1 != 0 { @@ -1446,6 +1588,21 @@ func Unlink(path string) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Unlinkat(dirfd int, path string, flags int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := Syscall(SYS_UNLINKAT, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Unmount(path string, flags int) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/worker/db.go b/worker/db.go index a49209bb8..87f0b186f 100644 --- a/worker/db.go +++ b/worker/db.go @@ -39,6 +39,7 @@ import ( "github.com/CovenantSQL/CovenantSQL/utils/log" wt "github.com/CovenantSQL/CovenantSQL/worker/types" "github.com/CovenantSQL/sqlparser" + "github.com/pkg/errors" ) const ( @@ -193,7 +194,7 @@ func (db *Database) Query(request *wt.Request) (response *wt.Response, err error return db.writeQuery(request) default: // TODO(xq262144): verbose errors with custom error structure - return nil, ErrInvalidRequest + return nil, errors.Wrap(ErrInvalidRequest, "invalid query type") } } @@ -287,13 +288,22 @@ func (db *Database) writeQuery(request *wt.Request) (response *wt.Response, err } var logOffset uint64 - logOffset, err = db.kayakRuntime.Apply(buf.Bytes()) + var result interface{} + result, logOffset, err = db.kayakRuntime.Apply(buf.Bytes()) if err != nil { return } - return db.buildQueryResponse(request, logOffset, []string{}, []string{}, [][]interface{}{}) + // get affected rows and last insert id + var affectedRows, lastInsertID int64 + + if execResult, ok := result.(storage.ExecResult); ok { + affectedRows = execResult.RowsAffected + lastInsertID = execResult.LastInsertID + } + + return db.buildQueryResponse(request, logOffset, []string{}, []string{}, [][]interface{}{}, lastInsertID, affectedRows) } func (db *Database) readQuery(request *wt.Request) (response *wt.Response, err error) { @@ -313,11 +323,11 @@ func (db *Database) readQuery(request *wt.Request) (response *wt.Response, err e return } - return db.buildQueryResponse(request, 0, columns, types, data) + return db.buildQueryResponse(request, 0, columns, types, data, 0, 0) } func (db *Database) buildQueryResponse(request *wt.Request, offset uint64, - columns []string, types []string, data [][]interface{}) (response *wt.Response, err error) { + columns []string, types []string, data [][]interface{}, lastInsertID int64, affectedRows int64) (response *wt.Response, err error) { // build response response = new(wt.Response) response.Header.Request = request.Header @@ -327,6 +337,8 @@ func (db *Database) buildQueryResponse(request *wt.Request, offset uint64, response.Header.LogOffset = offset response.Header.Timestamp = getLocalTime() response.Header.RowCount = uint64(len(data)) + response.Header.LastInsertID = lastInsertID + response.Header.AffectedRows = affectedRows // set payload response.Payload.Columns = columns diff --git a/worker/db_storage.go b/worker/db_storage.go index 6407e9c0d..837783e6e 100644 --- a/worker/db_storage.go +++ b/worker/db_storage.go @@ -24,6 +24,7 @@ import ( "github.com/CovenantSQL/CovenantSQL/twopc" "github.com/CovenantSQL/CovenantSQL/utils" wt "github.com/CovenantSQL/CovenantSQL/worker/types" + "github.com/pkg/errors" ) // Following contains storage related logic extracted from main database instance definition. @@ -39,7 +40,7 @@ func (db *Database) Prepare(ctx context.Context, wb twopc.WriteBatch) (err error } // Commit implements twopc.Worker.Commmit. -func (db *Database) Commit(ctx context.Context, wb twopc.WriteBatch) (err error) { +func (db *Database) Commit(ctx context.Context, wb twopc.WriteBatch) (result interface{}, err error) { // wrap storage with signature check var log *storage.ExecLog if log, err = db.convertRequest(wb); err != nil { @@ -86,7 +87,7 @@ func (db *Database) convertRequest(wb twopc.WriteBatch) (log *storage.ExecLog, e // type convert var payloadBytes []byte if payloadBytes, ok = wb.([]byte); !ok { - err = ErrInvalidRequest + err = errors.Wrap(ErrInvalidRequest, "invalid request payload") return } @@ -107,7 +108,7 @@ func (db *Database) convertRequest(wb twopc.WriteBatch) (log *storage.ExecLog, e maxTime := nowTime.Add(db.cfg.MaxWriteTimeGap) if req.Header.Timestamp.Before(minTime) || req.Header.Timestamp.After(maxTime) { - err = ErrInvalidRequest + err = errors.Wrap(ErrInvalidRequest, "invalid request time") return } diff --git a/worker/dbms_rpc.go b/worker/dbms_rpc.go index b75cc9407..1daffa148 100644 --- a/worker/dbms_rpc.go +++ b/worker/dbms_rpc.go @@ -23,6 +23,7 @@ import ( "github.com/CovenantSQL/CovenantSQL/route" "github.com/CovenantSQL/CovenantSQL/rpc" wt "github.com/CovenantSQL/CovenantSQL/worker/types" + "github.com/pkg/errors" "github.com/rcrowley/go-metrics" ) @@ -65,7 +66,7 @@ func (rpc *DBMSRPCService) Query(req *wt.Request, res *wt.Response) (err error) // verify query is sent from the request node if req.Envelope.NodeID.String() != string(req.Header.NodeID) { // node id mismatch - err = ErrInvalidRequest + err = errors.Wrap(ErrInvalidRequest, "request node id mismatch in query") dbQueryFailCounter.Mark(1) return } @@ -95,7 +96,7 @@ func (rpc *DBMSRPCService) Ack(ack *wt.Ack, _ *wt.AckResponse) (err error) { // verify if ack node is the original ack node if ack.Envelope.NodeID.String() != string(ack.Header.Response.Request.NodeID) { - err = ErrInvalidRequest + err = errors.Wrap(ErrInvalidRequest, "request node id mismatch in ack") return } @@ -109,7 +110,7 @@ func (rpc *DBMSRPCService) Ack(ack *wt.Ack, _ *wt.AckResponse) (err error) { func (rpc *DBMSRPCService) Deploy(req *wt.UpdateService, _ *wt.UpdateServiceResponse) (err error) { // verify request node is block producer if !route.IsPermitted(&req.Envelope, route.DBSDeploy) { - err = ErrInvalidRequest + err = errors.Wrap(ErrInvalidRequest, "node not permitted for deploy request") return } diff --git a/worker/types/response_type.go b/worker/types/response_type.go index 1f0d3ee77..093fe4749 100644 --- a/worker/types/response_type.go +++ b/worker/types/response_type.go @@ -44,12 +44,14 @@ type ResponsePayload struct { // ResponseHeader defines a query response header. type ResponseHeader struct { - Request SignedRequestHeader `json:"r"` - NodeID proto.NodeID `json:"id"` // response node id - Timestamp time.Time `json:"t"` // time in UTC zone - RowCount uint64 `json:"c"` // response row count of payload - LogOffset uint64 `json:"o"` // request log offset - DataHash hash.Hash `json:"dh"` // hash of query response + Request SignedRequestHeader `json:"r"` + NodeID proto.NodeID `json:"id"` // response node id + Timestamp time.Time `json:"t"` // time in UTC zone + RowCount uint64 `json:"c"` // response row count of payload + LogOffset uint64 `json:"o"` // request log offset + LastInsertID int64 `json:"l"` // insert insert id + AffectedRows int64 `json:"a"` // affected rows + DataHash hash.Hash `json:"dh"` // hash of query response } // SignedResponseHeader defines a signed query response header. diff --git a/worker/types/response_type_gen.go b/worker/types/response_type_gen.go index 8ce0f4c36..07a3d20fa 100644 --- a/worker/types/response_type_gen.go +++ b/worker/types/response_type_gen.go @@ -36,37 +36,41 @@ func (z *Response) Msgsize() (s int) { func (z *ResponseHeader) MarshalHash() (o []byte, err error) { var b []byte o = hsp.Require(b, z.Msgsize()) - // map header, size 6 - o = append(o, 0x86, 0x86) + // map header, size 8 + o = append(o, 0x88, 0x88) if oTemp, err := z.Request.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x86) + o = append(o, 0x88) if oTemp, err := z.DataHash.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x86) + o = append(o, 0x88) + o = hsp.AppendInt64(o, z.LastInsertID) + o = append(o, 0x88) + o = hsp.AppendInt64(o, z.AffectedRows) + o = append(o, 0x88) if oTemp, err := z.NodeID.MarshalHash(); err != nil { return nil, err } else { o = hsp.AppendBytes(o, oTemp) } - o = append(o, 0x86) + o = append(o, 0x88) o = hsp.AppendTime(o, z.Timestamp) - o = append(o, 0x86) + o = append(o, 0x88) o = hsp.AppendUint64(o, z.RowCount) - o = append(o, 0x86) + o = append(o, 0x88) o = hsp.AppendUint64(o, z.LogOffset) return } // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message func (z *ResponseHeader) Msgsize() (s int) { - s = 1 + 8 + z.Request.Msgsize() + 9 + z.DataHash.Msgsize() + 7 + z.NodeID.Msgsize() + 10 + hsp.TimeSize + 9 + hsp.Uint64Size + 10 + hsp.Uint64Size + s = 1 + 8 + z.Request.Msgsize() + 9 + z.DataHash.Msgsize() + 13 + hsp.Int64Size + 13 + hsp.Int64Size + 7 + z.NodeID.Msgsize() + 10 + hsp.TimeSize + 9 + hsp.Uint64Size + 10 + hsp.Uint64Size return }