📄 table.c
字号:
/*** Copyright (c) 1995-2001 Hughes Technologies Pty Ltd. All rights** reserved. **** Terms under which this software may be used or copied are** provided in the specific license associated with this product.**** Hughes Technologies disclaims all warranties with regard to this ** software, including all implied warranties of merchantability and ** fitness, in no event shall Hughes Technologies be liable for any ** special, indirect or consequential damages or any damages whatsoever ** resulting from loss of use, data or profits, whether in an action of ** contract, negligence or other tortious action, arising out of or in ** connection with the use or performance of this software.****** $Id: table.c,v 1.28 2003/08/11 05:27:31 bambi Exp $***//*** Module : main : table** Purpose : ** Exports : ** Depends Upon : *//**************************************************************************** STANDARD INCLUDES**************************************************************************/#include <common/config.h>#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <common/config_extras.h>#include <common/config/config.h>#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_STRING_H# include <string.h>#endif#ifdef HAVE_STRINGS_H# include <strings.h>#endif/**************************************************************************** MODULE SPECIFIC INCLUDES**************************************************************************/#ifdef HAVE_DIRENT_H# include <dirent.h>#endif#ifdef HAVE_SYS_DIR_H# include <sys/dir.h>#endif#if HAVE_SYS_MMAN_H# include <sys/mman.h>#endif#include <fcntl.h>#include <errno.h>#include <sys/stat.h>#include <common/msql_defs.h>#include <common/debug/debug.h>#include <common/portability.h>#include <msqld/index/index.h>#include <msqld/includes/errmsg.h>#include <msqld/includes/msqld.h>#include <msqld/main/main.h>#include <msqld/main/yaccer.h>#include <msqld/main/version.h>#include <msqld/main/table.h>#include <msqld/main/sysvar.h>#include <msqld/main/varchar.h>#include <msqld/main/index.h>#include <msqld/main/parse.h>#include <msqld/main/memory.h>#include <common/types/types.h>#include <libmsql/msql.h>/**************************************************************************** GLOBAL VARIABLES**************************************************************************/extern char errMsg[];extern cache_t *tableCache;char *msql_tmpnam();/**************************************************************************** PRIVATE ROUTINES**************************************************************************/static mField_t *_readTableDef(server, table, alias, db) msqld *server; char *table, *alias, *db;{ mField_t *headField=NULL, *tmpField=NULL, *prevField=NULL, *curField=NULL; char path[MSQL_PATH_LEN]; int numFields, numBytes, fieldCount, fd, version; static char buf[MAX_FIELDS * sizeof(mField_t) + sizeof(int)]; debugTrace(TRACE_IN,"readTableDef()"); (void)snprintf(path, MSQL_PATH_LEN, "%s/%s/%s.def", server->config.dbDir, db,table); fd = open(path,O_RDONLY,0); if (fd < 0) { snprintf(errMsg, MAX_ERR_MSG, BAD_TABLE_ERROR,table); msqlDebug1(MOD_ERR,"Unknown table \"%s\"\n",table); debugTrace(TRACE_OUT,"readTableDef()"); return(NULL); } numBytes = read(fd,buf,sizeof(buf)); if (numBytes < 1) { snprintf(errMsg, MAX_ERR_MSG, TABLE_READ_ERROR,table, (char*)strerror(errno)); msqlDebug1(MOD_ERR, "Error reading table \"%s\" definition\n", table); close(fd); debugTrace(TRACE_OUT,"readTableDef()"); return(NULL); } bcopy(buf,&version,sizeof(int)); if (version != DB_VERSION) { snprintf(errMsg, MAX_ERR_MSG, "Table \"%s\" wrong database format\n", table); msqlDebug1(MOD_ERR, "Table \"%s\" wrong database format\n", table); close(fd); debugTrace(TRACE_OUT,"readTableDef()"); return(NULL); } numFields = (numBytes - sizeof(int)) / sizeof(mField_t); fieldCount = 0; headField = NULL; while(fieldCount < numFields) { tmpField = (mField_t *)(buf + sizeof(int) + (fieldCount * sizeof(mField_t))); curField = memMallocField(); if (!headField) { headField = prevField = curField; } else { prevField->next = curField; prevField = curField; } /*bcopy(tmpField, curField, sizeof(mField_t));*/ memCopyField(tmpField, curField); if (alias) { strcpy(curField->table,alias); } curField->value = NULL; fieldCount++; } close(fd); debugTrace(TRACE_OUT,"readTableDef()"); return(headField);}static int findRowLen(cacheEntry) cache_t *cacheEntry;{ int rowLen; mField_t *fieldDef; rowLen = 0; fieldDef = cacheEntry->def; while(fieldDef) { rowLen += fieldDef->dataLength +1; /* +1 for NULL indicator */ fieldDef = fieldDef->next; } return(rowLen);}static cache_t *_createTargetTable(path,name,table1,table2,fields, flag) char *path, *name; cache_t *table1, *table2; mField_t *fields; int flag;{ cache_t *new; mField_t *curField, *newField, *tmpField; int fd, foundField, foundTable, curOffset = 0; sblk_t sblk; /* ** start building the table cache entry */ debugTrace(TRACE_IN,"createTargetTable()"); new = (cache_t *)malloc(sizeof(cache_t)); if (!new) { snprintf(errMsg,MAX_ERR_MSG,TMP_MEM_ERROR); msqlDebug1(MOD_ERR,"Out of memory for temporary table (%s)\n" ,path); debugTrace(TRACE_OUT,"createTargetTable()"); return(NULL); } bzero(new, sizeof(cache_t)); (void)strcpy(new->table,name); fd = open(path,O_RDWR|O_CREAT|O_TRUNC, 0700); if (fd < 0) { snprintf(errMsg,MAX_ERR_MSG,TMP_CREATE_ERROR, (char*)strerror(errno)); msqlDebug1(MOD_ERR,"Couldn't create temporary table (%s)\n", path); (void)free(new); debugTrace(TRACE_OUT,"createTargetTable()"); return(NULL); } sblk.version = DB_VERSION; sblk.activeRows = sblk.numRows = 0; sblk.sequence.step = sblk.sequence.value = 0; sblk.freeList = NO_POS; if (write(fd, &sblk, SBLK_SIZE) < SBLK_SIZE) { snprintf(errMsg,MAX_ERR_MSG, TMP_CREATE_ERROR, (char*)strerror(errno)); msqlDebug1(MOD_ERR,"Couldn't create temporary table (%s)\n", path); (void)free(new); debugTrace(TRACE_OUT,"createTargetTable()"); return(NULL); } new->dataFD = fd; new->result = 1; new->size = SBLK_SIZE; new->dirty = 0; /* ** Map the tmp table and setup the superblock */ new->dataMap = (caddr_t)mmap(NULL, (size_t)new->size, (PROT_READ|PROT_WRITE), MAP_SHARED, new->dataFD, (off_t)0);#ifdef HAVE_MADVISE madvise(new->dataMap, new->size, MADV_SEQUENTIAL);#endif if (new->dataMap == (caddr_t)-1) { free(new); return(NULL); } new->sblk=(sblk_t*)new->dataMap; /* ** Add the field definitions. Ensure that any key fields are ** not flagged as such as we can't access the key data of the ** original table when accessing this. */ curField = table1->def; newField = NULL; while(curField) { /* ** If we've been given a list of fields, only add this ** field to the tmp table if it's in the list. */ if (fields && flag == QUERY_FIELDS_ONLY) { foundField = 0; tmpField = fields; while(tmpField) { if(strcmp(tmpField->name,curField->name)==0 && strcmp(tmpField->table,curField->table)==0) { foundField = 1; break; } tmpField = tmpField->next; } if (!foundField) { curField = curField->next; continue; } } /* ** O.k. Add this field */ if (newField) { newField->next = memMallocField(); newField = newField->next; } else { new->def = memMallocField(); newField = new->def; } memCopyField(curField,newField); if (newField->function) newField->function = NULL; if( *(newField->table) == 0) { (void)strcpy(newField->table,table1->table); } new->rowLen += curField->dataLength + 1; newField->offset = curOffset; curOffset += curField->dataLength + 1; newField->value = NULL; newField->entry = curField->entry; if (newField->entry == NULL) newField->entry = table1; curField = curField->next; } if (table2) { curField = table2->def; while(curField) { /* ** If we've been given a list of fields, only add this ** field to the tmp table if it's in the list. */ if (fields && flag == QUERY_FIELDS_ONLY) { foundField = 0; tmpField = fields; while(tmpField) { if(strcmp(tmpField->name, curField->name)==0 && strcmp(tmpField->table, curField->table)==0) { foundField = 1; break; } tmpField = tmpField->next; } if (!foundField) { curField = curField->next; continue; } } /* ** Add it. */ if (newField) { newField->next = memMallocField(); newField = newField->next; } else { new->def = newField = memMallocField(); } /*bcopy(curField,newField,sizeof(mField_t));*/ memCopyField(curField,newField); if( *(newField->table) == 0) { (void)strcpy(newField->table,table2->table); } new->rowLen += curField->dataLength + 1; newField->offset = curOffset; newField->value = NULL; newField->entry = curField->entry; if (newField->entry == NULL) newField->entry = table2; curOffset += curField->dataLength + 1; curField = curField->next; } } /* ** Create real fields for any function return values */ curField = fields; while(curField) { if (curField->function == NULL) { curField = curField->next; continue; } if (newField) { newField->next = memMallocField(); newField = newField->next; } else { new->def = memMallocField(); newField = new->def; } /*bcopy(curField,newField,sizeof(mField_t));*/ memCopyField(curField,newField); if (newField->function) newField->function = NULL; if( *(newField->table) == 0) { (void)strcpy(newField->table,table1->table); } new->rowLen += curField->dataLength + 1; newField->offset = curOffset; curOffset += curField->dataLength + 1; newField->value = NULL; newField->entry = curField->entry; if (newField->entry == NULL) newField->entry = table1; curField = curField->next; } /* ** Now the ugly bit. We have to create "real" fields for any ** system variables the we want selected. This is so that we ** get the actual sysvar from the original table (such as _rowid) ** rather than getting it generated on the fly from the result ** table. */ curField = fields; while(curField) { if (*(curField->name) == '_') { foundTable = 0; if (strcmp(curField->table, table1->table) == 0) { foundTable = 1; } else if (table2) { if(strcmp(curField->table,table2->table) == 0) { foundTable = 1; } } if ( !foundTable) { curField = curField->next; continue; } /* ** Add the field definition */ if (newField) { newField->next=sysvarGetDefinition(curField); newField = newField->next; } else { new->def=newField=sysvarGetDefinition(curField); } if (!newField) { snprintf(errMsg, MAX_ERR_MSG, SYSVAR_ERROR, curField->name); return(NULL); } new->rowLen += newField->dataLength + 1; newField->offset = curOffset; curOffset += newField->dataLength + 1; } curField = curField->next; } if (newField) { newField->next = NULL; } /* ** Setup the 8 byte padding for the new table row */ new->rowDataLen = new->rowLen; new->rowLen = new->rowDataLen + (8 - ((new->rowDataLen + HEADER_SIZE) % 8)); new->row.buf = (u_char *)malloc(new->rowLen + HEADER_SIZE + 2); new->row.header = (hdr_t *)new->row.buf; new->row.data = new->row.buf + HEADER_SIZE; debugTrace(TRACE_OUT,"createTargetTable()"); return(new);}static int _tableWriteRow(cacheEntry,row,rowNum, active, query) cache_t *cacheEntry; row_t *row; u_int rowNum; int active; mQuery_t *query;{ off_t seekPos; char *buf; struct stat sbuf; int expandSize; if (cacheEntry->dataFD < 0) { abort(); } cacheEntry->dirty = 1; if (rowNum == NO_POS) { msqlDebug1(MOD_ACCESS,"tableWriteRow() : append to %s\n", (cacheEntry->result)?cacheEntry->resInfo: cacheEntry->table); } else { msqlDebug2(MOD_ACCESS, "tableWriteRow() : write at row %u of %s\n", rowNum, (cacheEntry->result)?cacheEntry->resInfo: cacheEntry->table); } /* ** Write the row to the table */ if (rowNum == NO_POS) /* append */ { seekPos = cacheEntry->sblk->numRows * (cacheEntry->rowLen + HEADER_SIZE) + SBLK_SIZE; cacheEntry->sblk->numRows++; } else { seekPos = rowNum * (cacheEntry->rowLen + HEADER_SIZE) + SBLK_SIZE; } if (seekPos + cacheEntry->rowLen + HEADER_SIZE >= cacheEntry->size) { if (cacheEntry->result) expandSize = 2048; else expandSize = 512; munmap(cacheEntry->dataMap, cacheEntry->size); cacheEntry->dataMap = NULL; cacheEntry->size = 0; lseek(cacheEntry->dataFD, seekPos + (expandSize * cacheEntry->rowLen + HEADER_SIZE), SEEK_SET); write(cacheEntry->dataFD, "\0", 1); fstat(cacheEntry->dataFD, &sbuf); cacheEntry->size = sbuf.st_size; if (cacheEntry->size) { cacheEntry->dataMap = (caddr_t)mmap(NULL, (size_t)cacheEntry->size,(PROT_READ|PROT_WRITE), MAP_SHARED, cacheEntry->dataFD, (off_t)0); if (cacheEntry->dataMap == (caddr_t)-1) return(-1);#ifdef HAVE_MADVISE madvise(cacheEntry->dataMap, cacheEntry->size, MADV_SEQUENTIAL);#endif cacheEntry->sblk=(sblk_t*)cacheEntry->dataMap; cacheEntry->sblk->dataSize = cacheEntry->size; } } buf = ((char *)cacheEntry->dataMap) + seekPos; if (row) { if (active) row->header->active = 1; bcopy(&(query->queryTime),&(row->header->timestamp), sizeof(query->queryTime)); bcopy(row->buf, buf, HEADER_SIZE + cacheEntry->rowLen); } else { if (active) cacheEntry->row.header->active = 1; bcopy(&(query->queryTime),&(cacheEntry->row.header->timestamp), sizeof(query->queryTime)); bcopy(cacheEntry->row.buf, buf, cacheEntry->rowLen + HEADER_SIZE); } return(0);}/**************************************************************************** PUBLIC ROUTINES**************************************************************************//****************************************************************************** _tableOpenTable**** Purpose : Open the datafile for a given table** Args : Database and Table names** Returns : file descriptor for the data file** Notes : */int tableOpenTable(server,table,db) msqld *server; char *table; char *db;{ char path[MSQL_PATH_LEN]; (void)snprintf(path, MSQL_PATH_LEN, "%s/%s/%s.dat", server->config.dbDir,db, table); return(open(path,O_RDWR | O_CREAT, 0600));}int tableOpenOverflow(server,table,db) msqld *server; char *table;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -