Class: GDAL::CPLErrorHandler

Inherits:
Object
  • Object
show all
Includes:
Logger
Defined in:
lib/gdal/cpl_error_handler.rb

Overview

This is used to override GDAL’s built-in error handling. By default, GDAL only logs errors to STDOUT, which doesn’t allow a whole lot of flexibility. This maps GDAL’s errors to either standard Ruby exceptions or new exceptions defined in this gem. Doing so also lets ffi-gdal users rescue these exceptions, which is beneficial for obvious reasons.

Constant Summary collapse

CPLE_MAP =

NOTE: Error codes are defined in gdal.org/doxygen/cpl__error_8h_source.html

[
  { cple: :CPLE_None,                     exception: nil }.freeze,
  { cple: :CPLE_AppDefined,               exception: GDAL::Error }.freeze,
  { cple: :CPLE_OutOfMemory,              exception: ::NoMemoryError }.freeze,
  { cple: :CPLE_FileIO,                   exception: ::IOError }.freeze,
  { cple: :CPLE_OpenFailed,               exception: GDAL::OpenFailure }.freeze,
  { cple: :CPLE_IllegalArg,               exception: ::ArgumentError }.freeze,
  { cple: :CPLE_NotSupported,             exception: GDAL::UnsupportedOperation }.freeze,
  { cple: :CPLE_AssertionFailed,          exception: ::RuntimeError }.freeze,
  { cple: :CPLE_NoWriteAccess,            exception: GDAL::NoWriteAccess }.freeze,
  { cple: :CPLE_UserInterrupt,            exception: ::Interrupt }.freeze,
  { cple: :CPLE_ObjectNull,               exception: GDAL::NullObject }.freeze,
  { cple: :CPLE_HttpResponse,             exception: GDAL::HttpResponse }.freeze,
  { cple: :CPLE_AWSBucketNotFound,        exception: GDAL::AWSBucketNotFound }.freeze,
  { cple: :CPLE_AWSObjectNotFound,        exception: GDAL::AWSObjectNotFound }.freeze,
  { cple: :CPLE_AWSAccessDenied,          exception: GDAL::AWSAccessDenied }.freeze,
  { cple: :CPLE_AWSInvalidCredentials,    exception: GDAL::AWSInvalidCredentials }.freeze,
  { cple: :CPLE_AWSSignatureDoesNotMatch, exception: GDAL::AWSSignatureDoesNotMatch }.freeze
].freeze
FALLBACK_CPLE_EXCEPTION =
{ exception: GDAL::Error }.freeze
FAIL_PROC =
lambda do |exception, message|
  ex = exception ? exception.new(message) : GDAL::Error.new(message)
  ex.set_backtrace(caller(3))

  raise(ex)
end
SUCCESS_PROC =
proc { true }

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeCPLErrorHandler



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/gdal/cpl_error_handler.rb', line 74

def initialize
  @on_none = SUCCESS_PROC

  @on_debug = lambda do |_, message|
    logger.debug(message)
    true
  end

  @on_warning = lambda do |_, message|
    logger.warn(message)
    true
  end

  @on_failure = FAIL_PROC
  @on_fatal = FAIL_PROC
end

Instance Attribute Details

#on_debugProc



63
64
65
# File 'lib/gdal/cpl_error_handler.rb', line 63

def on_debug
  @on_debug
end

#on_failureProc



69
70
71
# File 'lib/gdal/cpl_error_handler.rb', line 69

def on_failure
  @on_failure
end

#on_fatalProc



72
73
74
# File 'lib/gdal/cpl_error_handler.rb', line 72

def on_fatal
  @on_fatal
end

#on_noneProc



60
61
62
# File 'lib/gdal/cpl_error_handler.rb', line 60

def on_none
  @on_none
end

#on_warningProc



66
67
68
# File 'lib/gdal/cpl_error_handler.rb', line 66

def on_warning
  @on_warning
end

Class Method Details

.handle_errorProc



44
45
46
# File 'lib/gdal/cpl_error_handler.rb', line 44

def self.handle_error
  new.handler_lambda
end

.manually_handle(message) ⇒ Object

Raises:



51
52
53
54
55
56
57
# File 'lib/gdal/cpl_error_handler.rb', line 51

def self.manually_handle(message)
  cpl_err = yield

  case cpl_err
  when :CE_Fatal, :CE_Failure then raise GDAL::Error, message
  end
end

Instance Method Details

#custom_handleObject

Use this when you want to override the default event handling. For example, you may want to return a value in the case of a :CE_Warning. To do so, you need to create a new ErrorHandler object, assign a new Proc by calling #on_warning=, then call this method with your wrapped CPLErr-returning function in a block. That might look something like:

handler = GDAL::ErrorHandler.new
handler.on_warning = -> { warn 'Uh oh!'; return Array.new }
handler.custom_handle do
  FFI::GDAL.DoSomeStuff()
end

After this code gets called, error handling will return to normal.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/gdal/cpl_error_handler.rb', line 118

def custom_handle
  FFI::CPL::Error.CPLPushErrorHandler(handler_lambda)
  yield

  msg, ptr = FFI::CPL::Error.CPLGetLastErrorMsg
  ptr.autorelease = false

  r = result(FFI::CPL::Error.CPLGetLastErrorType,
             FFI::CPL::Error.CPLGetLastErrorNo,
             msg)
  FFI::CPL::Error.CPLErrorReset
  FFI::CPL::Error.CPLPopErrorHandler

  r
end

#handler_lambdaProc

Looks up the error class then calls the appropriate on_ proc, thus handling various error/non-error scenarios. More info here: www.gdal.org/cpl__error_8h.html#a74d0e649d58180e621540bf73b58e4a2.



96
97
98
99
100
101
102
103
# File 'lib/gdal/cpl_error_handler.rb', line 96

def handler_lambda
  @handler_lambda ||= lambda do |error_class, error_number, message|
    r = result(error_class, error_number, message)
    FFI::CPL::Error.CPLErrorReset

    r
  end
end