Actual source code: view.c
2: #include <petsc/private/viewerimpl.h>
3: #include <petscdraw.h>
5: PetscClassId PETSC_VIEWER_CLASSID;
7: static PetscBool PetscViewerPackageInitialized = PETSC_FALSE;
8: /*@C
9: PetscViewerFinalizePackage - This function destroys any global objects created in PETSc viewers. It is
10: called from `PetscFinalize()`.
12: Level: developer
14: .seealso: [](sec_viewers), `PetscViewer`, `PetscFinalize()`, `PetscViewerInitializePackage()`
15: @*/
16: PetscErrorCode PetscViewerFinalizePackage(void)
17: {
18: PetscFunctionBegin;
19: if (Petsc_Viewer_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_keyval));
20: if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Stdout_keyval));
21: if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Stderr_keyval));
22: if (Petsc_Viewer_Binary_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Binary_keyval));
23: if (Petsc_Viewer_Draw_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Draw_keyval));
24: #if defined(PETSC_HAVE_HDF5)
25: if (Petsc_Viewer_HDF5_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_HDF5_keyval));
26: #endif
27: #if defined(PETSC_USE_SOCKETVIEWER)
28: if (Petsc_Viewer_Socket_keyval != MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_free_keyval(&Petsc_Viewer_Socket_keyval));
29: #endif
30: PetscCall(PetscFunctionListDestroy(&PetscViewerList));
31: PetscViewerPackageInitialized = PETSC_FALSE;
32: PetscViewerRegisterAllCalled = PETSC_FALSE;
33: PetscFunctionReturn(PETSC_SUCCESS);
34: }
36: /*@C
37: PetscViewerInitializePackage - This function initializes everything in the `PetscViewer` package.
39: Level: developer
41: .seealso: [](sec_viewers), `PetscViewer`, `PetscInitialize()`, `PetscViewerFinalizePackage()`
42: @*/
43: PetscErrorCode PetscViewerInitializePackage(void)
44: {
45: char logList[256];
46: PetscBool opt, pkg;
48: PetscFunctionBegin;
49: if (PetscViewerPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
50: PetscViewerPackageInitialized = PETSC_TRUE;
51: /* Register Classes */
52: PetscCall(PetscClassIdRegister("Viewer", &PETSC_VIEWER_CLASSID));
53: /* Register Constructors */
54: PetscCall(PetscViewerRegisterAll());
55: /* Process Info */
56: {
57: PetscClassId classids[1];
59: classids[0] = PETSC_VIEWER_CLASSID;
60: PetscCall(PetscInfoProcessClass("viewer", 1, classids));
61: }
62: /* Process summary exclusions */
63: PetscCall(PetscOptionsGetString(NULL, NULL, "-log_exclude", logList, sizeof(logList), &opt));
64: if (opt) {
65: PetscCall(PetscStrInList("viewer", logList, ',', &pkg));
66: if (pkg) PetscCall(PetscLogEventExcludeClass(PETSC_VIEWER_CLASSID));
67: }
68: #if defined(PETSC_HAVE_MATHEMATICA)
69: PetscCall(PetscViewerMathematicaInitializePackage());
70: #endif
71: /* Register package finalizer */
72: PetscCall(PetscRegisterFinalize(PetscViewerFinalizePackage));
73: PetscFunctionReturn(PETSC_SUCCESS);
74: }
76: /*@
77: PetscViewerDestroy - Destroys a `PetscViewer`.
79: Collective
81: Input Parameter:
82: . viewer - the `PetscViewer` to be destroyed.
84: Level: beginner
86: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerCreate()`, `PetscViewerDrawOpen()`
87: @*/
88: PetscErrorCode PetscViewerDestroy(PetscViewer *viewer)
89: {
90: PetscFunctionBegin;
91: if (!*viewer) PetscFunctionReturn(PETSC_SUCCESS);
94: PetscCall(PetscViewerFlush(*viewer));
95: if (--((PetscObject)(*viewer))->refct > 0) {
96: *viewer = NULL;
97: PetscFunctionReturn(PETSC_SUCCESS);
98: }
100: PetscCall(PetscObjectSAWsViewOff((PetscObject)*viewer));
101: if ((*viewer)->ops->destroy) PetscCall((*(*viewer)->ops->destroy)(*viewer));
102: PetscCall(PetscHeaderDestroy(viewer));
103: PetscFunctionReturn(PETSC_SUCCESS);
104: }
106: /*@C
107: PetscViewerAndFormatCreate - Creates a `PetscViewerAndFormat` struct.
109: Collective
111: Input Parameters:
112: + viewer - the viewer
113: - format - the format
115: Output Parameter:
116: . vf - viewer and format object
118: Level: developer
120: Notes:
121: This increases the reference count of the viewer.
123: Use `PetscViewerAndFormatDestroy()` to free the struct
125: This is used as the context variable for many of the `TS`, `SNES`, and `KSP` monitor functions
127: This construct exists because it allows one to keep track of the use of a `PetscViewerFormat` without requiring the
128: format in the viewer to be permanently changed.
130: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerAndFormat`, `PetscViewerFormat`, `PetscViewerSocketOpen()`, `PetscViewerASCIIOpen()`, `PetscViewerCreate()`,
131: `PetscViewerDrawOpen()`, `PetscViewerAndFormatDestroy()`
132: @*/
133: PetscErrorCode PetscViewerAndFormatCreate(PetscViewer viewer, PetscViewerFormat format, PetscViewerAndFormat **vf)
134: {
135: PetscFunctionBegin;
136: PetscCall(PetscObjectReference((PetscObject)viewer));
137: PetscCall(PetscNew(vf));
138: (*vf)->viewer = viewer;
139: (*vf)->format = format;
140: (*vf)->lg = NULL;
141: (*vf)->data = NULL;
142: PetscFunctionReturn(PETSC_SUCCESS);
143: }
145: /*@C
146: PetscViewerAndFormatDestroy - Destroys a `PetscViewerAndFormat` struct created with `PetscViewerAndFormatCreate()`
148: Collective
150: Input Parameter:
151: . vf - the `PetscViewerAndFormat` to be destroyed.
153: Level: developer
155: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerAndFormat`, `PetscViewerFormat`, `PetscViewerAndFormatCreate()`, `PetscViewerSocketOpen()`,
156: `PetscViewerASCIIOpen()`, `PetscViewerCreate()`, `PetscViewerDrawOpen()`, `PetscViewerAndFormatDestroy()`
157: @*/
158: PetscErrorCode PetscViewerAndFormatDestroy(PetscViewerAndFormat **vf)
159: {
160: PetscFunctionBegin;
161: PetscCall(PetscViewerDestroy(&(*vf)->viewer));
162: PetscCall(PetscDrawLGDestroy(&(*vf)->lg));
163: PetscCall(PetscFree(*vf));
164: PetscFunctionReturn(PETSC_SUCCESS);
165: }
167: /*@C
168: PetscViewerGetType - Returns the type of a `PetscViewer`.
170: Not Collective
172: Input Parameter:
173: . viewer - the `PetscViewer`
175: Output Parameter:
176: . type - `PetscViewerType`
178: Available Types Include:
179: + `PETSCVIEWERSOCKET` - Socket `PetscViewer`
180: . `PETSCVIEWERASCII` - ASCII `PetscViewer`
181: . `PETSCVIEWERBINARY` - binary file `PetscViewer`
182: . `PETSCVIEWERSTRING` - string `PetscViewer`
183: - `PETSCVIEWERDRAW` - drawing `PetscViewer`
185: Level: intermediate
187: Note:
188: `PetscViewerType` is actually a string
190: .seealso: [](sec_viewers), `PetscViewerType`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerType`
191: @*/
192: PetscErrorCode PetscViewerGetType(PetscViewer viewer, PetscViewerType *type)
193: {
194: PetscFunctionBegin;
197: *type = ((PetscObject)viewer)->type_name;
198: PetscFunctionReturn(PETSC_SUCCESS);
199: }
201: /*@C
202: PetscViewerSetOptionsPrefix - Sets the prefix used for searching for
203: `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.
205: Logically Collective
207: Input Parameters:
208: + viewer - the `PetscViewer` context
209: - prefix - the prefix to prepend to all option names
211: Note:
212: A hyphen (-) must NOT be given at the beginning of the prefix name.
213: The first character of all runtime options is AUTOMATICALLY the hyphen.
215: Level: advanced
217: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerSetFromOptions()`, `PetscViewerAppendOptionsPrefix()`
218: @*/
219: PetscErrorCode PetscViewerSetOptionsPrefix(PetscViewer viewer, const char prefix[])
220: {
221: PetscFunctionBegin;
223: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)viewer, prefix));
224: PetscFunctionReturn(PETSC_SUCCESS);
225: }
227: /*@C
228: PetscViewerAppendOptionsPrefix - Appends to the prefix used for searching for
229: `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.
231: Logically Collective
233: Input Parameters:
234: + viewer - the `PetscViewer` context
235: - prefix - the prefix to prepend to all option names
237: Level: advanced
239: Note:
240: A hyphen (-) must NOT be given at the beginning of the prefix name.
241: The first character of all runtime options is AUTOMATICALLY the hyphen.
243: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerGetOptionsPrefix()`, `PetscViewerSetOptionsPrefix()`
244: @*/
245: PetscErrorCode PetscViewerAppendOptionsPrefix(PetscViewer viewer, const char prefix[])
246: {
247: PetscFunctionBegin;
249: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)viewer, prefix));
250: PetscFunctionReturn(PETSC_SUCCESS);
251: }
253: /*@C
254: PetscViewerGetOptionsPrefix - Gets the prefix used for searching for
255: `PetscViewer` options in the database during `PetscViewerSetFromOptions()`.
257: Not Collective
259: Input Parameter:
260: . viewer - the `PetscViewer` context
262: Output Parameter:
263: . prefix - pointer to the prefix string used
265: Level: advanced
267: Fortran Note:
268: The user should pass in a string 'prefix' of sufficient length to hold the prefix.
270: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerAppendOptionsPrefix()`, `PetscViewerSetOptionsPrefix()`
271: @*/
272: PetscErrorCode PetscViewerGetOptionsPrefix(PetscViewer viewer, const char *prefix[])
273: {
274: PetscFunctionBegin;
276: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)viewer, prefix));
277: PetscFunctionReturn(PETSC_SUCCESS);
278: }
280: /*@
281: PetscViewerSetUp - Sets up the internal viewer data structures for the later use.
283: Collective
285: Input Parameter:
286: . viewer - the `PetscViewer` context
288: Level: advanced
290: Note:
291: For basic use of the `PetscViewer` classes the user need not explicitly call
292: `PetscViewerSetUp()`, since these actions will happen automatically.
294: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`
295: @*/
296: PetscErrorCode PetscViewerSetUp(PetscViewer viewer)
297: {
298: PetscFunctionBegin;
300: if (viewer->setupcalled) PetscFunctionReturn(PETSC_SUCCESS);
301: PetscTryTypeMethod(viewer, setup);
302: viewer->setupcalled = PETSC_TRUE;
303: PetscFunctionReturn(PETSC_SUCCESS);
304: }
306: /*@C
307: PetscViewerViewFromOptions - View from the viewer based on options in the options database
309: Collective
311: Input Parameters:
312: + A - the `PetscViewer` context
313: . obj - Optional object that provides the prefix for the option names
314: - name - command line option
316: Level: intermediate
318: Note:
319: See `PetscObjectViewFromOptions()` for details on the viewers and formats support via this interface
321: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerView`, `PetscObjectViewFromOptions()`, `PetscViewerCreate()`
322: @*/
323: PetscErrorCode PetscViewerViewFromOptions(PetscViewer A, PetscObject obj, const char name[])
324: {
325: PetscFunctionBegin;
327: PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
328: PetscFunctionReturn(PETSC_SUCCESS);
329: }
331: /*@C
332: PetscViewerView - Visualizes a viewer object.
334: Collective
336: Input Parameters:
337: + v - the viewer to be viewed
338: - viewer - visualization context
340: Level: beginner
342: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`,
343: `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerLoad()`
344: @*/
345: PetscErrorCode PetscViewerView(PetscViewer v, PetscViewer viewer)
346: {
347: PetscBool iascii;
348: PetscViewerFormat format;
349: #if defined(PETSC_HAVE_SAWS)
350: PetscBool issaws;
351: #endif
353: PetscFunctionBegin;
356: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)v), &viewer));
358: PetscCheckSameComm(v, 1, viewer, 2);
360: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
361: #if defined(PETSC_HAVE_SAWS)
362: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
363: #endif
364: if (iascii) {
365: PetscCall(PetscViewerGetFormat(viewer, &format));
366: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)v, viewer));
367: if (format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
368: if (v->format) PetscCall(PetscViewerASCIIPrintf(viewer, " Viewer format = %s\n", PetscViewerFormats[v->format]));
369: PetscCall(PetscViewerASCIIPushTab(viewer));
370: PetscTryTypeMethod(v, view, viewer);
371: PetscCall(PetscViewerASCIIPopTab(viewer));
372: }
373: #if defined(PETSC_HAVE_SAWS)
374: } else if (issaws) {
375: if (!((PetscObject)v)->amsmem) {
376: PetscCall(PetscObjectViewSAWs((PetscObject)v, viewer));
377: PetscTryTypeMethod(v, view, viewer);
378: }
379: #endif
380: }
381: PetscFunctionReturn(PETSC_SUCCESS);
382: }
384: /*@C
385: PetscViewerRead - Reads data from a `PetscViewer`
387: Collective
389: Input Parameters:
390: + viewer - The viewer
391: . data - Location to write the data, treated as an array of the type defined by `datatype`
392: . num - Number of items of data to read
393: - datatype - Type of data to read
395: Output Parameter:
396: . count - number of items of data actually read, or `NULL`
398: Level: beginner
400: Notes:
401: If datatype is `PETSC_STRING` and `num` is negative, reads until a newline character is found,
402: until a maximum of (-num - 1) chars.
404: Only certain viewers, such as `PETSCVIEWERBINARY` can be read from, see `PetscViewerReadable()`
406: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
407: `PetscViewerReadable()`, `PetscViewerBinaryGetDescriptor()`,
408: `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`
409: @*/
410: PetscErrorCode PetscViewerRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
411: {
412: PetscFunctionBegin;
414: if (dtype == PETSC_STRING) {
415: PetscInt c, i = 0, cnt;
416: char *s = (char *)data;
417: if (num >= 0) {
418: for (c = 0; c < num; c++) {
419: /* Skip leading whitespaces */
420: do {
421: PetscCall((*viewer->ops->read)(viewer, &(s[i]), 1, &cnt, PETSC_CHAR));
422: if (!cnt) break;
423: } while (s[i] == '\n' || s[i] == '\t' || s[i] == ' ' || s[i] == '\0' || s[i] == '\v' || s[i] == '\f' || s[i] == '\r');
424: i++;
425: /* Read strings one char at a time */
426: do {
427: PetscCall((*viewer->ops->read)(viewer, &(s[i++]), 1, &cnt, PETSC_CHAR));
428: if (!cnt) break;
429: } while (s[i - 1] != '\n' && s[i - 1] != '\t' && s[i - 1] != ' ' && s[i - 1] != '\0' && s[i - 1] != '\v' && s[i - 1] != '\f' && s[i - 1] != '\r');
430: /* Terminate final string */
431: if (c == num - 1) s[i - 1] = '\0';
432: }
433: } else {
434: /* Read until a \n is encountered (-num is the max size allowed) */
435: do {
436: PetscCall((*viewer->ops->read)(viewer, &(s[i++]), 1, &cnt, PETSC_CHAR));
437: if (i == -num || !cnt) break;
438: } while (s[i - 1] != '\n');
439: /* Terminate final string */
440: s[i - 1] = '\0';
441: c = i;
442: }
443: if (count) *count = c;
444: else PetscCheck(c >= num, PetscObjectComm((PetscObject)viewer), PETSC_ERR_FILE_READ, "Insufficient data, only read %" PetscInt_FMT " < %" PetscInt_FMT " strings", c, num);
445: } else PetscUseTypeMethod(viewer, read, data, num, count, dtype);
446: PetscFunctionReturn(PETSC_SUCCESS);
447: }
449: /*@
450: PetscViewerReadable - Return a flag whether the viewer can be read from with `PetscViewerRead()`
452: Not Collective
454: Input Parameter:
455: . viewer - the `PetscViewer` context
457: Output Parameter:
458: . flg - `PETSC_TRUE` if the viewer is readable, `PETSC_FALSE` otherwise
460: Level: intermediate
462: Note:
463: `PETSC_TRUE` means that viewer's `PetscViewerType` supports reading, that is `PetscViewerRead()`, (this holds e.g. for `PETSCVIEWERBINARY`)
464: and the viewer is in a mode allowing reading, i.e. `PetscViewerFileGetMode()`
465: returns one of `FILE_MODE_READ`, `FILE_MODE_UPDATE`, `FILE_MODE_APPEND_UPDATE`.
467: .seealso: [](sec_viewers), `PetscViewerRead()`, `PetscViewer`, `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
468: @*/
469: PetscErrorCode PetscViewerReadable(PetscViewer viewer, PetscBool *flg)
470: {
471: PetscFileMode mode;
472: PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL;
474: PetscFunctionBegin;
477: PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f));
478: *flg = PETSC_FALSE;
479: if (!f) PetscFunctionReturn(PETSC_SUCCESS);
480: PetscCall((*f)(viewer, &mode));
481: switch (mode) {
482: case FILE_MODE_READ:
483: case FILE_MODE_UPDATE:
484: case FILE_MODE_APPEND_UPDATE:
485: *flg = PETSC_TRUE;
486: default:
487: break;
488: }
489: PetscFunctionReturn(PETSC_SUCCESS);
490: }
492: /*@
493: PetscViewerWritable - Return a flag whether the viewer can be written to with `PetscViewerWrite()`
495: Not Collective
497: Input Parameter:
498: . viewer - the `PetscViewer` context
500: Output Parameter:
501: . flg - `PETSC_TRUE` if the viewer is writable, `PETSC_FALSE` otherwise
503: Level: intermediate
505: Note:
506: `PETSC_TRUE` means viewer is in a mode allowing writing, i.e. `PetscViewerFileGetMode()`
507: returns one of `FILE_MODE_WRITE`, `FILE_MODE_APPEND`, `FILE_MODE_UPDATE`, `FILE_MODE_APPEND_UPDATE`.
509: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
510: @*/
511: PetscErrorCode PetscViewerWritable(PetscViewer viewer, PetscBool *flg)
512: {
513: PetscFileMode mode;
514: PetscErrorCode (*f)(PetscViewer, PetscFileMode *) = NULL;
516: PetscFunctionBegin;
519: PetscCall(PetscObjectQueryFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", &f));
520: *flg = PETSC_TRUE;
521: if (!f) PetscFunctionReturn(PETSC_SUCCESS);
522: PetscCall((*f)(viewer, &mode));
523: if (mode == FILE_MODE_READ) *flg = PETSC_FALSE;
524: PetscFunctionReturn(PETSC_SUCCESS);
525: }
527: /*@
528: PetscViewerCheckReadable - Check whether the viewer can be read from, generates an error if not
530: Collective
532: Input Parameter:
533: . viewer - the `PetscViewer` context
535: Level: intermediate
537: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerReadable()`, `PetscViewerCheckWritable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
538: @*/
539: PetscErrorCode PetscViewerCheckReadable(PetscViewer viewer)
540: {
541: PetscBool flg;
543: PetscFunctionBegin;
545: PetscCall(PetscViewerReadable(viewer, &flg));
546: PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Viewer doesn't support reading, or is not in reading mode (FILE_MODE_READ, FILE_MODE_UPDATE, FILE_MODE_APPEND_UPDATE)");
547: PetscFunctionReturn(PETSC_SUCCESS);
548: }
550: /*@
551: PetscViewerCheckWritable - Check whether the viewer can be written to, generates an error if not
553: Collective
555: Input Parameter:
556: . viewer - the `PetscViewer` context
558: Level: intermediate
560: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerWritable()`, `PetscViewerCheckReadable()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetType()`
561: @*/
562: PetscErrorCode PetscViewerCheckWritable(PetscViewer viewer)
563: {
564: PetscBool flg;
566: PetscFunctionBegin;
568: PetscCall(PetscViewerWritable(viewer, &flg));
569: PetscCheck(flg, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Viewer doesn't support writing, or is in FILE_MODE_READ mode");
570: PetscFunctionReturn(PETSC_SUCCESS);
571: }