NCEPLIBS-bufr  11.7.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> | Date | Programmer | Comments |
93 C> | -----|------------|----------|
94 C> | 1994-01-06 | J. Woollen | Original author |
95 C> | 1998-07-08 | J. Woollen | Replaced call to Cray library routine "ABORT" with call to new internal routine bort(); modified to make Y2K compliant |
96 C> | 2000-09-19 | J. Woollen | Maximum message length increased from 10,000 to 20,000 bytes |
97 C> | 2003-11-04 | S. Bender | Added remarks and routine interdependencies |
98 C> | 2003-11-04 | D. Keyser | Unified/portable for WRF; added documentation; outputs more complete diagnostic info when routine terminates abnormally |
99 C> | 2004-08-18 | J. Ator | Add post msgupd() check for and return of message within MSGT in order to prevent loss of message in certain situations; maximum message length increased from 20,000 to 50,000 bytes |
100 C> | 2005-03-09 | J. Ator | Added capability for compressed messages |
101 C> | 2009-03-23 | J. Ator | Added LMSGT argument and check |
102 C> | 2014-12-10 | J. Ator | Use modules instead of COMMON blocks |
103 C> | 2019-05-09 | J. Ator | Added dimensions for MSGLEN and MSGTXT |
104 C> | 2020-09-22 | J. Ator | Added capability to return two BUFR messages within MSGT during the same call to this routine, in the rare instances where this can occur |
105 C>
106  SUBROUTINE writsa(LUNXX,LMSGT,MSGT,MSGL)
107 
108  USE moda_bufrmg
109 
110  COMMON /msgcmp/ ccmf
111 
112  CHARACTER*1 ccmf
113 
114  dimension msgt(*)
115 
116 C----------------------------------------------------------------------
117 C----------------------------------------------------------------------
118 
119  lunit = abs(lunxx)
120 
121 C CHECK THE FILE STATUS
122 C ---------------------
123 
124  CALL status(lunit,lun,il,im)
125  IF(il.EQ.0) goto 900
126  IF(il.LT.0) goto 901
127  IF(im.EQ.0) goto 902
128 
129 C IF LUNXX < 0, FORCE MEMORY MSG TO BE WRITTEN (W/O ANY CURRENT SUBSET)
130 C ---------------------------------------------------------------------
131 
132  IF(lunxx.LT.0) CALL closmg(lunit)
133 
134 C IS THERE A COMPLETED BUFR MESSAGE TO BE RETURNED?
135 C -------------------------------------------------
136 
137  IF(msglen(lun).GT.0) THEN
138  IF(msglen(lun).GT.lmsgt) goto 904
139  msgl = msglen(lun)
140  DO n=1,msgl
141  msgt(n) = msgtxt(n,lun)
142  ENDDO
143  msglen(lun) = 0
144  ELSE
145  msgl = 0
146  ENDIF
147 
148  IF(lunxx.LT.0) goto 100
149 
150 C PACK UP THE SUBSET AND PUT IT INTO THE MESSAGE
151 C ----------------------------------------------
152 
153  CALL wrtree(lun)
154  IF( ccmf.EQ.'Y' ) THEN
155  CALL wrcmps(lunit)
156  ELSE
157  CALL msgupd(lunit,lun)
158  ENDIF
159 
160 C IF THE JUST-COMPLETED CALL TO WRCMPS OR MSGUPD FOR THIS SUBSET CAUSED
161 C A MESSAGE TO BE FLUSHED TO ABS(LUNXX), THEN ATTEMPT TO RETRIEVE AND
162 C RETURN THAT MESSAGE NOW. OTHERWISE, WE RUN THE RISK THAT THE NEXT
163 C CALL TO OPENMB OR OPENMG MIGHT CAUSE ANOTHER MESSAGE TO BE FLUSHED,
164 C AND THUS OVERWRITE THE CURRENT MESSAGE WITHIN ARRAY MSGTXT BEFORE WE
165 C HAD THE CHANCE TO RETRIEVE IT DURING THE NEXT CALL TO WRITSA.
166 
167 C ALSO NOTE THAT, IN RARE INSTANCES (E.G. IF THE BYTE COUNT OF THE MOST
168 C RECENT SUBSET IS > 65530), WE COULD END UP WITH TWO BUFR MESSAGES
169 C AVAILABLE TO BE RETURNED FROM THIS ONE CALL TO WRITSA. IF SUFFICIENT
170 C SPACE IS AVAILABLE IN THE MSGT ARRAY, THEN GO AHEAD AND RETURN BOTH
171 C MESSAGES NOW.
172 
173  IF( (msglen(lun).GT.0) .AND. (msgl+msglen(lun).LE.lmsgt) ) THEN
174  DO n = 1,msglen(lun)
175  msgt(msgl+n) = msgtxt(n,lun)
176  ENDDO
177  msgl = msgl+msglen(lun)
178  msglen(lun) = 0
179  ENDIF
180 
181 C EXITS
182 C -----
183 
184 100 RETURN
185 900 CALL bort('BUFRLIB: WRITSA - OUTPUT BUFR FILE IS CLOSED, IT '//
186  . 'MUST BE OPEN FOR OUTPUT')
187 901 CALL bort('BUFRLIB: WRITSA - OUTPUT BUFR FILE IS OPEN FOR '//
188  . 'INPUT, IT MUST BE OPEN FOR OUTPUT')
189 902 CALL bort('BUFRLIB: WRITSA - A MESSAGE MUST BE OPEN IN OUTPUT '//
190  . 'BUFR FILE, NONE ARE')
191 904 CALL bort('BUFRLIB: WRITSA - OVERFLOW OF OUTPUT BUFR MESSAGE '//
192  . 'ARRAY; TRY A LARGER DIMENSION FOR THIS ARRAY')
193  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:55
subroutine closmg(LUNIN)
This subroutine closes the BUFR message that is currently open for writing within internal arrays ass...
Definition: closmg.f:40
subroutine writsa(LUNXX, LMSGT, MSGT, MSGL)
This subroutine is similar to subroutine writsb(), except that in addition to writing each completed ...
Definition: writsa.f:106
subroutine bort(STR)
This subroutine calls subroutine errwrt() to log an error message, then calls subroutine bort_exit() ...
Definition: bort.f:22
subroutine wrtree(LUN)
THIS SUBROUTINE CONVERTS USER NUMBERS INTO SCALED INTEGERS AND PACKS THE USER ARRAY INTO THE SUBSET B...
Definition: wrtree.f:49