xref: /illumos-gate/usr/src/lib/libnisdb/db_scheme.cc (revision 7a6d80f1660abd4755c68cbd094d4a914681d26e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  *	db_scheme.cc
24  *
25  *	Copyright (c) 1988-2000 Sun Microsystems, Inc.
26  *	All Rights Reserved.
27  */
28 
29 #include <string.h>
30 #include "db_headers.h"
31 #include "db_scheme.h"
32 
33 #include "nisdb_mt.h"
34 
35 /*
36  *  Constructor:  create new scheme by making copy of 'orig'.
37  * All items within old scheme are also copied (i.e. no shared pointers).
38 */
39 db_scheme::db_scheme(db_scheme* orig)
40 {
41 	int numkeys, i;
42 	keys.keys_len = 0;
43 	keys.keys_val = NULL;
44 
45 	if (orig == NULL) {
46 		WARNING("db_scheme::db_scheme: null original db_scheme");
47 		return;
48 	}
49 
50 	READLOCKV(orig, "r orig db_scheme::db_scheme");
51 
52 	numkeys = this->keys.keys_len = orig->keys.keys_len;
53 	db_key_desc * descols = this->keys.keys_val = new db_key_desc[numkeys];
54 	db_key_desc * srccols = orig->keys.keys_val;
55 
56 	if (descols == NULL) {
57 		clear_columns(0);
58 		READUNLOCKV(orig, "ru orig db_scheme::db_scheme");
59 		FATAL("db_scheme::db_scheme: cannot allocate space for columns",
60 		DB_MEMORY_LIMIT);
61 	}
62 
63 	for (i = 0; i < numkeys; i++) {
64 		if (srccols[i].key_name == NULL) {
65 			clear_columns(i);
66 			WARNING("db_scheme::db_scheme: null column name");
67 			READUNLOCKV(orig, "ru orig db_scheme::db_scheme");
68 			return;
69 		}
70 		descols[i].key_name = new item(srccols[i].key_name);
71 		if (descols[i].key_name == NULL) {
72 			clear_columns(i);
73 			READUNLOCKV(orig, "ru orig db_scheme::db_scheme");
74 			FATAL(
75 		"db_scheme::db_scheme: cannot allocate space for column names",
76 		DB_MEMORY_LIMIT);
77 		}
78 		descols[i].key_flags = srccols[i].key_flags;
79 		descols[i].where = srccols[i].where;
80 		descols[i].store_type = srccols[i].store_type;
81 		descols[i].column_number = srccols[i].column_number;
82 	}
83 	this->max_columns = orig->max_columns;
84 	this->data = orig->data;
85 	READUNLOCKV(orig, "ru orig db_scheme::db_scheme");
86 	INITRW(scheme);
87 }
88 
89 /* Constructor:  create new sheme by using information in 'zdesc'. */
90 db_scheme::db_scheme(table_obj *zdesc)
91 {
92 	keys.keys_len = 0;
93 	keys.keys_val = NULL;
94 
95 	if (zdesc == NULL) {
96 		WARNING("db_scheme::db_scheme: null table obj");
97 		return;
98 	}
99 
100 	max_columns = zdesc->ta_maxcol;
101 
102 	/* find out how many searchable columns */
103 	int total_cols = zdesc->ta_cols.ta_cols_len;
104 	table_col * zcols = zdesc->ta_cols.ta_cols_val;
105 	int count = 0, i;
106 
107 	if (zcols == NULL) {
108 		WARNING("db_scheme::db_scheme: no columns in nis table obj");
109 		return;
110 	}
111 
112 	/* find out number of indices  */
113 	for (i = 0; i < total_cols; i++) {
114 		if (zcols[i].tc_flags&TA_SEARCHABLE)
115 			++count;
116 	}
117 	if (count == 0) {
118 		WARNING(
119 		"db_scheme::db_scheme: no searchable columns in nis table obj");
120 		return;
121 	}
122 
123 	keys.keys_len = count;
124 	db_key_desc * scols = keys.keys_val = new db_key_desc[count];
125 	if (scols == NULL) {
126 		clear_columns(0);
127 		FATAL("db_scheme::db_scheme: cannot allocate space for keys",
128 			DB_MEMORY_LIMIT);
129 	}
130 	int keynum = 0;
131 
132 	for (i = 0; i < total_cols; i++) {
133 		if (zcols[i].tc_flags&TA_SEARCHABLE) {
134 			if (zcols[i].tc_name == NULL) {
135 				clear_columns(keynum);
136 				WARNING(
137 	    "db_scheme::db_scheme: searchable column cannot have null name");
138 				return;
139 			}
140 			scols[keynum].key_name = new item(zcols[i].tc_name,
141 					strlen(zcols[i].tc_name));
142 			if (scols[keynum].key_name == NULL) {
143 				clear_columns(keynum);
144 				FATAL(
145 		    "db_scheme::db_scheme: cannot allocate space for key names",
146 		    DB_MEMORY_LIMIT);
147 			}
148 			scols[keynum].key_flags = zcols[i].tc_flags;
149 			scols[keynum].column_number = i;
150 			scols[keynum].where.max_len = NIS_MAXATTRVAL;
151 			scols[keynum].where.start_column = 0;
152 			/* don't care about position information for now */
153 			++keynum;	/* advance to next key number */
154 		}
155 	}
156 	if (keynum != count) {		/* something is wrong */
157 		clear_columns(keynum);
158 		WARNING(
159 	    "db_scheme::db_scheme: incorrect number of  searchable columns");
160 	}
161 	INITRW(scheme);
162 }
163 
164 void
165 db_scheme::clear_columns(int numkeys)
166 {
167 		int j;
168 
169 		WRITELOCKV(this, "w db_scheme::clear_columns");
170 
171 		db_key_desc * cols = keys.keys_val;
172 
173 		if (cols) {
174 			for (j = 0; j < numkeys; j++) {
175 				if (cols[j].key_name)
176 					delete cols[j].key_name;
177 			}
178 			delete cols;
179 			keys.keys_val = NULL;
180 		}
181 		keys.keys_len = 0;
182 
183 		WRITEUNLOCKV(this, "wu db_scheme::clear_columns");
184 }
185 
186 /* Destructor:  delete all keys associated with scheme and scheme itself. */
187 db_scheme::~db_scheme()
188 {
189 	WRITELOCKV(this, "w db_scheme::~db_scheme");
190 	clear_columns(keys.keys_len);
191 	DESTROYRW(scheme);
192 }
193 
194 /*
195  * Predicate:  return whether given string is one of the index names
196  * this scheme.  If so, return in 'result' the index's number.
197 */
198 bool_t
199 db_scheme::find_index(char *purportedname, int *result)
200 {
201 	if (purportedname) {
202 		int i;
203 		int plen;
204 		plen = strlen(purportedname);
205 
206 		READLOCK(this, FALSE, "r db_scheme::find_index");
207 		for (i = 0; i < keys.keys_len; i++) {
208 			if (keys.keys_val[i].key_name->equal(purportedname,
209 								plen, TRUE)) {
210 				if (result) *result = i;
211 				READUNLOCK(this, TRUE,
212 					"ru db_scheme::find_index");
213 				return (TRUE);
214 			}
215 		}
216 		READUNLOCK(this, FALSE, "ru db_scheme::find_index");
217 	}
218 	return (FALSE);
219 }
220 
221 /* Print out description of table. */
222 void
223 db_scheme::print()
224 {
225 	int i;
226 
227 	READLOCKV(this, "r db_scheme::print");
228 	for (i = 0; i < keys.keys_len; i++) {
229 		keys.keys_val[i].key_name->print();
230 		printf(
231 	"\tcolumn=%d, flags=0x%x, key record position=%d, max length=%d\n",
232 			keys.keys_val[i].column_number,
233 			keys.keys_val[i].key_flags,
234 			keys.keys_val[i].where.start_column,
235 			keys.keys_val[i].where.max_len);
236 		printf("\tdata record position=%d, max length=%d\n",
237 			data.where.start_column, data.where.max_len);
238 	}
239 	printf("\tmaximum number of columns=%d\n", max_columns);
240 	READUNLOCKV(this, "ru db_scheme::print");
241 }
242