cmd/xfsprogs/libdm/dmapi_tests/README 1.1 Renamed to cmd/xfstests/dmapi/README
[xfstests-dev.git] / dmapi / src / common / lib / find_session.c
1 /*
2  * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
3  * 
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  * 
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * 
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  * 
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  * 
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  * 
26  * http://www.sgi.com 
27  * 
28  * For further information regarding this notice, see: 
29  * 
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32
33 #include <lib/hsm.h>
34
35
36 /*******************************************************************************
37 *
38 * NAME
39 *       find_test_session - find or create a test DMAPI session.
40 *
41 * DESCRIPTION
42 *       find_test_session() is used to find a test DMAPI session to
43 *       use.  There is only one test session per host; all test processes
44 *       share the same session.  If the session does not already exist,
45 *       then the first process to call find_test_session() causes
46 *       the session to be created.
47 *
48 *       Note: It is possible for N different programs to call this routine
49 *       at the same time.  Each would find that a test session does not
50 *       exist, and each one would then create a new test session.  Since
51 *       excess test sessions are not automatically released on death of
52 *       process, we need to make sure that we don't leave such excess
53 *       sessions around.  So, after creating a session we go back and find
54 *       the test session with the lowest session number.  If it is ours,
55 *       great; we are done.  If not, then we must destroy our session
56 *       and use the one with the lower session ID.  There is still a risk
57 *       here of creating a session and crashing before it can be removed
58 *       again.  To deal with this, the daemon will periodically remove all
59 *       test sessions except for the one with the lowest ID value.
60 *
61 * RETURN VALUE
62 *       None.
63 *
64 *******************************************************************************/
65
66 #define TEST_MSG        "DMAPI test session"
67
68 static int
69 session_compare(
70 const   void    *a,
71 const   void    *b)
72 {
73         return(*((dm_sessid_t *)a) - *((dm_sessid_t *)b));
74 }
75
76 extern void
77 find_test_session(
78         dm_sessid_t     *session)
79 {
80         char            buffer[DM_SESSION_INFO_LEN];
81         dm_sessid_t     *sidbuf = NULL;
82         dm_sessid_t     new_session;
83         u_int           allocelem = 0;
84         u_int           nelem;
85         size_t          rlen;
86         int             error;
87         int             rc;
88         u_int           i;
89
90         /* Retrieve the list of all active sessions on the host. */
91
92         nelem = 100;            /* a reasonable first guess */
93         do {
94                 if (allocelem < nelem) {
95                         allocelem = nelem;
96                         sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
97                         if (sidbuf == NULL) {
98                                 fprintf(stderr, "realloc of %d bytes failed\n",
99                                         nelem * sizeof(*sidbuf));
100                                 exit(1);
101                         }
102                 }
103                 error = dm_getall_sessions(allocelem, sidbuf, &nelem);
104         } while (error < 0 && errno == E2BIG);
105
106         /* If an error occurred, translate it into something meaningful. */
107
108         if (error < 0) {
109                 fprintf(stderr, "unexpected dm_getall_sessions failure, %s\n",
110                         strerror(errno));
111                 free(sidbuf);
112                 exit(1);
113         }
114
115         /* We have the list of all active sessions.  Scan the list looking
116            for an existing "test" session that we can use.  The list must
117            first be sorted in case other processes happen to be creating test
118            sessions at the same time; we need to make sure that we pick the one
119            with the lowest session ID.
120         */
121
122         qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);
123
124         for (i = 0; i < nelem; i++) {
125                 error = dm_query_session(sidbuf[i], sizeof(buffer),
126                                 buffer, &rlen);
127                 if (error < 0) {
128                         fprintf(stderr, "unexpected dm_query_session "
129                                 "failure, %s\n", strerror(errno));
130                         free(sidbuf);
131                         exit(1);
132                 }
133
134                 if (!strncmp(buffer, TEST_MSG, strlen(TEST_MSG)))
135                         break;
136         }
137         if (i < nelem) {
138                 *session = (dm_sessid_t)sidbuf[i];
139                 free(sidbuf);
140                 return;
141         }
142
143         /* No test session exists, so we have to create one ourselves. */
144
145         if (dm_create_session(DM_NO_SESSION, TEST_MSG, &new_session) != 0) {
146                 fprintf(stderr, "dm_create_session failed, %s\n",
147                         strerror(errno));
148                 free(sidbuf);
149                 exit(1);
150         }
151
152         /* Now re-retrieve the list of active sessions. */
153
154         do {
155                 if (allocelem < nelem) {
156                         allocelem = nelem;
157                         sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
158                         if (sidbuf == NULL) {
159                                 fprintf(stderr, "realloc of %d bytes failed\n",
160                                         nelem * sizeof(*sidbuf));
161                                 exit(1);
162                         }
163                 }
164                 error = dm_getall_sessions(allocelem, sidbuf, &nelem);
165         } while (error < 0 && errno == E2BIG);
166
167         if (error < 0) {
168                 fprintf(stderr, "dm_getall_sessions failed, %s\n",
169                         strerror(errno));
170                 free(sidbuf);
171                 exit(1);
172         }
173
174         /* Sort the session ID list into ascending ID order, then find the
175            test session with the lowest session ID.  We better find at
176            least one since we created one!
177         */
178
179         qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);
180
181         for (i = 0; i < nelem; i++) {
182                 error = dm_query_session(sidbuf[i], sizeof(buffer),
183                                 buffer, &rlen);
184                 if (error < 0) {
185                         fprintf(stderr, "dm_query_session failed, %s\n",
186                                 strerror(errno));
187                         free(sidbuf);
188                         exit(1);
189                 }
190                 if (!strncmp(buffer, TEST_MSG, strlen(TEST_MSG)))
191                         break;
192         }
193         if (i == nelem) {
194                 fprintf(stderr, "can't find the session we created\n");
195                 free(sidbuf);
196                 exit(1);
197         }
198         *session = (dm_sessid_t)sidbuf[i];
199         free(sidbuf);
200
201         /* If the session we are going to use is not the one we created,
202            then we need to get rid of the created one.
203         */
204
205         if (*session != new_session) {
206                 if ((new_session) != 0) {
207                         fprintf(stderr, "dm_destroy_session failed, %s\n",
208                                 strerror(errno));
209                         exit(1);
210                 }
211         }
212 }