@startuml
|ReserveDevice|
start
if (device matches requested media_type?) then (yes) <<#limegreen>>
  if (device initialized?) then (no)
    :InitDev(); <<procedure>>
  endif
  if (device exists and is open?) then (yes)
    :set suitable_device; <<task>> <<#aqua>>
    :initialize DCR;
    if (append?) then (no)
      :ReserveDeviceForRead(); <<procedure>>
    else (yes)
      |ReserveDeviceForAppend|
      if (CanRead()) then (no)
        if (IsDeviceUnmounted()) then (no)
          |CanReserveDrive|
          if (IsMaxJobsOk()) then (yes)
            if (any_drive set?) then (no) <<#aqua>>
              if (try_low_use_drive set?) then (yes) <<#aqua>>
                if (low_use_drive is current drive?) then (yes) <<#aqua>>
                  (S)
                  detach
                endif
              endif
              if (PreferMountedVols set?) then (no) <<#aqua>>
                if (isBusy()) then (yes)
                  if (dev.num_writers + NumReserved() < num_writers) then (yes) <<#aqua>>
                    :set num_writers := dev.numwriters + NumReserved(); <<task>> <<#aqua>>
                    :set low_use_drive := dev; <<task>> <<#aqua>>
                  endif
                  (X)
                  detach
                endif
              else (yes)
                if (IsTape() but no volume) then (yes)
                  (X)
                  detach
                endif
              endif
              if(exact_match set? and have_volume set?) then (yes) <<#aqua>>
                if(VolumeName matches mounted volume) then (no) <<#aqua>>
                  (X)
                  detach
                endif
                if (Can_i_use_volume()) then (no)
                  (X)
                  detach
                endif
              endif
              :line 1080;

              :line 1152;
            endif
            if (autochanger_only) then (yes) <<#aqua>>
              if (IsBusy()) then (no)
                if (volume in drive) then (no)
                  (S)
                  detach
                endif
              endif
            endif
            if (num_writers == 0) then (yes)
              if (NumReserved()) then (yes)
                if (IsPoolOk()) then (yes)
                  (S)
                  detach
                else (no)
                  (X)
                  detach
                endif
              elseif (CanAppend()) then (yes)
                if (IsPoolOk()) then (no)
                  :UnloadAutoChanger(); <<procedure>>
                endif
                (S)
                detach
              endif
            endif
            if (num_writers > 0 || CanAppend()) then (yes)
              if (IsPoolOk()) then (yes)
                (S)
                :return success; <<#tomato>>
              else (no)
                (X)
                detach
              endif
            else (no)
              :cancel job (M_FATAL); <<#tomato>>
              detach
            endif
          else (no)
            (X)
            :return failure; <<#tomato>>
          endif
          |ReserveDeviceForAppend|
          if (success?) then (yes)
            :reserve device;
            :set have_device; <<task>>
          endif
        endif
      endif
      |ReserveDevice|
      if (have_device?) then (yes)
        if (have_volume set?) then (yes) <<#aqua>>
          if (reserve_volume()) then (no)
            (F)
            detach
          endif
        else (no)
          if (DirFindNextAppendableVolume()) then (yes)
            :set have_volume; <<task>> <<#aqua>>
            :set VolumeName; <<task>> <<#aqua>>
          else (no)
            :clear have_volume; <<task>> <<#aqua>>
            :clear VolumeName; <<task>> <<#aqua>>
            if (FoundInUse()) then (yes)
              if(PreferMountedVols set?) then (no) <<#aqua>>
                :set PreferMountedVols; <<task>> <<#aqua>>
                if (dcr has volume?) then (yes)
                  :UnreserveDevice(); <<procedure>>
                endif
                (F)
                detach
              endif
            endif
            if (num_writers != 0) then (yes)
                if (dcr has volume?) then (yes)
                  :UnreserveDevice(); <<procedure>>
                endif
                (F)
                detach
            endif
          endif
        endif
      else (no)
        (F)
        detach
      endif
    endif
if (have_device?) then (yes)
  :OK device message>
else (no)
  (F)
  :clear have_volume; <<task>> <<#aqua>>
  :clear VolumeName; <<task>> <<#aqua>>
endif
  endif
endif

@enduml
