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