NCEPLIBS-bufr  11.5.0
 All Data Structures Files Functions Variables Pages
writsa.f
Go to the documentation of this file.
1 C> @file
2 C> @brief Write a data subset into a BUFR message, and return each
3 C> completed message within a memory array.
4 
5 C> This subroutine is similar to subroutine writsb(), except that in
6 C> addition to writing each completed message to a specified Fortran
7 C> logical unit, it also returns a copy of each completed message to
8 C> the application program within a memory array.
9 C>
10 C> @authors J. Woollen
11 C> @authors J. Ator
12 C> @date 1994-01-06
13 C>
14 C> @param[in] LUNXX - integer: Absolute value is Fortran logical
15 C> unit number for BUFR file
16 C> @param[in] LMSGT - integer: Dimensioned size (in integers) of
17 C> MSGT; used by the subroutine to ensure that
18 C> it doesn't overflow the MSGT array
19 C> @param[out] MSGT - integer(*): BUFR message
20 C> @param[out] MSGL - integer: Size (in integers) of BUFR message
21 C> in MSGT
22 C> - 0 = No BUFR message was returned within
23 C> MSGT
24 C>
25 C> <p>This subroutine looks and behaves a lot like subroutine writsb().
26 C> Specifically, it is called to indicate to the BUFRLIB software that
27 C> all necessary values for a data subset (i.e. report) have been written,
28 C> and thus that the subset is ready to be encoded and packed into the
29 C> current message for the BUFR file associated with logical unit
30 C> ABS(LUNXX). Logical unit ABS(LUNXX) should have already been opened
31 C> for output operations via a previous call to subroutine openbf(),
32 C> and a BUFR message should already be open for output within internal
33 C> arrays via a previous call to one of the BUFRLIB
34 C> [message-writing subroutines](@ref hierarchy).
35 C> Furthermore, all of the values for the data subset should have
36 C> already been written into internal arrays via calls to any of the
37 C> BUFRLIB [values-writing subroutines](@ref hierarchy)
38 C>
39 C> <p>Where this subroutine differs from writsb() is that, in addition
40 C> to doing all of the above, it also returns a copy of each completed
41 C> BUFR message to the application program within a memory array.
42 C> When using this subroutine, it is important to note that the BUFRLIB
43 C> software is designed to pack as many data subsets as possible into
44 C> each message for output, and therefore not every call to this
45 C> subroutine will result in a message being returned in MSGT. In
46 C> such cases, MSGL will contain the value 0, indicating that no
47 C> message was returned.
48 C>
49 C> <p>In other words, only when MSGL contains a value
50 C> greater than 0 is there an actual BUFR message within MSGT; otherwise,
51 C> the message into which the data subset was packed remains internally
52 C> within BUFRLIB so that future data subsets can be packed into it as
53 C> well, and the message will eventually be returned during some other
54 C> future call to this subroutine. For this reason, there is a way to
55 C> force the subroutine to return any message contained within the
56 C> internal BUFRLIB arrays, such as when there are no more data subsets
57 C> to be encoded and we're ready to exit the application program. In
58 C> this case, the application program should make one final call to
59 C> this subroutine, but with LUNXX set to a negative value;
60 C> specifically, to the additive inverse of the Fortran logical unit
61 C> number of the BUFR file. This signals to the subroutine that there
62 C> are no more data subsets to be packed into the current message for
63 C> logical unit ABS(LUNXX), and that the existing message should
64 C> instead be immediately flushed to output and returned in MSGT.
65 C>
66 C> @remarks
67 C> - There is a maximum size for any BUFR message that can be written
68 C> by the BUFRLIB software. This maximum message size is initially set
69 C> to an internal default value within subroutine bfrini(), but it can
70 C> be changed to a different value via a separate prior call to
71 C> subroutine maxout().
72 C> - As is the case for subroutine writsb(), this subroutine will also
73 C> check to ensure that the data subset, when encoded and packed, will
74 C> fit into the current BUFR message that is open within the internal
75 C> arrays associated with logical unit ABS(LUNXX). If adding the data
76 C> subset to the current message would cause the maximum message size
77 C> to be exceeded, then the subroutine will automatically flush the
78 C> current message to logical unit ABS(LUNXX) and to array MSGT, then
79 C> open and initialize a new internal message using the same SUBSET and
80 C> JDATE values that were specified in the most recent call to one of
81 C> the [message-writing subroutines](@ref hierarchy) for ABS(LUNXX),
82 C> then encode and pack the data subset into that new message.
83 C> - If the user would prefer that output messages only be returned
84 C> to the calling program via the MSGT memory array and not also
85 C> written to Fortran logical unit ABS(LUNXX), then this can be
86 C> accomplished by setting IO = 'NUL' when calling subroutine openbf()
87 C> for ABS(LUNXX). In such cases, the logical unit number ABS(LUNXX)
88 C> does not even need to be associated with an actual file on the
89 C> local system.
90 C>
91 C> <b>Program history log:</b>
92 C> - 1994-01-06 J. Woollen -- Original author
93 C> - 1998-07-08 J. Woollen -- Replaced call to Cray library routine
94 C> "ABORT" with call to new internal BUFRLIB
95 C> routine "BORT"; modified to make Y2K
96 C> compliant
97 C> - 2000-09-19 J. Woollen -- Maximum message length increased
98 C> from 10,000 to 20,000 bytes
99 C> - 2003-11-04 S. Bender -- Added remarks and routine interdependencies
100 C> - 2003-11-04 D. Keyser -- Unified/portable for WRF; added history
101 C> documentation; outputs more complete
102 C> diagnostic info when routine terminates
103 C> abnormally
104 C> - 2004-08-18 J. Ator -- Add post msgupd() check for and return of
105 C> message within MSGT in order to prevent
106 C> loss of message in certain situations;
107 C> maximum message length increased from
108 C> 20,000 to 50,000 bytes
109 C> - 2005-03-09 J. Ator -- Added capability for compressed messages
110 C> - 2009-03-23 J. Ator -- Added LMSGT argument and check
111 C> - 2014-12-10 J. Ator -- Use modules instead of COMMON blocks
112 C> - 2019-05-09 J. Ator -- Added dimensions for MSGLEN and MSGTXT
113 C> - 2020-09-22 J. Ator -- Added capability to return two BUFR
114 C> messages within MSGT during the same call
115 C> to this routine, in the rare instances
116 C> where this can occur
117 C>
118  SUBROUTINE writsa(LUNXX,LMSGT,MSGT,MSGL)
119 
120  USE moda_bufrmg
121 
122  COMMON /msgcmp/ ccmf
123 
124  CHARACTER*1 ccmf
125 
126  dimension msgt(*)
127 
128 C----------------------------------------------------------------------
129 C----------------------------------------------------------------------
130 
131  lunit = abs(lunxx)
132 
133 C CHECK THE FILE STATUS
134 C ---------------------
135 
136  CALL status(lunit,lun,il,im)
137  IF(il.EQ.0) goto 900
138  IF(il.LT.0) goto 901
139  IF(im.EQ.0) goto 902
140 
141 C IF LUNXX < 0, FORCE MEMORY MSG TO BE WRITTEN (W/O ANY CURRENT SUBSET)
142 C ---------------------------------------------------------------------
143 
144  IF(lunxx.LT.0) CALL closmg(lunit)
145 
146 C IS THERE A COMPLETED BUFR MESSAGE TO BE RETURNED?
147 C -------------------------------------------------
148 
149  IF(msglen(lun).GT.0) THEN
150  IF(msglen(lun).GT.lmsgt) goto 904
151  msgl = msglen(lun)
152  DO n=1,msgl
153  msgt(n) = msgtxt(n,lun)
154  ENDDO
155  msglen(lun) = 0
156  ELSE
157  msgl = 0
158  ENDIF
159 
160  IF(lunxx.LT.0) goto 100
161 
162 C PACK UP THE SUBSET AND PUT IT INTO THE MESSAGE
163 C ----------------------------------------------
164 
165  CALL wrtree(lun)
166  IF( ccmf.EQ.'Y' ) THEN
167  CALL wrcmps(lunit)
168  ELSE
169  CALL msgupd(lunit,lun)
170  ENDIF
171 
172 C IF THE JUST-COMPLETED CALL TO WRCMPS OR MSGUPD FOR THIS SUBSET CAUSED
173 C A MESSAGE TO BE FLUSHED TO ABS(LUNXX), THEN ATTEMPT TO RETRIEVE AND
174 C RETURN THAT MESSAGE NOW. OTHERWISE, WE RUN THE RISK THAT THE NEXT
175 C CALL TO OPENMB OR OPENMG MIGHT CAUSE ANOTHER MESSAGE TO BE FLUSHED,
176 C AND THUS OVERWRITE THE CURRENT MESSAGE WITHIN ARRAY MSGTXT BEFORE WE
177 C HAD THE CHANCE TO RETRIEVE IT DURING THE NEXT CALL TO WRITSA.
178 
179 C ALSO NOTE THAT, IN RARE INSTANCES (E.G. IF THE BYTE COUNT OF THE MOST
180 C RECENT SUBSET IS > 65530), WE COULD END UP WITH TWO BUFR MESSAGES
181 C AVAILABLE TO BE RETURNED FROM THIS ONE CALL TO WRITSA. IF SUFFICIENT
182 C SPACE IS AVAILABLE IN THE MSGT ARRAY, THEN GO AHEAD AND RETURN BOTH
183 C MESSAGES NOW.
184 
185  IF( (msglen(lun).GT.0) .AND. (msgl+msglen(lun).LE.lmsgt) ) THEN
186  DO n = 1,msglen(lun)
187  msgt(msgl+n) = msgtxt(n,lun)
188  ENDDO
189  msgl = msgl+msglen(lun)
190  msglen(lun) = 0
191  ENDIF
192 
193 C EXITS
194 C -----
195 
196 100 RETURN
197 900 CALL bort('BUFRLIB: WRITSA - OUTPUT BUFR FILE IS CLOSED, IT '//
198  . 'MUST BE OPEN FOR OUTPUT')
199 901 CALL bort('BUFRLIB: WRITSA - OUTPUT BUFR FILE IS OPEN FOR '//
200  . 'INPUT, IT MUST BE OPEN FOR OUTPUT')
201 902 CALL bort('BUFRLIB: WRITSA - A MESSAGE MUST BE OPEN IN OUTPUT '//
202  . 'BUFR FILE, NONE ARE')
203 904 CALL bort('BUFRLIB: WRITSA - OVERFLOW OF OUTPUT BUFR MESSAGE '//
204  . 'ARRAY; TRY A LARGER DIMENSION FOR THIS ARRAY')
205  END
subroutine msgupd(LUNIT, LUN)
THIS SUBROUTINE PACKS UP THE CURRENT SUBSET WITHIN MEMORY (ARRAY IBAY IN MODULE BITBUF) AND THEN TRIE...
Definition: msgupd.f:59
subroutine wrcmps(LUNIX)
THIS SUBROUTINE PACKS UP THE CURRENT SUBSET WITHIN MEMORY (ARRAY IBAY IN MODULE BITBUF), STORING IT FOR COMPRESSION.
Definition: wrcmps.f:79
subroutine status(LUNIT, LUN, IL, IM)
This subroutine checks whether a specified Fortran logical unit number is currently connected to the ...
Definition: status.f:61
subroutine closmg(LUNIN)
This subroutine closes the BUFR message that is currently open for writing within internal arrays ass...
Definition: closmg.f:53
subroutine writsa(LUNXX, LMSGT, MSGT, MSGL)
This subroutine is similar to subroutine writsb(), except that in addition to writing each completed ...
Definition: writsa.f:118
subroutine bort(STR)
This subroutine calls subroutine errwrt() to log an error message, then calls subroutine bort_exit() ...
Definition: bort.f:23
subroutine wrtree(LUN)
THIS SUBROUTINE CONVERTS USER NUMBERS INTO SCALED INTEGERS AND PACKS THE USER ARRAY INTO THE SUBSET B...
Definition: wrtree.f:49