utils.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /*
  2. * Copyright (c) 2016, Psiphon Inc.
  3. * All rights reserved.
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package server
  20. import (
  21. "fmt"
  22. "io"
  23. "sync/atomic"
  24. )
  25. // IntentionalPanicError is an error type that is used
  26. // when calling panic() in a situation where recovers
  27. // should propagate the panic.
  28. type IntentionalPanicError struct {
  29. message string
  30. }
  31. // NewIntentionalPanicError creates a new IntentionalPanicError.
  32. func NewIntentionalPanicError(errorMessage string) error {
  33. return IntentionalPanicError{
  34. message: fmt.Sprintf("intentional panic error: %s", errorMessage)}
  35. }
  36. // Error implements the error interface.
  37. func (err IntentionalPanicError) Error() string {
  38. return err.message
  39. }
  40. // PanickingLogWriter wraps an io.Writer and intentionally
  41. // panics when a Write() fails.
  42. type PanickingLogWriter struct {
  43. name string
  44. writer io.Writer
  45. }
  46. // NewPanickingLogWriter creates a new PanickingLogWriter.
  47. func NewPanickingLogWriter(
  48. name string, writer io.Writer) *PanickingLogWriter {
  49. return &PanickingLogWriter{
  50. name: name,
  51. writer: writer,
  52. }
  53. }
  54. // Write implements the io.Writer interface.
  55. func (w *PanickingLogWriter) Write(p []byte) (n int, err error) {
  56. n, err = w.writer.Write(p)
  57. if err != nil {
  58. panic(
  59. NewIntentionalPanicError(
  60. fmt.Sprintf("fatal write to %s failed: %s", w.name, err)))
  61. }
  62. return
  63. }
  64. func min(a, b int) int {
  65. if a < b {
  66. return a
  67. }
  68. return b
  69. }
  70. func greaterThanSwapInt64(addr *int64, new int64) bool {
  71. old := atomic.LoadInt64(addr)
  72. if new > old {
  73. return atomic.CompareAndSwapInt64(addr, old, new)
  74. }
  75. return false
  76. }