tcl_internal.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:9k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*-
  2.  * See the file LICENSE for redistribution information.
  3.  *
  4.  * Copyright (c) 1999, 2000
  5.  * Sleepycat Software.  All rights reserved.
  6.  */
  7. #include "db_config.h"
  8. #ifndef lint
  9. static const char revid[] = "$Id: tcl_internal.c,v 11.27 2000/05/22 18:36:51 sue Exp $";
  10. #endif /* not lint */
  11. #ifndef NO_SYSTEM_INCLUDES
  12. #include <sys/types.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <tcl.h>
  16. #endif
  17. #include "db_int.h"
  18. #include "tcl_db.h"
  19. #include "db_page.h"
  20. #include "db_am.h"
  21. #include "db_ext.h"
  22. /*
  23.  *
  24.  * internal.c --
  25.  *
  26.  * This file contains internal functions we need to maintain
  27.  * state for our Tcl interface.
  28.  *
  29.  * NOTE: This all uses a linear linked list.  If we end up with
  30.  * too many info structs such that this is a performance hit, it
  31.  * should be redone using hashes or a list per type.  The assumption
  32.  * is that the user won't have more than a few dozen info structs
  33.  * in operation at any given point in time.  Even a complicated
  34.  * application with a few environments, nested transactions, locking,
  35.  * and several databases open, using cursors should not have a
  36.  * negative performance impact, in terms of searching the list to
  37.  * get/manipulate the info structure.
  38.  */
  39. /*
  40.  * Prototypes for procedures defined later in this file:
  41.  */
  42. #define GLOB_CHAR(c) ((c) == '*' || (c) == '?')
  43. /*
  44.  * PUBLIC: DBTCL_INFO *_NewInfo __P((Tcl_Interp *,
  45.  * PUBLIC:    void *, char *, enum INFOTYPE));
  46.  *
  47.  * _NewInfo --
  48.  *
  49.  * This function will create a new info structure and fill it in
  50.  * with the name and pointer, id and type.
  51.  */
  52. DBTCL_INFO *
  53. _NewInfo(interp, anyp, name, type)
  54. Tcl_Interp *interp;
  55. void *anyp;
  56. char *name;
  57. enum INFOTYPE type;
  58. {
  59. DBTCL_INFO *p;
  60. int i, ret;
  61. if ((ret = __os_malloc(NULL, sizeof(DBTCL_INFO), NULL, &p)) != 0) {
  62. Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
  63. return (NULL);
  64. }
  65. if ((ret = __os_strdup(NULL, name, &p->i_name)) != 0) {
  66. Tcl_SetResult(interp, db_strerror(ret), TCL_STATIC);
  67. __os_free(p, sizeof(DBTCL_INFO));
  68. return (NULL);
  69. }
  70. p->i_interp = interp;
  71. p->i_anyp = anyp;
  72. p->i_data = 0;
  73. p->i_data2 = 0;
  74. p->i_type = type;
  75. p->i_parent = NULL;
  76. p->i_err = NULL;
  77. p->i_errpfx = NULL;
  78. p->i_lockobj.data = NULL;
  79. for (i = 0; i < MAX_ID; i++)
  80. p->i_otherid[i] = 0;
  81. LIST_INSERT_HEAD(&__db_infohead, p, entries);
  82. return (p);
  83. }
  84. /*
  85.  * PUBLIC: void *_NameToPtr __P((CONST char *));
  86.  */
  87. void *
  88. _NameToPtr(name)
  89. CONST char *name;
  90. {
  91. DBTCL_INFO *p;
  92. for (p = LIST_FIRST(&__db_infohead); p != NULL;
  93.     p = LIST_NEXT(p, entries))
  94. if (strcmp(name, p->i_name) == 0)
  95. return (p->i_anyp);
  96. return (NULL);
  97. }
  98. /*
  99.  * PUBLIC: char *_PtrToName __P((CONST void *));
  100.  */
  101. char *
  102. _PtrToName(ptr)
  103. CONST void *ptr;
  104. {
  105. DBTCL_INFO *p;
  106. for (p = LIST_FIRST(&__db_infohead); p != NULL;
  107.     p = LIST_NEXT(p, entries))
  108. if (p->i_anyp == ptr)
  109. return (p->i_name);
  110. return (NULL);
  111. }
  112. /*
  113.  * PUBLIC: DBTCL_INFO *_PtrToInfo __P((CONST void *));
  114.  */
  115. DBTCL_INFO *
  116. _PtrToInfo(ptr)
  117. CONST void *ptr;
  118. {
  119. DBTCL_INFO *p;
  120. for (p = LIST_FIRST(&__db_infohead); p != NULL;
  121.     p = LIST_NEXT(p, entries))
  122. if (p->i_anyp == ptr)
  123. return (p);
  124. return (NULL);
  125. }
  126. /*
  127.  * PUBLIC: DBTCL_INFO *_NameToInfo __P((CONST char *));
  128.  */
  129. DBTCL_INFO *
  130. _NameToInfo(name)
  131. CONST char *name;
  132. {
  133. DBTCL_INFO *p;
  134. for (p = LIST_FIRST(&__db_infohead); p != NULL;
  135.     p = LIST_NEXT(p, entries))
  136. if (strcmp(name, p->i_name) == 0)
  137. return (p);
  138. return (NULL);
  139. }
  140. /*
  141.  * PUBLIC: void  _SetInfoData __P((DBTCL_INFO *, void *));
  142.  */
  143. void
  144. _SetInfoData(p, data)
  145. DBTCL_INFO *p;
  146. void *data;
  147. {
  148. if (p == NULL)
  149. return;
  150. p->i_anyp = data;
  151. return;
  152. }
  153. /*
  154.  * PUBLIC: void  _DeleteInfo __P((DBTCL_INFO *));
  155.  */
  156. void
  157. _DeleteInfo(p)
  158. DBTCL_INFO *p;
  159. {
  160. if (p == NULL)
  161. return;
  162. LIST_REMOVE(p, entries);
  163. if (p->i_lockobj.data != NULL)
  164. __os_free(p->i_lockobj.data, p->i_lockobj.size);
  165. if (p->i_err != NULL) {
  166. fclose(p->i_err);
  167. p->i_err = NULL;
  168. }
  169. if (p->i_errpfx != NULL)
  170. __os_freestr(p->i_errpfx);
  171. __os_freestr(p->i_name);
  172. __os_free(p, sizeof(DBTCL_INFO));
  173. return;
  174. }
  175. /*
  176.  * PUBLIC: int _SetListElem __P((Tcl_Interp *,
  177.  * PUBLIC:    Tcl_Obj *, void *, int, void *, int));
  178.  */
  179. int
  180. _SetListElem(interp, list, elem1, e1cnt, elem2, e2cnt)
  181. Tcl_Interp *interp;
  182. Tcl_Obj *list;
  183. void *elem1, *elem2;
  184. int e1cnt, e2cnt;
  185. {
  186. Tcl_Obj *myobjv[2], *thislist;
  187. int myobjc;
  188. myobjc = 2;
  189. myobjv[0] = Tcl_NewByteArrayObj((u_char *)elem1, e1cnt);
  190. myobjv[1] = Tcl_NewByteArrayObj((u_char *)elem2, e2cnt);
  191. thislist = Tcl_NewListObj(myobjc, myobjv);
  192. if (thislist == NULL)
  193. return (TCL_ERROR);
  194. return (Tcl_ListObjAppendElement(interp, list, thislist));
  195. }
  196. /*
  197.  * PUBLIC: int _SetListElemInt __P((Tcl_Interp *, Tcl_Obj *, void *, int));
  198.  */
  199. int
  200. _SetListElemInt(interp, list, elem1, elem2)
  201. Tcl_Interp *interp;
  202. Tcl_Obj *list;
  203. void *elem1;
  204. int elem2;
  205. {
  206. Tcl_Obj *myobjv[2], *thislist;
  207. int myobjc;
  208. myobjc = 2;
  209. myobjv[0] = Tcl_NewByteArrayObj((u_char *)elem1, strlen((char *)elem1));
  210. myobjv[1] = Tcl_NewIntObj(elem2);
  211. thislist = Tcl_NewListObj(myobjc, myobjv);
  212. if (thislist == NULL)
  213. return (TCL_ERROR);
  214. return (Tcl_ListObjAppendElement(interp, list, thislist));
  215. }
  216. /*
  217.  * PUBLIC: int _SetListRecnoElem __P((Tcl_Interp *, Tcl_Obj *,
  218.  * PUBLIC:     db_recno_t, u_char *, int));
  219.  */
  220. int
  221. _SetListRecnoElem(interp, list, elem1, elem2, e2size)
  222. Tcl_Interp *interp;
  223. Tcl_Obj *list;
  224. db_recno_t elem1;
  225. u_char *elem2;
  226. int e2size;
  227. {
  228. Tcl_Obj *myobjv[2], *thislist;
  229. int myobjc;
  230. myobjc = 2;
  231. myobjv[0] = Tcl_NewIntObj(elem1);
  232. myobjv[1] = Tcl_NewByteArrayObj(elem2, e2size);
  233. thislist = Tcl_NewListObj(myobjc, myobjv);
  234. if (thislist == NULL)
  235. return (TCL_ERROR);
  236. return (Tcl_ListObjAppendElement(interp, list, thislist));
  237. }
  238. /*
  239.  * PUBLIC: int _GetGlobPrefix __P((char *, char **));
  240.  */
  241. int
  242. _GetGlobPrefix(pattern, prefix)
  243. char *pattern;
  244. char **prefix;
  245. {
  246. int i, j;
  247. char *p;
  248. /*
  249.  * Duplicate it, we get enough space and most of the work is done.
  250.  */
  251. if (__os_strdup(NULL, pattern, prefix) != 0)
  252. return (1);
  253. p = *prefix;
  254. for (i = 0, j = 0; p[i] && !GLOB_CHAR(p[i]); i++, j++)
  255. /*
  256.  * Check for an escaped character and adjust
  257.  */
  258. if (p[i] == '\' && p[i+1]) {
  259. p[j] = p[i+1];
  260. i++;
  261. } else
  262. p[j] = p[i];
  263. p[j] = 0;
  264. return (0);
  265. }
  266. /*
  267.  * PUBLIC: int _ReturnSetup __P((Tcl_Interp *, int, char *));
  268.  */
  269. int
  270. _ReturnSetup(interp, ret, errmsg)
  271. Tcl_Interp *interp;
  272. int ret;
  273. char *errmsg;
  274. {
  275. char *msg;
  276. if (ret > 0)
  277. return (_ErrorSetup(interp, ret, errmsg));
  278. /*
  279.  * We either have success or a DB error.  If a DB error, set up the
  280.  * string.  We return an error if not one of the errors we catch.
  281.  * If anyone wants to reset the result to return anything different,
  282.  * then the calling function is responsible for doing so via
  283.  * Tcl_ResetResult or another Tcl_SetObjResult.
  284.  */
  285. if (ret == 0) {
  286. Tcl_SetResult(interp, "0", TCL_STATIC);
  287. return (TCL_OK);
  288. }
  289. msg = db_strerror(ret);
  290. Tcl_AppendResult(interp, msg, NULL);
  291. switch (ret) {
  292. case DB_NOTFOUND:
  293. case DB_KEYEXIST:
  294. case DB_KEYEMPTY:
  295. return (TCL_OK);
  296. default:
  297. Tcl_SetErrorCode(interp, "BerkeleyDB", msg, NULL);
  298. return (TCL_ERROR);
  299. }
  300. }
  301. /*
  302.  * PUBLIC: int _ErrorSetup __P((Tcl_Interp *, int, char *));
  303.  */
  304. int
  305. _ErrorSetup(interp, ret, errmsg)
  306. Tcl_Interp *interp;
  307. int ret;
  308. char *errmsg;
  309. {
  310. Tcl_SetErrno(ret);
  311. Tcl_AppendResult(interp, errmsg, ":", Tcl_PosixError(interp), NULL);
  312. return (TCL_ERROR);
  313. }
  314. /*
  315.  * PUBLIC: void _ErrorFunc __P((CONST char *, char *));
  316.  */
  317. void
  318. _ErrorFunc(pfx, msg)
  319. CONST char *pfx;
  320. char *msg;
  321. {
  322. DBTCL_INFO *p;
  323. Tcl_Interp *interp;
  324. int size;
  325. char *err;
  326. p = _NameToInfo(pfx);
  327. if (p == NULL)
  328. return;
  329. interp = p->i_interp;
  330. size = strlen(pfx) + strlen(msg) + 4;
  331. /*
  332.  * If we cannot allocate enough to put together the prefix
  333.  * and message then give them just the message.
  334.  */
  335. if (__os_malloc(NULL, size, NULL, &err) != 0) {
  336. Tcl_AddErrorInfo(interp, msg);
  337. Tcl_AppendResult(interp, msg, "n", NULL);
  338. return;
  339. }
  340. snprintf(err, size, "%s: %s", pfx, msg);
  341. Tcl_AddErrorInfo(interp, err);
  342. Tcl_AppendResult(interp, err, "n", NULL);
  343. __os_free(err, size);
  344. return;
  345. }
  346. #define INVALID_LSNMSG "Invalid LSN with %d parts. Should have 2.n"
  347. /*
  348.  * PUBLIC: int _GetLsn __P((Tcl_Interp *, Tcl_Obj *, DB_LSN *));
  349.  */
  350. int
  351. _GetLsn(interp, obj, lsn)
  352. Tcl_Interp *interp;
  353. Tcl_Obj *obj;
  354. DB_LSN *lsn;
  355. {
  356. Tcl_Obj **myobjv;
  357. int itmp, myobjc, result;
  358. char msg[MSG_SIZE];
  359. result = Tcl_ListObjGetElements(interp, obj, &myobjc, &myobjv);
  360. if (result == TCL_ERROR)
  361. return (result);
  362. if (myobjc != 2) {
  363. result = TCL_ERROR;
  364. snprintf(msg, MSG_SIZE, INVALID_LSNMSG, myobjc);
  365. Tcl_SetResult(interp, msg, TCL_VOLATILE);
  366. return (result);
  367. }
  368. result = Tcl_GetIntFromObj(interp, myobjv[0], &itmp);
  369. if (result == TCL_ERROR)
  370. return (result);
  371. lsn->file = itmp;
  372. result = Tcl_GetIntFromObj(interp, myobjv[1], &itmp);
  373. lsn->offset = itmp;
  374. return (result);
  375. }
  376. int __debug_stop, __debug_on, __debug_print, __debug_test;
  377. /*
  378.  * PUBLIC: void _debug_check  __P((void));
  379.  */
  380. void
  381. _debug_check()
  382. {
  383. if (__debug_on == 0)
  384. return;
  385. if (__debug_print != 0) {
  386. printf("r%6d:", __debug_on);
  387. fflush(stdout);
  388. }
  389. if (__debug_on++ == __debug_test || __debug_stop)
  390. __db_loadme();
  391. }