github.com/google/fleetspeak@v0.1.15-0.20240426164851-4f31f62c1aea/fleetspeak/src/server/mysql/filestore.go (about) 1 // Copyright 2017 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package mysql 16 17 import ( 18 "bytes" 19 "context" 20 "database/sql" 21 "io" 22 "time" 23 24 "github.com/google/fleetspeak/fleetspeak/src/server/db" 25 ) 26 27 func (d *Datastore) StoreFile(ctx context.Context, service, name string, data io.Reader) error { 28 b, err := io.ReadAll(data) 29 if err != nil { 30 return err 31 } 32 return d.runInTx(ctx, false, func(tx *sql.Tx) error { 33 _, err := tx.ExecContext(ctx, "REPLACE INTO files (service, name, modified_time_nanos, data) VALUES(?, ?, ?, ?)", 34 service, name, db.Now().UnixNano(), b) 35 return err 36 }) 37 } 38 39 func (d *Datastore) StatFile(ctx context.Context, service, name string) (time.Time, error) { 40 var ts int64 41 42 err := d.runInTx(ctx, true, func(tx *sql.Tx) error { 43 row := tx.QueryRowContext(ctx, "SELECT modified_time_nanos FROM files WHERE service = ? AND name = ?", service, name) 44 return row.Scan(&ts) 45 }) 46 47 return time.Unix(0, ts).UTC(), err 48 } 49 50 func (d *Datastore) ReadFile(ctx context.Context, service, name string) (data db.ReadSeekerCloser, modtime time.Time, err error) { 51 var b []byte 52 var ts int64 53 54 err = d.runInTx(ctx, true, func(tx *sql.Tx) error { 55 row := tx.QueryRowContext(ctx, "SELECT modified_time_nanos, data FROM files WHERE service = ? AND name = ?", service, name) 56 if err := row.Scan(&ts, &b); err != nil { 57 b = nil 58 return err 59 } 60 return nil 61 }) 62 63 if err != nil { 64 return nil, time.Time{}, err 65 } 66 if b == nil { 67 b = []byte{} 68 } 69 return db.NOOPCloser{ReadSeeker: bytes.NewReader(b)}, time.Unix(0, ts).UTC(), nil 70 }