OLD | NEW |
1 // Copyright 2015 The LUCI Authors. All rights reserved. | 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
2 // Use of this source code is governed under the Apache License, Version 2.0 | 2 // Use of this source code is governed under the Apache License, Version 2.0 |
3 // that can be found in the LICENSE file. | 3 // that can be found in the LICENSE file. |
4 | 4 |
5 package caching | 5 package caching |
6 | 6 |
7 import ( | 7 import ( |
8 "fmt" | 8 "fmt" |
9 "net/url" | 9 "net/url" |
10 "strings" | 10 "strings" |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 for i := range v.Items { | 195 for i := range v.Items { |
196 res[i] = v.Items[i].ConfigItem() | 196 res[i] = v.Items[i].ConfigItem() |
197 } | 197 } |
198 return res | 198 return res |
199 } | 199 } |
200 | 200 |
201 // DecodeValue loads a Value from is encoded representation. | 201 // DecodeValue loads a Value from is encoded representation. |
202 func DecodeValue(d []byte) (*Value, error) { | 202 func DecodeValue(d []byte) (*Value, error) { |
203 var v Value | 203 var v Value |
204 if err := Decode(d, &v); err != nil { | 204 if err := Decode(d, &v); err != nil { |
205 » » return nil, errors.Annotate(err).Err() | 205 » » return nil, errors.Annotate(err, "").Err() |
206 } | 206 } |
207 return &v, nil | 207 return &v, nil |
208 } | 208 } |
209 | 209 |
210 // Encode encodes this Value. | 210 // Encode encodes this Value. |
211 // | 211 // |
212 // This is offered for convenience, but caches aren't required to use this | 212 // This is offered for convenience, but caches aren't required to use this |
213 // encoding. | 213 // encoding. |
214 // | 214 // |
215 // The format stores the Value as compressed JSON. | 215 // The format stores the Value as compressed JSON. |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 } | 283 } |
284 value, err := b.CacheGet(c, key, b.loader) | 284 value, err := b.CacheGet(c, key, b.loader) |
285 if err != nil { | 285 if err != nil { |
286 if b.FailOnError { | 286 if b.FailOnError { |
287 log.Fields{ | 287 log.Fields{ |
288 log.ErrorKey: err, | 288 log.ErrorKey: err, |
289 "authority": p.Authority, | 289 "authority": p.Authority, |
290 "configSet": configSet, | 290 "configSet": configSet, |
291 "path": path, | 291 "path": path, |
292 }.Errorf(c, "(Hard Failure) failed to load cache value."
) | 292 }.Errorf(c, "(Hard Failure) failed to load cache value."
) |
293 » » » return nil, errors.Annotate(err).Err() | 293 » » » return nil, errors.Annotate(err, "").Err() |
294 } | 294 } |
295 | 295 |
296 log.Fields{ | 296 log.Fields{ |
297 log.ErrorKey: err, | 297 log.ErrorKey: err, |
298 "authority": p.Authority, | 298 "authority": p.Authority, |
299 "configSet": configSet, | 299 "configSet": configSet, |
300 "path": path, | 300 "path": path, |
301 }.Warningf(c, "Failed to load cache value.") | 301 }.Warningf(c, "Failed to load cache value.") |
302 return b.B.Get(c, configSet, path, p) | 302 return b.B.Get(c, configSet, path, p) |
303 } | 303 } |
(...skipping 21 matching lines...) Expand all Loading... |
325 } | 325 } |
326 value, err := b.CacheGet(c, key, b.loader) | 326 value, err := b.CacheGet(c, key, b.loader) |
327 if err != nil { | 327 if err != nil { |
328 if b.FailOnError { | 328 if b.FailOnError { |
329 log.Fields{ | 329 log.Fields{ |
330 log.ErrorKey: err, | 330 log.ErrorKey: err, |
331 "authority": p.Authority, | 331 "authority": p.Authority, |
332 "type": t, | 332 "type": t, |
333 "path": path, | 333 "path": path, |
334 }.Errorf(c, "(Hard Failure) failed to load cache value."
) | 334 }.Errorf(c, "(Hard Failure) failed to load cache value."
) |
335 » » » return nil, errors.Annotate(err).Err() | 335 » » » return nil, errors.Annotate(err, "").Err() |
336 } | 336 } |
337 | 337 |
338 log.Fields{ | 338 log.Fields{ |
339 log.ErrorKey: err, | 339 log.ErrorKey: err, |
340 "authority": p.Authority, | 340 "authority": p.Authority, |
341 "type": t, | 341 "type": t, |
342 "path": path, | 342 "path": path, |
343 }.Warningf(c, "Failed to load cache value.") | 343 }.Warningf(c, "Failed to load cache value.") |
344 return b.B.GetAll(c, t, path, p) | 344 return b.B.GetAll(c, t, path, p) |
345 } | 345 } |
(...skipping 11 matching lines...) Expand all Loading... |
357 } | 357 } |
358 | 358 |
359 var value *Value | 359 var value *Value |
360 if value, err = b.CacheGet(c, key, b.loader); err != nil { | 360 if value, err = b.CacheGet(c, key, b.loader); err != nil { |
361 if b.FailOnError { | 361 if b.FailOnError { |
362 log.Fields{ | 362 log.Fields{ |
363 log.ErrorKey: err, | 363 log.ErrorKey: err, |
364 "authority": p.Authority, | 364 "authority": p.Authority, |
365 "configSet": configSet, | 365 "configSet": configSet, |
366 }.Errorf(c, "(Hard Failure) failed to load cache value."
) | 366 }.Errorf(c, "(Hard Failure) failed to load cache value."
) |
367 » » » err = errors.Annotate(err).Err() | 367 » » » err = errors.Annotate(err, "").Err() |
368 return | 368 return |
369 } | 369 } |
370 | 370 |
371 log.Fields{ | 371 log.Fields{ |
372 log.ErrorKey: err, | 372 log.ErrorKey: err, |
373 "authority": p.Authority, | 373 "authority": p.Authority, |
374 "configSet": configSet, | 374 "configSet": configSet, |
375 }.Warningf(c, "Failed to load cache value.") | 375 }.Warningf(c, "Failed to load cache value.") |
376 return b.B.ConfigSetURL(c, configSet, p) | 376 return b.B.ConfigSetURL(c, configSet, p) |
377 } | 377 } |
378 | 378 |
379 if value.URL == "" { | 379 if value.URL == "" { |
380 // Sentinel for no config. | 380 // Sentinel for no config. |
381 err = cfgclient.ErrNoConfig | 381 err = cfgclient.ErrNoConfig |
382 return | 382 return |
383 } | 383 } |
384 | 384 |
385 up, err := url.Parse(value.URL) | 385 up, err := url.Parse(value.URL) |
386 if err != nil { | 386 if err != nil { |
387 » » err = errors.Annotate(err).Reason("failed to parse cached URL: %
(value)q").D("value", value.URL).Err() | 387 » » err = errors.Annotate(err, "failed to parse cached URL: %q", val
ue.URL).Err() |
388 return | 388 return |
389 } | 389 } |
390 | 390 |
391 u = *up | 391 u = *up |
392 return | 392 return |
393 } | 393 } |
394 | 394 |
395 // loader runs a cache get against the configured Base backend. | 395 // loader runs a cache get against the configured Base backend. |
396 // | 396 // |
397 // This should be used by caches that do not have the cached value. | 397 // This should be used by caches that do not have the cached value. |
(...skipping 10 matching lines...) Expand all Loading... |
408 // instance. | 408 // instance. |
409 func CacheLoad(c context.Context, b backend.B, k Key, v *Value) (rv *Value, err
error) { | 409 func CacheLoad(c context.Context, b backend.B, k Key, v *Value) (rv *Value, err
error) { |
410 switch k.Op { | 410 switch k.Op { |
411 case OpGet: | 411 case OpGet: |
412 rv, err = doGet(c, b, k.ConfigSet, k.Path, v, k.Params()) | 412 rv, err = doGet(c, b, k.ConfigSet, k.Path, v, k.Params()) |
413 case OpGetAll: | 413 case OpGetAll: |
414 rv, err = doGetAll(c, b, k.GetAllTarget, k.Path, v, k.Params()) | 414 rv, err = doGetAll(c, b, k.GetAllTarget, k.Path, v, k.Params()) |
415 case OpConfigSetURL: | 415 case OpConfigSetURL: |
416 rv, err = doConfigSetURL(c, b, k.ConfigSet, k.Params()) | 416 rv, err = doConfigSetURL(c, b, k.ConfigSet, k.Params()) |
417 default: | 417 default: |
418 » » return nil, errors.Reason("unknown operation: %(op)v").D("op", k
.Op).Err() | 418 » » return nil, errors.Reason("unknown operation: %v", k.Op).Err() |
419 } | 419 } |
420 if err != nil { | 420 if err != nil { |
421 return nil, err | 421 return nil, err |
422 } | 422 } |
423 return | 423 return |
424 } | 424 } |
425 | 425 |
426 func doGet(c context.Context, b backend.B, configSet, path string, v *Value, p b
ackend.Params) (*Value, error) { | 426 func doGet(c context.Context, b backend.B, configSet, path string, v *Value, p b
ackend.Params) (*Value, error) { |
427 hadItem := (v != nil && len(v.Items) > 0) | 427 hadItem := (v != nil && len(v.Items) > 0) |
428 if !hadItem { | 428 if !hadItem { |
(...skipping 23 matching lines...) Expand all Loading... |
452 | 452 |
453 // If we get here, we are requesting full-content and ou
r hash check | 453 // If we get here, we are requesting full-content and ou
r hash check |
454 // showed that the current content has a different hash. | 454 // showed that the current content has a different hash. |
455 break | 455 break |
456 | 456 |
457 case cfgclient.ErrNoConfig: | 457 case cfgclient.ErrNoConfig: |
458 v.LoadItems() | 458 v.LoadItems() |
459 return v, nil | 459 return v, nil |
460 | 460 |
461 default: | 461 default: |
462 » » » return nil, errors.Annotate(err).Err() | 462 » » » return nil, errors.Annotate(err, "").Err() |
463 } | 463 } |
464 } | 464 } |
465 | 465 |
466 // Perform a full content request. | 466 // Perform a full content request. |
467 switch item, err := b.Get(c, configSet, path, p); err { | 467 switch item, err := b.Get(c, configSet, path, p); err { |
468 case nil: | 468 case nil: |
469 v.LoadItems(item) | 469 v.LoadItems(item) |
470 return v, nil | 470 return v, nil |
471 | 471 |
472 case cfgclient.ErrNoConfig: | 472 case cfgclient.ErrNoConfig: |
473 // Empty "config missing" item. | 473 // Empty "config missing" item. |
474 v.LoadItems() | 474 v.LoadItems() |
475 return v, nil | 475 return v, nil |
476 | 476 |
477 default: | 477 default: |
478 » » return nil, errors.Annotate(err).Err() | 478 » » return nil, errors.Annotate(err, "").Err() |
479 } | 479 } |
480 } | 480 } |
481 | 481 |
482 func doGetAll(c context.Context, b backend.B, t backend.GetAllTarget, path strin
g, v *Value, p backend.Params) ( | 482 func doGetAll(c context.Context, b backend.B, t backend.GetAllTarget, path strin
g, v *Value, p backend.Params) ( |
483 *Value, error) { | 483 *Value, error) { |
484 | 484 |
485 // If we already have a cached value, or if we're requesting no-content,
do a | 485 // If we already have a cached value, or if we're requesting no-content,
do a |
486 // no-content refresh to see if anything has changed. | 486 // no-content refresh to see if anything has changed. |
487 // | 487 // |
488 // Response values are in order, so this is a simple traversal. | 488 // Response values are in order, so this is a simple traversal. |
489 if v != nil || !p.Content { | 489 if v != nil || !p.Content { |
490 noContentP := p | 490 noContentP := p |
491 noContentP.Content = false | 491 noContentP.Content = false |
492 | 492 |
493 items, err := b.GetAll(c, t, path, noContentP) | 493 items, err := b.GetAll(c, t, path, noContentP) |
494 if err != nil { | 494 if err != nil { |
495 » » » return nil, errors.Annotate(err).Reason("failed RPC (has
h-only)").Err() | 495 » » » return nil, errors.Annotate(err, "failed RPC (hash-only)
").Err() |
496 } | 496 } |
497 | 497 |
498 // If we already have a cached item, validate it. | 498 // If we already have a cached item, validate it. |
499 if v != nil && len(items) == len(v.Items) { | 499 if v != nil && len(items) == len(v.Items) { |
500 match := true | 500 match := true |
501 for i, other := range items { | 501 for i, other := range items { |
502 cur := v.Items[i] | 502 cur := v.Items[i] |
503 if cur.ConfigSet == other.ConfigSet && cur.Path
== other.Path && | 503 if cur.ConfigSet == other.ConfigSet && cur.Path
== other.Path && |
504 cur.ContentHash == other.ContentHash { | 504 cur.ContentHash == other.ContentHash { |
505 continue | 505 continue |
(...skipping 13 matching lines...) Expand all Loading... |
519 if !p.Content { | 519 if !p.Content { |
520 var retV Value | 520 var retV Value |
521 retV.LoadItems(items...) | 521 retV.LoadItems(items...) |
522 return &retV, nil | 522 return &retV, nil |
523 } | 523 } |
524 } | 524 } |
525 | 525 |
526 // Perform a full-content request. | 526 // Perform a full-content request. |
527 items, err := b.GetAll(c, t, path, p) | 527 items, err := b.GetAll(c, t, path, p) |
528 if err != nil { | 528 if err != nil { |
529 » » return nil, errors.Annotate(err).Err() | 529 » » return nil, errors.Annotate(err, "").Err() |
530 } | 530 } |
531 var retV Value | 531 var retV Value |
532 retV.LoadItems(items...) | 532 retV.LoadItems(items...) |
533 return &retV, nil | 533 return &retV, nil |
534 } | 534 } |
535 | 535 |
536 func doConfigSetURL(c context.Context, b backend.B, configSet string, p backend.
Params) (*Value, error) { | 536 func doConfigSetURL(c context.Context, b backend.B, configSet string, p backend.
Params) (*Value, error) { |
537 u, err := b.ConfigSetURL(c, configSet, p) | 537 u, err := b.ConfigSetURL(c, configSet, p) |
538 switch err { | 538 switch err { |
539 case nil: | 539 case nil: |
540 return &Value{ | 540 return &Value{ |
541 URL: u.String(), | 541 URL: u.String(), |
542 }, nil | 542 }, nil |
543 | 543 |
544 case cfgclient.ErrNoConfig: | 544 case cfgclient.ErrNoConfig: |
545 return &Value{}, nil | 545 return &Value{}, nil |
546 | 546 |
547 default: | 547 default: |
548 return nil, err | 548 return nil, err |
549 } | 549 } |
550 } | 550 } |
OLD | NEW |