( ctx context.Context, req *types.Request)
| 247 | } |
| 248 | |
| 249 | func (s *State) readTx( |
| 250 | ctx context.Context, req *types.Request) (ref *QueryTracker, resp *types.Response, err error, |
| 251 | ) { |
| 252 | var ( |
| 253 | id = s.getSeq() |
| 254 | ierr error |
| 255 | cnames, ctypes []string |
| 256 | data [][]interface{} |
| 257 | querier sqlQuerier |
| 258 | ) |
| 259 | if s.level == sql.LevelReadUncommitted && atomic.LoadUint32(&s.hasSchemaChange) == 1 { |
| 260 | // lock transaction |
| 261 | s.Lock() |
| 262 | defer s.Unlock() |
| 263 | querier = s.handler |
| 264 | } else { |
| 265 | var tx *sql.Tx |
| 266 | if tx, ierr = s.reader().Begin(); ierr != nil { |
| 267 | err = errors.Wrap(ierr, "open tx failed") |
| 268 | return |
| 269 | } |
| 270 | querier = tx |
| 271 | defer func() { |
| 272 | _ = tx.Rollback() |
| 273 | }() |
| 274 | } |
| 275 | |
| 276 | defer func() { |
| 277 | if ctx.Err() != nil { |
| 278 | log.WithError(ctx.Err()).WithFields(log.Fields{ |
| 279 | "req": req, |
| 280 | "id": id, |
| 281 | "dirtyRead": atomic.LoadUint32(&s.hasSchemaChange) != 1, |
| 282 | }).Warning("read query canceled") |
| 283 | } |
| 284 | }() |
| 285 | |
| 286 | for i, v := range req.Payload.Queries { |
| 287 | if cnames, ctypes, data, ierr = readSingle(ctx, querier, &v); ierr != nil { |
| 288 | err = errors.Wrapf(ierr, "query at #%d failed", i) |
| 289 | // Add to failed pool list |
| 290 | s.Lock() |
| 291 | s.pool.setFailed(req) |
| 292 | s.Unlock() |
| 293 | return |
| 294 | } |
| 295 | } |
| 296 | // Build query response |
| 297 | ref = &QueryTracker{Req: req} |
| 298 | s.Lock() |
| 299 | s.pool.enqueueRead(ref) |
| 300 | s.Unlock() |
| 301 | resp = &types.Response{ |
| 302 | Header: types.SignedResponseHeader{ |
| 303 | ResponseHeader: types.ResponseHeader{ |
| 304 | Request: req.Header.RequestHeader, |
| 305 | RequestHash: req.Header.Hash(), |
| 306 | NodeID: s.nodeID, |
no test coverage detected