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