xref: /illumos-gate/usr/src/lib/libnisdb/db_scheme.cc (revision 3d4e20a23e1894c03df6b83e39a88625f74ee0e4)
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 <stdio.h>
30 #include <string.h>
31 #include "db_headers.h"
32 #include "db_scheme.h"
33 
34 #include "nisdb_mt.h"
35 
36 /*
37  *  Constructor:  create new scheme by making copy of 'orig'.
38  * All items within old scheme are also copied (i.e. no shared pointers).
39 */
40 db_scheme::db_scheme(db_scheme* orig)
41 {
42 	int numkeys, i;
43 	keys.keys_len = 0;
44 	keys.keys_val = NULL;
45 
46 	if (orig == NULL) {
47 		WARNING("db_scheme::db_scheme: null original db_scheme");
48 		return;
49 	}
50 
51 	READLOCKV(orig, "r orig db_scheme::db_scheme");
52 
53 	numkeys = this->keys.keys_len = orig->keys.keys_len;
54 	db_key_desc * descols = this->keys.keys_val = new db_key_desc[numkeys];
55 	db_key_desc * srccols = orig->keys.keys_val;
56 
57 	if (descols == NULL) {
58 		clear_columns(0);
59 		READUNLOCKV(orig, "ru orig db_scheme::db_scheme");
60 		FATAL("db_scheme::db_scheme: cannot allocate space for columns",
61 		DB_MEMORY_LIMIT);
62 	}
63 
64 	for (i = 0; i < numkeys; i++) {
65 		if (srccols[i].key_name == NULL) {
66 			clear_columns(i);
67 			WARNING("db_scheme::db_scheme: null column name");
68 			READUNLOCKV(orig, "ru orig db_scheme::db_scheme");
69 			return;
70 		}
71 		descols[i].key_name = new item(srccols[i].key_name);
72 		if (descols[i].key_name == NULL) {
73 			clear_columns(i);
74 			READUNLOCKV(orig, "ru orig db_scheme::db_scheme");
75 			FATAL(
76 		"db_scheme::db_scheme: cannot allocate space for column names",
77 		DB_MEMORY_LIMIT);
78 		}
79 		descols[i].key_flags = srccols[i].key_flags;
80 		descols[i].where = srccols[i].where;
81 		descols[i].store_type = srccols[i].store_type;
82 		descols[i].column_number = srccols[i].column_number;
83 	}
84 	this->max_columns = orig->max_columns;
85 	this->data = orig->data;
86 	READUNLOCKV(orig, "ru orig db_scheme::db_scheme");
87 	INITRW(scheme);
88 }
89 
90 /* Constructor:  create new sheme by using information in 'zdesc'. */
91 db_scheme::db_scheme(table_obj *zdesc)
92 {
93 	keys.keys_len = 0;
94 	keys.keys_val = NULL;
95 
96 	if (zdesc == NULL) {
97 		WARNING("db_scheme::db_scheme: null table obj");
98 		return;
99 	}
100 
101 	max_columns = zdesc->ta_maxcol;
102 
103 	/* find out how many searchable columns */
104 	int total_cols = zdesc->ta_cols.ta_cols_len;
105 	table_col * zcols = zdesc->ta_cols.ta_cols_val;
106 	int count = 0, i;
107 
108 	if (zcols == NULL) {
109 		WARNING("db_scheme::db_scheme: no columns in nis table obj");
110 		return;
111 	}
112 
113 	/* find out number of indices  */
114 	for (i = 0; i < total_cols; i++) {
115 		if (zcols[i].tc_flags&TA_SEARCHABLE)
116 			++count;
117 	}
118 	if (count == 0) {
119 		WARNING(
120 		"db_scheme::db_scheme: no searchable columns in nis table obj");
121 		return;
122 	}
123 
124 	keys.keys_len = count;
125 	db_key_desc * scols = keys.keys_val = new db_key_desc[count];
126 	if (scols == NULL) {
127 		clear_columns(0);
128 		FATAL("db_scheme::db_scheme: cannot allocate space for keys",
129 			DB_MEMORY_LIMIT);
130 	}
131 	int keynum = 0;
132 
133 	for (i = 0; i < total_cols; i++) {
134 		if (zcols[i].tc_flags&TA_SEARCHABLE) {
135 			if (zcols[i].tc_name == NULL) {
136 				clear_columns(keynum);
137 				WARNING(
138 	    "db_scheme::db_scheme: searchable column cannot have null name");
139 				return;
140 			}
141 			scols[keynum].key_name = new item(zcols[i].tc_name,
142 					strlen(zcols[i].tc_name));
143 			if (scols[keynum].key_name == NULL) {
144 				clear_columns(keynum);
145 				FATAL(
146 		    "db_scheme::db_scheme: cannot allocate space for key names",
147 		    DB_MEMORY_LIMIT);
148 			}
149 			scols[keynum].key_flags = zcols[i].tc_flags;
150 			scols[keynum].column_number = i;
151 			scols[keynum].where.max_len = NIS_MAXATTRVAL;
152 			scols[keynum].where.start_column = 0;
153 			/* don't care about position information for now */
154 			++keynum;	/* advance to next key number */
155 		}
156 	}
157 	if (keynum != count) {		/* something is wrong */
158 		clear_columns(keynum);
159 		WARNING(
160 	    "db_scheme::db_scheme: incorrect number of  searchable columns");
161 	}
162 	INITRW(scheme);
163 }
164 
165 void
166 db_scheme::clear_columns(int numkeys)
167 {
168 		int j;
169 
170 		WRITELOCKV(this, "w db_scheme::clear_columns");
171 
172 		db_key_desc * cols = keys.keys_val;
173 
174 		if (cols) {
175 			for (j = 0; j < numkeys; j++) {
176 				if (cols[j].key_name)
177 					delete cols[j].key_name;
178 			}
179 			delete cols;
180 			keys.keys_val = NULL;
181 		}
182 		keys.keys_len = 0;
183 
184 		WRITEUNLOCKV(this, "wu db_scheme::clear_columns");
185 }
186 
187 /* Destructor:  delete all keys associated with scheme and scheme itself. */
188 db_scheme::~db_scheme()
189 {
190 	WRITELOCKV(this, "w db_scheme::~db_scheme");
191 	clear_columns(keys.keys_len);
192 	DESTROYRW(scheme);
193 }
194 
195 /*
196  * Predicate:  return whether given string is one of the index names
197  * this scheme.  If so, return in 'result' the index's number.
198 */
199 bool_t
200 db_scheme::find_index(char *purportedname, int *result)
201 {
202 	if (purportedname) {
203 		int i;
204 		int plen;
205 		plen = strlen(purportedname);
206 
207 		READLOCK(this, FALSE, "r db_scheme::find_index");
208 		for (i = 0; i < keys.keys_len; i++) {
209 			if (keys.keys_val[i].key_name->equal(purportedname,
210 								plen, TRUE)) {
211 				if (result) *result = i;
212 				READUNLOCK(this, TRUE,
213 					"ru db_scheme::find_index");
214 				return (TRUE);
215 			}
216 		}
217 		READUNLOCK(this, FALSE, "ru db_scheme::find_index");
218 	}
219 	return (FALSE);
220 }
221 
222 /* Print out description of table. */
223 void
224 db_scheme::print()
225 {
226 	int i;
227 
228 	READLOCKV(this, "r db_scheme::print");
229 	for (i = 0; i < keys.keys_len; i++) {
230 		keys.keys_val[i].key_name->print();
231 		printf(
232 	"\tcolumn=%d, flags=0x%x, key record position=%d, max length=%d\n",
233 			keys.keys_val[i].column_number,
234 			keys.keys_val[i].key_flags,
235 			keys.keys_val[i].where.start_column,
236 			keys.keys_val[i].where.max_len);
237 		printf("\tdata record position=%d, max length=%d\n",
238 			data.where.start_column, data.where.max_len);
239 	}
240 	printf("\tmaximum number of columns=%d\n", max_columns);
241 	READUNLOCKV(this, "ru db_scheme::print");
242 }
243