Changeset 516
- Timestamp:
- Apr 26, 2004, 12:19:55 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/doc/pslib/psLibSDRS.tex (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/pslib/psLibSDRS.tex
r411 r516 1 %%% $Id: psLibSDRS.tex,v 1.3 6 2004-04-09 05:16:54price Exp $1 %%% $Id: psLibSDRS.tex,v 1.37 2004-04-26 22:19:55 price Exp $ 2 2 \documentclass[panstarrs]{panstarrs} 3 3 … … 27 27 \RevisionsStart 28 28 % version Date Description 29 DR -1 & 2003 Mar 11 & Draft \\30 \hline31 DR-2 & 2003 Mar 29 & Reorganized, spell-checked \\ 29 DR & 2004 Mar 29 & Draft \\ \hline 30 00 & 2004 Apr 1 & First version, sent to MHPCC \\ \hline 31 01 & 2004 Apr 23 & Added section on error handling \\ \hline 32 32 \RevisionsEnd 33 33 … … 35 35 36 36 \DocumentsInternal 37 PSCD- 430-xxx& PS-1 Design Reference Mission \\ \hline37 PSCD-130-001 & PS-1 Design Reference Mission \\ \hline 38 38 PSCD-430-004 & Pan-STARRS IPP C Code Conventions \\ \hline 39 39 PSCD-430-005 & Pan-STARRS IPP SRS \\ \hline … … 801 801 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 802 802 803 \subsection{Miscellaneous Utilities} 804 805 We require several very low-level functions. Two functions provide 806 conveniences tied to the logging facilities: 807 % 803 \subsection{Error Handling} 804 \hlabel{errorStack} 805 806 \PS{} errors shall be raised using a function, \code{psError}, with 807 the caller supplying a component name and error message. It is 808 desireable to be able to trace an error through the program so that 809 the events that led to the error may be quickly and clearly 810 identified. 811 812 \begin{verbatim} 813 /// Prints an error message and doesn't abort; returns code 814 int psError(const char *name, ///< Category of code that caused the error 815 psErrorCode code, ///< class of error (equivalent to errno) 816 psErrorStatus status, ///< is this a new error? 817 const char *fmt, ///< Format 818 ... ///< Extra arguments to use format 819 ); 820 821 typedef enum { 822 PS_OLD_ERROR = 0, ///< This is an old error, and should append to the error stack 823 PS_NEW_ERROR = 1, ///< This is a new error and should clear the error stack 824 } psErrorStatus; 825 \end{verbatim} 826 827 The \code{name} is of the form \code{aaa.bbb.ccc} and identifies the 828 component raising the error. The \code{psErrorCode} is an enumerated 829 type which lists the possible \textit{classes} of errors 830 (e.g. \code{PS_ERR_IO}) that \PS{} code can generate (see section 831 \ref{psErrorCodes}). \code{status} specifies whether this is a new 832 error, or whether this call to \code{psError} is in response to an 833 error that has already resulted in a call to \code{psError}. The 834 final required argument, \code{fmt}, is a \code{printf}-style format 835 that is passed to \code{psLogMsg} with code \code{PS_LOG_ERROR}. 836 837 The result of a call to \code{psError} shall be to push an error onto 838 a stack; this stack is cleared if \code{psErrorStatus} is true, or by a call 839 to \code{psErrorClear}. The errors are defined as the following: 840 841 \begin{verbatim} 842 typedef struct { 843 char *name; ///< category of code that caused the error 844 psErrorCode code; ///< class of error (equivalent to errno) 845 char *msg; ///< the message associated with the error 846 } psErr; 847 \end{verbatim} 848 849 850 The last error reported is available from \code{psLastError}; if no 851 errors are current, a non-\code{NULL} \code{psErr} shall be returned 852 with code \code{PS_ERR_NONE}. Previous errors on the stack shall be 853 returned by \code{psGetError} (a value of \code{0} passed to 854 \code{psGetError} is equivalent to a call to \code{psLastError}). 855 856 \begin{verbatim} 857 const psErr *psGetError(int which); ///< return specified error (or an "error" with code PS_ERR_NONE) 858 const psErr *psLastError(void); ///< return last error (or an "error" with code PS_ERR_NONE) 859 \end{verbatim} 860 861 The error stack may be completely cleared: 862 863 \begin{verbatim} 864 void psErrorClear(void); ///< Clear the error stack 865 \end{verbatim} 866 867 The entire error stack may be printed to an open file descriptor by 868 calling \code{psErrorStackPrint} (or \code{psVErrorStackPrint}); if 869 and only if there are current errors, the printf-style string 870 \code{fmt} is first printed to the file descriptor \code{fd}. In this 871 printout, error codes shall be replaced by their string equivalents as 872 defined in the next section. Note that these are also available in 873 the \code{psErr} structure. The successive lines of the traceback 874 should be indented by an additional space (see 875 example). \code{psVErrorStackPrint} shall not invoke \code{va_end}. 876 877 \begin{verbatim} 878 void psErrorStackPrint(FILE *fd, const char *fmt, ...); ///< print the errorstack to this file descriptor 879 void psVErrorStackPrint(FILE *fd, const char *fmt, va_list va); ///< print the errorstack to this file 880 ///< descriptor 881 \end{verbatim} 882 883 Any \code{errorCode}s less then or equal to \code{PS_ERR_BASE} (see 884 next section) shall be taken to be valid values of \code{errno}, and 885 \code{psErrorStackPrint} shall print the value returned by 886 \code{strerror} if such error codes are encountered. 887 888 The routine \code{psErrorCodeString} returns the string associated 889 with an error code: 890 891 \begin{verbatim} 892 const char *psErrorCodeString(psErrorCode code); ///< return the string associated with an error code. 893 \end{verbatim} 894 895 896 \subsubsection{Error Codes} 897 \hlabel{psErrorCodes} 898 899 The type \code{psErrorCode} is defined by an auxiliary file, conventionally named 900 \file{psErrorCodes.dat}. This file shall consist of a number of lines, each 901 of the form: 902 \begin{verbatim} 903 NAME [ = value ] , STRING 904 \end{verbatim} 905 where \code{[ = value]} is optional, and no spaces are significant except in the 906 STRING. Comments extend from \code{#} to the end of the line (except that a 907 \code{\#} shall be replaced by \code{#} and not taken to start a comment). For example, 908 \begin{verbatim} 909 # 910 # This file is used to generate psErrorClasses.h 911 # 912 NONE = 0, not an error; must be 0 913 BASE = 256, first value we use; should avoid errno conflicts 914 UNKNOWN, unknown error 915 IO, I/O error 916 BADFREE, bad argument to psFree() 917 MEMORY_CORRUPTION, memory corruption detected 918 \end{verbatim} 919 The values \code{NONE = 0} and {UNKNOWN} must be present. 920 921 The \PS{} Makefiles shall 922 generate two files, \file{psErrorCodes.h} and 923 \file{psErrorCodes.c} from the input file \file{psErrorCodes.dat}. 924 \file{psErrorCodes.h} shall define an enumerated type 925 \code{psErrorCode} with elements \code{PS_ERR_NAME} and values as specified 926 in \file{psErrorCodes.dat}, e.g. 927 \begin{verbatim} 928 #if !defined(PS_ERROR_CODES_H) 929 #define PS_ERROR_CODES_H 930 931 typedef enum { 932 PS_ERR_NONE = 0, 933 PS_ERR_BASE = 256, 934 PS_ERR_UNKNOWN, 935 PS_ERR_IO, 936 PS_ERR_BADFREE, 937 PS_ERR_MEMORY_CORRUPTION, 938 PS_ERR_N_ERR_CLASSES, 939 } psErrorCode; 940 941 #endif 942 \end{verbatim} 943 Any \code{errorCode}s less then or equal to \code{PS_ERR_BASE} shall be taken 944 to be valid values of \code{errno}. 945 946 The implementation may add extra fields (e.g. \code{PS_ERR_N_ERR_CLASSES}). 947 948 The latter shall be of the form 949 \begin{verbatim} 950 static struct { 951 psErrorCode code; 952 char *descrip; 953 } errorStrings[] = { 954 { PS_ERR_NONE, "not an error; must be 0"}, 955 { PS_ERR_BASE, "first value we use; should avoid errno conflicts"}, 956 { PS_ERR_UNKNOWN, "unknown error"}, 957 { PS_ERR_IO, "I/O error"}, 958 { PS_ERR_BADFREE, "bad argument to psFree()"}, 959 { PS_ERR_MEMORY_CORRUPTION, "memory corruption detected"}, 960 { PS_ERR_N_ERR_CLASSES, NULL}, 961 }; 962 \end{verbatim} 963 964 \subsubsection{Example} 965 966 The following example code: 967 968 \begin{verbatim} 969 #include "psLib.h" 970 971 static int primary(int i) 972 { 973 if (i != 0) { // let's pretend it's an I/O error 974 return psError("tst.error.primary", PS_ERR_IO, 1, "Primary error"); 975 } 976 977 return 0; 978 } 979 980 static int middle(void) 981 { 982 if (primary(1) != 0) { 983 return psError("tst.error.middle", PS_ERR_UNKNOWN, 0, "Secondary error"); 984 } 985 986 return 0; 987 } 988 989 static int toplevel(void) 990 { 991 if (middle() != 0) { 992 return psError("tst.error", PS_ERR_UNKNOWN, 0, "Toplevel error"); 993 } 994 995 return 0; 996 } 997 998 int main(void) 999 { 1000 if (toplevel() != 0) { 1001 psErrorStackPrint(stdout, "Traceback:\n"); 1002 1003 if (psLastError()->code == PS_ERR_UNKNOWN) { 1004 fprintf(stderr, "Last error is of unknown type\n"); 1005 } 1006 if (psGetError(2)->code == PS_ERR_IO) { 1007 fprintf(stderr, "Third oldest error is of type IO\n"); 1008 } 1009 } 1010 1011 psErrorClear(); 1012 psErrorStackPrint(stdout, "Traceback:\n"); 1013 1014 if (psLastError()->code == PS_ERR_NONE) { 1015 fprintf(stderr, "No errors. Hurrah\n"); 1016 } 1017 1018 return 0; 1019 } 1020 \end{verbatim} 1021 1022 1023 Produces the following output: 1024 1025 \begin{verbatim} 1026 Traceback: 1027 tst.error.primary I/O error Primary error 1028 tst.error.middle unknown error Secondary error 1029 tst.error unknown error Toplevel error 1030 Last error is of unknown type 1031 Third oldest error is of type IO 1032 No errors. Hurrah 1033 \end{verbatim} 1034 1035 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1036 1037 \subsection{Abort} 1038 1039 \code{psAbort}, shall call \code{psMsgLog} with a 1040 level of \code{PS_LOG_ABORT}, and then call \code{abort}. 1041 808 1042 \begin{verbatim} 809 1043 void psAbort(char *name, char *fmt,...); 810 void psError(char *name, char *fmt,...); 811 \end{verbatim} 812 % 813 The first function, \code{psAbort}, shall call \code{psMsgLog} with a 814 level of \code{PS_LOG_ABORT}, and then call \code{abort}. The second 815 function, \code{psError}, shall call \code{psMsgLog} with a level of 816 \code{PS_LOG_ERROR}, and then return. In cases of doubt, a good 817 choice for \code{name} is \code{__func__}. 818 819 A few useful string functions are also necessary: 820 % 821 \begin{verbatim} 822 PS_STRING(S); 823 char *psStringCopy(char *string); 824 char *psStringNCopy(char *string, int nChar); 825 \end{verbatim} 826 % 827 The first function simply converts the argument to a string 828 \tbd{explanation of usage and rationale?}. The second function, 829 \code{psStringCopy}, shall allocate a sufficient memory block and 830 return a copy of the input string. Similarly, \code{psStringNCopy} 831 shall allocate exactly \code{nChar} bytes and copy as much of the 832 input string as possible into the resulting block without overrunning 833 the available space. The last byte of the output string is required 834 to be \code{NULL}, as well as any additional bytes if \code{string} is 835 not long enough to fill the output string. 1044 \end{verbatim} 836 1045 837 1046 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 2580 2789 second representation employs a hash table which allows fast look-up 2581 2790 given a specific metadata keyword. 2582 2583 When we refer to ``metadata'' (especially in the case of images), we2584 generally mean a \code{psMetadata}:2585 \begin{verbatim}2586 typedef psMetadata psMetadata;2587 \end{verbatim}2588 2791 2589 2792 An example of the usage of the metadata APIs is as follows: … … 2739 2942 and the \tbd{first} item is returned. 2740 2943 2944 Care should be taken not to leak memory when appending an item for 2945 which the key already exists in the metadata (and is not 2946 \code{PS_META_NON_UNIQUE}). 2947 2741 2948 \begin{verbatim} 2742 2949 /// delete entry from the metadata
Note:
See TracChangeset
for help on using the changeset viewer.
