gdncfileopen.f90
Go to the documentation of this file.
1 subroutine gdncfileopen(fileid, filename, writable, overwrite, stat, err)
2  use gtdata_netcdf_file_types, only: gd_nc_file_id_entry
4  use netcdf, only: &
5  & nf90_write, &
6  & nf90_nowrite, &
7  & nf90_noerr, &
8  & nf90_noclobber, &
9  & nf90_clobber, &
10  & nf90_64bit_offset, &
11  & nf90_open, &
12  & nf90_create
13  use dc_message, only: messagenotify
14  use dc_error, only: storeerror
15  use dc_types, only: string
16  use dc_trace, only: beginsub, endsub
17  implicit none
18  integer, intent(out):: fileid
19  character(len = *), intent(in):: filename
20  logical, intent(in), optional:: writable
21  ! .TRUE. は書き込みモード、
22  ! .FALSE. は読込モード。
23  ! 読込モードの際にファイルが
24  ! ファイルが存在しないと
25  ! エラーになる。
26  ! デフォルトは読み込みモード
27  logical, intent(in), optional:: overwrite
28  ! writable が .TRUE. の
29  ! 場合のみ有効。
30  ! .TRUE. ならば上書きモード
31  ! .FALSE. の場合、既存の
32  ! ファイルが存在すると
33  ! エラーになる
34  logical, intent(out), optional:: err
35  integer, intent(out), optional:: stat
36  logical:: writable_required
37  logical:: overwrite_required
38  type(gd_nc_file_id_entry), pointer:: identptr, prev
39  integer:: mystat, mode
40  character(len = 256):: real_filename
41  character(len = STRING):: cause_c
42  character(*), parameter:: subname = "GDNcFileOpen"
43 continue
44  fileid = -1
45  !
46  ! オプションの解釈
47  !
48  writable_required = .false.
49  overwrite_required = .false.
50  if (present(writable)) writable_required = writable
51  if (present(overwrite)) overwrite_required = overwrite
52  call beginsub(subname, 'writable=%y overwrite=%y file=%c', &
53  & l=(/writable_required, overwrite_required/), c1=trim(filename))
54  !
55  ! 同じ名前で書込み可能性も適合していれば nf90_open しないで済ませる
56  !
57  if (id_used) then
58  identptr => id_head
59  nullify(prev)
60  do
61  if ((identptr % filename == filename) &
62  & .and. (identptr % writable .or. .not. writable_required)) then
63  fileid = identptr % id
64  identptr % count = identptr % count + 1
65  if (present(err)) err = .false.
66  if (present(stat)) stat = nf90_noerr
67  mystat = nf90_noerr
68  goto 999
69  endif
70  prev => identptr
71  identptr => identptr % next
72  if (.not. associated(identptr)) exit
73  enddo
74  allocate(identptr)
75  prev%next => identptr
76  else
77  nullify(prev)
78  allocate(id_head)
79  identptr => id_head
80  id_used = .true.
81  endif
82  nullify(identptr % next)
83  identptr % filename = filename
84  identptr % writable = writable_required
85  identptr % count = 1
86  !
87  ! URL の部分的サポート
88  !
89  real_filename = filename
90  if (real_filename(1:8) == 'file:///') then
91  real_filename = real_filename(8: )
92  else if (real_filename(1:5) == 'file:' .AND. real_filename(6:6) /= '/') then
93  real_filename = real_filename(6: )
94  endif
95  !
96  ! いざ nf90_open
97  !
98  mode = nf90_nowrite
99  if (writable_required) mode = ior(mode, nf90_write)
100  ! 既に nc ファイルがあると思って開けてみる
101  mystat = nf90_open(real_filename, mode, identptr % id)
102  !
103  ! ファイルが既に存在する場合
104  !
105  if (mystat == nf90_noerr) then
106  ! 書き込みモードの場合
107  if (writable_required) then
108  if (overwrite_required) then
109  ! 上書きモードの場合
110  mode = nf90_clobber
111  call messagenotify('M', subname, &
112  & '"%c" is overwritten.', c1=trim(filename), rank_mpi = -1)
113  else
114  ! 上書き禁止モードの場合
115  mode = nf90_noclobber
116  call messagenotify('W', subname, &
117  & '"%c" is opened in write-protect mode.', c1=trim(filename), rank_mpi = -1)
118  end if
119  mode = ior(mode,nf90_64bit_offset)
120  mystat = nf90_create(real_filename, mode, identptr % id)
121  if (mystat /= nf90_noerr) then
122  cause_c=filename
123  if (present(stat)) stat = mystat
124  goto 999
125  end if
126  endif
127  ! 読み込みモードの場合は何もしない
128  else
129  !
130  ! ファイルが無かった場合
131  !
132  if (.not. writable_required) then
133  ! 読み込みモードの場合
134  !
135  ! 「無いよ」とエラーを吐いて終了
136  if (mystat /= nf90_noerr) then
137  cause_c=filename
138  if (present(stat)) stat = mystat
139  goto 999
140  end if
141  else
142  ! 書き込みモードの場合
143  mode = nf90_clobber
144  ! ファイルを作成する
145  mode = ior(mode,nf90_64bit_offset)
146  mystat = nf90_create(real_filename, mode, identptr % id)
147  if (mystat /= nf90_noerr) then
148  cause_c=filename
149  if (present(stat)) stat = mystat
150  goto 999
151  end if
152  endif
153  endif
154 
155  fileid = identptr % id
156 
157  ! 失敗したら消しておく
158  if (mystat /= nf90_noerr) then
159  if (associated(prev)) then
160  prev%next => identptr % next
161  else
162  id_head => identptr % next
163  if (.not. associated(id_head)) id_used = .false.
164  endif
165  deallocate(identptr)
166  fileid = -1
167  endif
168 
169  if (present(stat)) then
170  stat = mystat
171  if (present(err)) err = (stat /= nf90_noerr)
172  else
173  cause_c=filename
174  goto 999
175  endif
176 999 continue
177  call storeerror(mystat, subname, err, cause_c)
178  call endsub(subname, 'id=%d stat=%d', i=(/fileid, mystat/))
179 end subroutine gdncfileopen
subroutine, public storeerror(number, where, err, cause_c, cause_i)
Definition: dc_error.f90:830
type(gd_nc_file_id_entry), pointer, save id_head
subroutine gdncfileopen(fileid, filename, writable, overwrite, stat, err)
Definition: gdncfileopen.f90:2
Provides kind type parameter values.
Definition: dc_types.f90:49
integer, parameter, public string
Character length for string.
Definition: dc_types.f90:118