1 /*
2  * ctable.h - include file for ctables
3  *
4  * $Id$
5  *
6  */
7 
8 #ifndef CTABLE_H
9 #define CTABLE_H
10 
11 #include <tcl.h>
12 #include <assert.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 
22 #ifdef HAVE_NET_ETHERNET_H
23 #include <net/ethernet.h>
24 #define HAVE_ETHERS
25 #endif
26 
27 #ifdef HAVE_NETINET_ETHER_H
28 #include <netinet/ether.h>
29 #define HAVE_ETHERS
30 #endif
31 
32 #ifdef HAVE_SYS_LIMITS_H
33 #include <sys/limits.h>
34 #endif
35 
36 #ifdef WITH_PGTCL
37 #include <libpq-fe.h>
38 #endif
39 
40 #ifdef WITH_CASSTCL
41 #include <cassandra.h>
42 #include <casstcl.h>
43 #endif
44 
45 #include "speedtables.h"
46 
47 #ifdef WITH_SHARED_TABLES
48 #include "shared.c"
49 
50 #define DEFAULT_SHARED_SIZE (1024*1024*4)
51 #define MIN_MIN_FREE (1024*128)
52 #define MAX_MIN_FREE (1024*1024*8)
53 
54 // How often do we allow the shared memory search to restart
55 #define MAX_RESTARTS 1000
56 
57 #endif
58 
59 #define TRUE 1
60 #define FALSE 0
61 
62 // types of quoting for tabsep fields
63 #define CTABLE_QUOTE_NONE 0
64 #define CTABLE_QUOTE_URI 1
65 #define CTABLE_QUOTE_STRICT_URI 2
66 #define CTABLE_QUOTE_ESCAPE 3
67 #define CTABLE_QUOTE_STRICT_ESCAPE 4
68 
69 /*-
70  *
71  * CT_LIST_* - link list routines from Berkeley
72  *
73  * Copyright (c) 1991, 1993
74  *      The Regents of the University of California.  All rights reserved.
75  *
76  * Redistribution and use in source and binary forms, with or without
77  * modification, are permitted provided that the following conditions
78  * are met:
79  * 1. Redistributions of source code must retain the above copyright
80  *    notice, this list of conditions and the following disclaimer.
81  * 2. Redistributions in binary form must reproduce the above copyright
82  *    notice, this list of conditions and the following disclaimer in the
83  *    documentation and/or other materials provided with the distribution.
84  * 4. Neither the name of the University nor the names of its contributors
85  *    may be used to endorse or promote products derived from this software
86  *    without specific prior written permission.
87  *
88  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
89  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
90  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
91  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
92  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
93  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
94  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
95  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
96  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
97  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
98  * SUCH DAMAGE.
99  *
100  *      @(#)queue.h     8.5 (Berkeley) 8/20/94
101  * $FreeBSD: src/sys/sys/queue.h,v 1.72.2.3.2.1 2010/12/21 17:09:25 kensmith Exp $
102  */
103 
104 /*
105  * bidirectionally linked list declarations, from BSD
106  */
107 #define	CT_LIST_HEAD(name, type)						\
108 struct name {								\
109 	struct type *lh_first;	/* first element */			\
110 }
111 
112 #define	CT_LIST_HEAD_INITIALIZER(head)					\
113 	{ NULL }
114 
115 #define	CT_LIST_ENTRY(type)						\
116 struct {								\
117 	struct type *le_next;	/* next element */			\
118 	struct type **le_prev;	/* address of previous next element */	\
119 }
120 
121 /*
122  * bidirectionally linked list functions, from BSD
123  */
124 
125 #define	CT_LIST_EMPTY(head)	((head)->lh_first == NULL)
126 
127 #define	CT_LIST_FIRST(head)	((head)->lh_first)
128 
129 #define	CT_LIST_FOREACH(var, head, field)					\
130 	for ((var) = CT_LIST_FIRST((head));				\
131 	    (var);							\
132 	    (var) = CT_LIST_NEXT((var), field))
133 
134 #define	CT_LIST_FOREACH_SAFE(var, head, field, tvar)			\
135 	for ((var) = CT_LIST_FIRST((head));				\
136 	    (var) && ((tvar) = CT_LIST_NEXT((var), field), 1);		\
137 	    (var) = (tvar))
138 
139 #define	CT_LIST_INIT(head) do {						\
140 	CT_LIST_FIRST((head)) = NULL;					\
141 } while (0)
142 
143 #define	CT_LIST_INSERT_HEAD(head, elm, field) do {				\
144 	if ((CT_LIST_NEXT((elm), field) = CT_LIST_FIRST((head))) != NULL)	\
145 		CT_LIST_FIRST((head))->field.le_prev = &CT_LIST_NEXT((elm), field);\
146 	CT_LIST_FIRST((head)) = (elm);					\
147 	(elm)->field.le_prev = &CT_LIST_FIRST((head));			\
148 } while (0)
149 
150 #define	CT_LIST_NEXT(elm, field)	((elm)->field.le_next)
151 
152 #define	CT_LIST_REMOVE(elm, field) do {					\
153 	if (CT_LIST_NEXT((elm), field) != NULL)				\
154 		CT_LIST_NEXT((elm), field)->field.le_prev = 		\
155 		    (elm)->field.le_prev;				\
156 	*(elm)->field.le_prev = CT_LIST_NEXT((elm), field);		\
157 } while (0)
158 
159 
160 
161 // these types must line up with ctableTypes in gentable.tcl
162 enum ctable_types {
163     CTABLE_TYPE_BOOLEAN,
164     CTABLE_TYPE_FIXEDSTRING,
165     CTABLE_TYPE_VARSTRING,
166     CTABLE_TYPE_CHAR,
167     CTABLE_TYPE_MAC,
168     CTABLE_TYPE_SHORT,
169     CTABLE_TYPE_INT,
170     CTABLE_TYPE_LONG,
171     CTABLE_TYPE_WIDE,
172     CTABLE_TYPE_FLOAT,
173     CTABLE_TYPE_DOUBLE,
174     CTABLE_TYPE_INET,
175     CTABLE_TYPE_TCLOBJ,
176     CTABLE_TYPE_KEY
177 };
178 
179 // define ctable linked lists structures et al
180 struct ctable_LinkedListNode {
181     struct ctable_BaseRow *next;
182     struct ctable_BaseRow **prev;
183     struct ctable_BaseRow **head;
184 };
185 
186 // This must start off as a copy of the start of the generated ctable
187 struct ctable_BaseRow {
188     // hashEntry absolutely must be the first thing defined in the base row
189     ctable_HashEntry     hashEntry;
190 #ifdef WITH_SHARED_TABLES
191     cell_t		_row_cycle;
192 #endif
193     // _ll_nodes absolutely must be the last thing defined in the base row
194     ctable_LinkedListNode _ll_nodes[0];
195 };
196 
197 #include "jsw_slib.h"
198 
199 //
200 // macros for traversing ctable lists
201 //
202 // in the safe version you can safely unlink the node you're currently "on"
203 //
204 
205 #define CTABLE_LIST_FOREACH(list, var, i) \
206     for ((var) = list; (var); (var) = (var)->_ll_nodes[i].next)
207 
208 #define CTABLE_LIST_FOREACH_SAFE(list, var, tvar, i) \
209     for ((var) = list; \
210         (var) && ((tvar) = (var)->_ll_nodes[i].next); \
211          var = tvar)
212 
213 // Cursor state values
214 #define CTABLE_CURSOR_NEW       0
215 #define CTABLE_CURSOR_OK        1
216 #define CTABLE_CURSOR_DELETING -1
217 
218 struct cursor {
219     struct cursor   *nextCursor;
220     struct CTable   *ownerTable;
221     char            *cursorName;
222     ctable_BaseRow **tranTable;
223     int              tranIndex;
224     int              offset;
225     int              offsetLimit;
226     int              cursorState;
227     Tcl_Command      commandInfo;
228 #ifdef WITH_SHARED_TABLES
229     int              lockCycle;
230 #endif
231 };
232 
233 // define ctable search comparison types
234 // these terms must line up with the definition of searchTerms
235 //  in function ctable_ParseSearch
236 //  and the skip table in file ctable_search.c
237 //
238 #define CTABLE_COMP_FALSE 0
239 #define CTABLE_COMP_TRUE 1
240 #define CTABLE_COMP_NULL 2
241 #define CTABLE_COMP_NOTNULL 3
242 #define CTABLE_COMP_LT 4
243 #define CTABLE_COMP_LE 5
244 #define CTABLE_COMP_EQ 6
245 #define CTABLE_COMP_NE 7
246 #define CTABLE_COMP_GE 8
247 #define CTABLE_COMP_GT 9
248 #define CTABLE_COMP_MATCH 10
249 #define CTABLE_COMP_NOTMATCH 11
250 #define CTABLE_COMP_MATCH_CASE 12
251 #define CTABLE_COMP_NOTMATCH_CASE 13
252 #define CTABLE_COMP_RANGE 14
253 #define CTABLE_COMP_IN 15
254 
255 // These must line up with the CTABLE_COMP terms above
256 #define CTABLE_SEARCH_TERMS {"false", "true", "null", "notnull", "<", "<=", "=", "!=", ">=", ">", "match", "notmatch", "match_case", "notmatch_case", "range", "in", (char *)NULL}
257 
258 
259 // when setting, incr'ing, read_tabsepping, etc, we can control at the
260 // C level whether we want normal index behavior (if the field is
261 // indexed and it changes, it will be removed from the index under
262 // the old value and inserted under the new.
263 //
264 // if new is set, it will be inserted but not removed, this is used
265 // when creating new entries.
266 //
267 // if private is set, no index changes will be performed.  This is for
268 // setting up structures for comparisons and the like, i.e. stuff that
269 // should not be a row in the ctable.
270 //
271 // CTABLE_INDEX_FASTDELETE is only used by _delete_all_rows and passed to
272 // _delete.  if fastdelete is set, then the keys have been pre-deleted but
273 // otherwise it should be treated as normal
274 //
275 // CTABLE_INDEX_DESTROY_SHARED is only used by _delete_all_rows and passed to
276 // _delete.  if destroy is set, then nothing in shared memory is deleted
277 // because shared memory will be deleted anyway
278 //
279 // do not change, new and normal and 0 and 1 also expected from find_or_create
280 #define CTABLE_INDEX_DESTROY_SHARED -4
281 #define CTABLE_INDEX_FASTDELETE -2
282 #define CTABLE_INDEX_PRIVATE -1
283 #define CTABLE_INDEX_NORMAL 0
284 #define CTABLE_INDEX_NEW 1
285 
286 // Forward reference to avoid a warning
287 struct CTable;
288 typedef int (*filterFunction_t)(Tcl_Interp *interp, struct CTable *ctable, ctable_BaseRow *row, Tcl_Obj *filter, int sequence);
289 typedef int (*fieldCompareFunction_t) (const ctable_BaseRow *row1, const ctable_BaseRow *row2);
290 
291 // ctable sort struct - this controls everything about a sort
292 struct CTableSort {
293     int *fields;
294     int *directions;
295     int nFields;
296 };
297 
298 #define CTABLE_STRING_MATCH_ANCHORED 0
299 #define CTABLE_STRING_MATCH_UNANCHORED 1
300 #define CTABLE_STRING_MATCH_PATTERN 2
301 
302 struct ctableSearchMatchStruct {
303     // boyer-moore stuff
304     int            *skip;
305     unsigned char  *needle;
306     int             occ[UCHAR_MAX+1];
307     int             nlen;
308 
309     // universal stuff
310     int             type;
311     int             nocase;
312 };
313 
314 // ctable search component struct - one for each "-compare" expression in a
315 // ctable search
316 struct CTableSearchComponent {
317     void                    *clientData;
318     ctable_BaseRow          *row1;
319     ctable_BaseRow          *row2;
320     ctable_BaseRow          *row3;
321     fieldCompareFunction_t   compareFunction;
322     Tcl_Obj                **inListObj;
323     ctable_BaseRow	   **inListRows;
324     int                      inCount;
325     int                      fieldID;
326     int                      comparisonType;
327 };
328 
329 // ctable search filter struct - one for each "-filter" expression in a
330 // ctable search
331 struct CTableSearchFilter {
332     filterFunction_t  filterFunction;
333     Tcl_Obj	     *filterObject;
334 };
335 
336 #define CTABLE_SEARCH_ACTION_NONE 0
337 #define CTABLE_SEARCH_ACTION_GET 1
338 #define CTABLE_SEARCH_ACTION_ARRAY_GET 2
339 #define CTABLE_SEARCH_ACTION_ARRAY_GET_WITH_NULLS 3
340 #define CTABLE_SEARCH_ACTION_ARRAY 4
341 #define CTABLE_SEARCH_ACTION_ARRAY_WITH_NULLS 5
342 #define CTABLE_SEARCH_ACTION_WRITE_TABSEP 6
343 #define CTABLE_SEARCH_ACTION_TRANSACTION_ONLY 7
344 #define CTABLE_SEARCH_ACTION_CODE 8
345 #define CTABLE_SEARCH_ACTION_CURSOR 9
346 
347 // transactions are run after the operation is complete, so they don't modify
348 // a field that's being searched on
349 #define CTABLE_SEARCH_TRAN_NONE 0
350 #define CTABLE_SEARCH_TRAN_DELETE 1
351 #define CTABLE_SEARCH_TRAN_UPDATE 2
352 #define CTABLE_SEARCH_TRAN_CURSOR 3
353 
354 // Buffering types
355 #define CTABLE_BUFFER_DEFAULT -1
356 #define CTABLE_BUFFER_PROVISIONAL -2
357 #define CTABLE_BUFFER_NONE 0
358 #define CTABLE_BUFFER_DEFER 1
359 
360 // Special "field" values for Search with skiplists
361 #define CTABLE_SEARCH_INDEX_NONE -1
362 #define CTABLE_SEARCH_INDEX_ANY -2
363 
364 // If poll code is provided, the poll code will be run after this many rows
365 #define CTABLE_DEFAULT_POLL_INTERVAL 1024
366 
367 // ctable search struct - this controls everything about a search
368 struct CTableSearch {
369     struct CTable                       *ctable;
370     struct CTableSearch                 *previousSearch;
371     CTableSearchComponent               *components;
372     CTableSearchFilter			*filters;
373     char                                *pattern;
374     int                                 *retrieveFields;
375 
376     Tcl_Obj                             *codeBody;
377     Tcl_Obj                             *rowVarNameObj;
378     Tcl_Obj                             *keyVarNameObj;
379 
380     int					 tranType;
381     Tcl_Obj				*tranData;
382 
383     int                                  action;
384 
385     int					 bufferResults;
386 
387     int                                  nComponents;
388     int					 nFilters;
389     int                                  countMax;
390     int                                  offset;
391     int                                  limit;
392 
393     CTableSort                           sortControl;
394 
395     int                                  nRetrieveFields;
396 
397     int                                  noKeys;
398 
399     int					 pollInterval;
400     Tcl_Obj				*pollCodeBody;
401     int					 nextPoll;
402 
403     Tcl_Channel                          tabsepChannel;
404     int                                  writingTabsepIncludeFieldNames;
405     CONST char				*sepstr;
406 
407     // count of matches during a search
408     int                                  matchCount;
409 
410     // field that the search was requested to be indexed on.
411     int					 reqIndexField;
412 
413     // -1 if brute force search, otherwise the component index that has
414     // already been taken care of
415     int                                  alreadySearched;
416 
417     // offsetLimit is calculated from offset and limit
418     int                                  offsetLimit;
419 
420     // we use tran table to accumulate matching rows for sorting when
421     // searching with sorting, and for completing a transaction after searching
422     ctable_BaseRow                     **tranTable;
423 
424     // how to quote quotable strings and reptresent nulls in write_tabsep
425     int					 quoteType;
426     char				*nullString;
427 
428     // Unique search ID for memoization
429     int					 sequence;
430 
431     // cursor ID and structure
432     char                                *cursorName;
433     struct cursor                       *cursor;
434 
435     // what index is this searching?
436     int                                  searchField;
437 };
438 
439 struct ctable_FieldInfo {
440     CONST char              *name;
441     Tcl_Obj                 *nameObj;
442     CONST char             **propKeys;
443     char                   **propValues;
444     fieldCompareFunction_t   compareFunction;
445     int                      number;
446     int                      needsQuoting;
447     int                      indexNumber;
448     int                      unique;
449     int			     canBeNull;
450     enum ctable_types        type;
451 };
452 
453 struct ctable_CreatorTable {
454     Tcl_HashTable     *registeredProcTablePtr;
455     long unsigned int     nextAutoCounter;
456 
457     CONST char          **fieldNames;
458     Tcl_Obj             **nameObjList;
459     Tcl_Obj		**keyObjList;
460     int                  *fieldList;
461     int			 *publicFieldList;
462     enum ctable_types    *fieldTypes;
463     int                  *fieldsThatNeedQuoting;
464     int			  keyField;
465 
466     ctable_FieldInfo    **fields;
467 
468     int                nFields;
469     int		       nPublicFields;
470     int                nLinkedLists;
471 
472     CONST char		   **filterNames;
473     CONST filterFunction_t  *filterFunctions;
474     int			     nFilters;
475 
476     ctable_BaseRow *(*make_empty_row) (struct CTable *ctable);
477     ctable_BaseRow *(*find_row) (struct CTable *ctable, CONST char *key);
478 
479     int (*set) (Tcl_Interp *interp, struct CTable *ctable, Tcl_Obj *dataObj, ctable_BaseRow *row, int field, int indexCtl);
480     int (*set_null) (Tcl_Interp *interp, struct CTable *ctable, ctable_BaseRow *row, int field, int indexCtl);
481 
482     Tcl_Obj *(*get) (Tcl_Interp *interp, ctable_BaseRow *row, int field);
483     CONST char *(*get_string) (const ctable_BaseRow *pointer, int field, int *lengthPtr, Tcl_Obj *utilityObj);
484 
485     Tcl_Obj *(*gen_list) (Tcl_Interp *interp, ctable_BaseRow *pointer);
486     Tcl_Obj *(*gen_keyvalue_list) (Tcl_Interp *interp, ctable_BaseRow *pointer);
487     Tcl_Obj *(*gen_nonnull_keyvalue_list) (Tcl_Interp *interp, ctable_BaseRow *pointer);
488     int (*lappend_field) (Tcl_Interp *interp, Tcl_Obj *destListObj, ctable_BaseRow *p, int field);
489     int (*lappend_field_and_name) (Tcl_Interp *interp, Tcl_Obj *destListObj, ctable_BaseRow *p, int field);
490     int (*lappend_nonnull_field_and_name) (Tcl_Interp *interp, Tcl_Obj *destListObj, ctable_BaseRow *p, int field);
491     void (*dstring_append_get_tabsep) (CONST char *key, ctable_BaseRow *pointer, int *fieldNums, int nFields, Tcl_DString *dsPtr, int noKey, CONST char *sepstr, int quoteType, CONST char *nullString);
492 
493     int (*array_set) (Tcl_Interp *interp, Tcl_Obj *arrayNameObj, ctable_BaseRow *row, int field);
494     int (*array_set_with_nulls) (Tcl_Interp *interp, Tcl_Obj *arrayNameObj, ctable_BaseRow *row, int field);
495 
496     int (*search_compare) (Tcl_Interp *interp, CTableSearch *searchControl, ctable_BaseRow *pointer);
497     int (*sort_compare) (void *clientData, const ctable_BaseRow *pointer1, const ctable_BaseRow *pointer2);
498 
499     void (*delete_row) (struct CTable *ctable, ctable_BaseRow *row, int indexCtl);
500 
501     int (*command) (ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
502     int (*cursor_command) (ClientData cData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]);
503 
504 #ifdef SANITY_CHECKS
505     void (*sanity_check_pointer)(struct CTable *ctable, void *ptr, int indexCtl, CONST char *where);
506 #endif
507     CT_LIST_HEAD(instances, CTable) instances;
508 };
509 
510 struct CTable {
511     ctable_CreatorTable                 *creator;
512     ctable_HashTable                    *keyTablePtr;
513 
514     jsw_skip_t                         **skipLists;
515     ctable_BaseRow                      *ll_head;
516 
517     int                                  autoRowNumber;
518     int                                  destroying;
519     CTableSearch			*searches;
520     char				*nullKeyValue;
521 #ifdef WITH_SHARED_TABLES
522     int					 was_locked;
523     const char				*emptyString;
524     const char			       **defaultStrings;
525 
526     int					 share_type;
527     int					 share_panic;
528     char				*share_name;
529     char				*share_file;
530     shm_t                               *share;
531     size_t				 share_min_free;
532 // reader-only
533     volatile struct CTable		*share_ctable;
534     volatile reader_t			*my_reader;
535 #endif
536     int					 performanceCallbackEnable:1;
537     char				*performanceCallback;
538     double				 performanceCallbackThreshold;
539 
540     Tcl_Command                          commandInfo;
541     long                                 count;
542 
543     struct cursor			*cursors;
544 #ifdef WITH_SHARED_TABLES
545 // reader only
546     int					 cursorLock;
547 #endif
548 
549     CT_LIST_ENTRY(CTable)                   instance;
550 };
551 
552 CTABLE_INTERNAL int ctable_CreateIndex (Tcl_Interp *interp, CTable *ctable, int fieldNum, int depth);
553 
554 // Helpers
555 #define is_hidden_obj(obj) (Tcl_GetString(obj)[0] == '_')
556 #define is_hidden_name(fieldNames,field) ((fieldNames)[field][0] == '_')
557 #define is_hidden_field(table,field) is_hidden_name((table)->fieldNames,field)
558 #define is_key_field(table,field,noKeys) ((noKeys) == 0 && strcmp("_key",(table)->fieldNames[field]) == 0)
559 
560 // Values for share_type
561 #ifdef WITH_SHARED_TABLES
562 # define CTABLE_SHARED_NONE 0
563 # define CTABLE_SHARED_MASTER 1
564 # define CTABLE_SHARED_READER 2
565 #endif
566 
567 #endif
568 
569 // vim: set ts=8 sw=4 sts=4 noet :
570