14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* cache .c - a LRU cache 24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Copyright (C) 2004-2010 Gerhard H�ring <gh@ghaering.de> 44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * This file is part of pysqlite. 64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * This software is provided 'as-is', without any express or implied 84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * warranty. In no event will the authors be held liable for any damages 94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * arising from the use of this software. 104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * Permission is granted to anyone to use this software for any purpose, 124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * including commercial applications, and to alter it and redistribute it 134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * freely, subject to the following restrictions: 144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 1. The origin of this software must not be misrepresented; you must not 164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * claim that you wrote the original software. If you use this software 174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * in a product, an acknowledgment in the product documentation would be 184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * appreciated but is not required. 194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 2. Altered source versions must be plainly marked as such, and must not be 204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * misrepresented as being the original software. 214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * 3. This notice may not be removed or altered from any source distribution. 224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm */ 234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "sqlitecompat.h" 254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include "cache.h" 264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm#include <limits.h> 274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm/* only used internally */ 294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmpysqlite_Node* pysqlite_new_node(PyObject* key, PyObject* data) 304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pysqlite_Node* node; 324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node = (pysqlite_Node*) (pysqlite_NodeType.tp_alloc(&pysqlite_NodeType, 0)); 344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!node) { 354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(key); 394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->key = key; 404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(data); 424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->data = data; 434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->prev = NULL; 454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->next = NULL; 464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return node; 484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmvoid pysqlite_node_dealloc(pysqlite_Node* self) 514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(self->key); 534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(self->data); 544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TYPE(self)->tp_free((PyObject*)self); 564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmint pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs) 594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject* factory; 614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int size = 10; 624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->factory = NULL; 644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!PyArg_ParseTuple(args, "O|i", &factory, &size)) { 664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* minimum cache size is 5 entries */ 704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (size < 5) { 714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm size = 5; 724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->size = size; 744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->first = NULL; 754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->last = NULL; 764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->mapping = PyDict_New(); 784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!self->mapping) { 794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return -1; 804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(factory); 834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->factory = factory; 844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->decref_factory = 1; 864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return 0; 884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmvoid pysqlite_cache_dealloc(pysqlite_Cache* self) 914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pysqlite_Node* node; 934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pysqlite_Node* delete_node; 944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!self->factory) { 964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* constructor failed, just get out of here */ 974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return; 984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* iterate over all nodes and deallocate them */ 1014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node = self->first; 1024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while (node) { 1034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm delete_node = node; 1044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node = node->next; 1054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(delete_node); 1064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->decref_factory) { 1094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(self->factory); 1104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(self->mapping); 1124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TYPE(self)->tp_free((PyObject*)self); 1144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 1154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args) 1174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 1184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject* key = args; 1194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pysqlite_Node* node; 1204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pysqlite_Node* ptr; 1214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject* data; 1224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node = (pysqlite_Node*)PyDict_GetItem(self->mapping, key); 1244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (node) { 1254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* an entry for this key already exists in the cache */ 1264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* increase usage counter of the node found */ 1284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (node->count < LONG_MAX) { 1294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->count++; 1304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* if necessary, reorder entries in the cache by swapping positions */ 1334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (node->prev && node->count > node->prev->count) { 1344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptr = node->prev; 1354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while (ptr->prev && node->count > ptr->prev->count) { 1374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptr = ptr->prev; 1384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (node->next) { 1414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->next->prev = node->prev; 1424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } else { 1434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->last = node->prev; 1444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (node->prev) { 1464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->prev->next = node->next; 1474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (ptr->prev) { 1494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptr->prev->next = node; 1504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } else { 1514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->first = node; 1524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->next = ptr; 1554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->prev = ptr->prev; 1564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!node->prev) { 1574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->first = node; 1584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptr->prev = node; 1604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } else { 1624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm /* There is no entry for this key in the cache, yet. We'll insert a new 1634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * entry in the cache, and make space if necessary by throwing the 1644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm * least used item out of the cache. */ 1654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyDict_Size(self->mapping) == self->size) { 1674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->last) { 1684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node = self->last; 1694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyDict_DelItem(self->mapping, self->last->key) != 0) { 1714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 1724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (node->prev) { 1754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->prev->next = NULL; 1764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->last = node->prev; 1784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->prev = NULL; 1794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(node); 1814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm data = PyObject_CallFunction(self->factory, "O", key); 1854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!data) { 1874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 1884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node = pysqlite_new_node(key, data); 1914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!node) { 1924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 1934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 1944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm node->prev = self->last; 1954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(data); 1974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 1984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (PyDict_SetItem(self->mapping, key, (PyObject*)node) != 0) { 1994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(node); 2004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 2014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (self->last) { 2044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->last->next = node; 2054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } else { 2064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->first = node; 2074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm self->last = node; 2094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(node->data); 2124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return node->data; 2134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 2144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args) 2164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 2174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pysqlite_Node* ptr; 2184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject* prevkey; 2194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject* nextkey; 2204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject* fmt_args; 2214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject* template; 2224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject* display_str; 2234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptr = self->first; 2254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm while (ptr) { 2274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (ptr->prev) { 2284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm prevkey = ptr->prev->key; 2294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } else { 2304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm prevkey = Py_None; 2314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(prevkey); 2334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (ptr->next) { 2354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm nextkey = ptr->next->key; 2364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } else { 2374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm nextkey = Py_None; 2384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(nextkey); 2404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm fmt_args = Py_BuildValue("OOO", prevkey, ptr->key, nextkey); 2424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!fmt_args) { 2434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 2444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm template = PyString_FromString("%s <- %s ->%s\n"); 2464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!template) { 2474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(fmt_args); 2484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 2494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm display_str = PyString_Format(template, fmt_args); 2514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(template); 2524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(fmt_args); 2534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (!display_str) { 2544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return NULL; 2554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyObject_Print(display_str, stdout, Py_PRINT_RAW); 2574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(display_str); 2584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(prevkey); 2604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_DECREF(nextkey); 2614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm ptr = ptr->next; 2634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 2644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_INCREF(Py_None); 2664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return Py_None; 2674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 2684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmstatic PyMethodDef cache_methods[] = { 2704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"get", (PyCFunction)pysqlite_cache_get, METH_O, 2714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyDoc_STR("Gets an entry from the cache or calls the factory function to produce one.")}, 2724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {"display", (PyCFunction)pysqlite_cache_display, METH_NOARGS, 2734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyDoc_STR("For debugging only.")}, 2744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm {NULL, NULL} 2754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 2764710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 2774710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyTypeObject pysqlite_NodeType = { 2784710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyVarObject_HEAD_INIT(NULL, 0) 2794710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm MODULE_NAME "Node", /* tp_name */ 2804710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sizeof(pysqlite_Node), /* tp_basicsize */ 2814710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_itemsize */ 2824710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (destructor)pysqlite_node_dealloc, /* tp_dealloc */ 2834710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_print */ 2844710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getattr */ 2854710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattr */ 2864710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_compare */ 2874710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_repr */ 2884710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_number */ 2894710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_sequence */ 2904710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_mapping */ 2914710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_hash */ 2924710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_call */ 2934710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_str */ 2944710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getattro */ 2954710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattro */ 2964710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_buffer */ 2974710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 2984710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_doc */ 2994710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_traverse */ 3004710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_clear */ 3014710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_richcompare */ 3024710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_weaklistoffset */ 3034710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_iter */ 3044710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_iternext */ 3054710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_methods */ 3064710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_members */ 3074710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getset */ 3084710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_base */ 3094710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_dict */ 3104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_get */ 3114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_set */ 3124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_dictoffset */ 3134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (initproc)0, /* tp_init */ 3144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_alloc */ 3154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_new */ 3164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0 /* tp_free */ 3174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 3184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmPyTypeObject pysqlite_CacheType = { 3204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm PyVarObject_HEAD_INIT(NULL, 0) 3214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm MODULE_NAME ".Cache", /* tp_name */ 3224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm sizeof(pysqlite_Cache), /* tp_basicsize */ 3234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_itemsize */ 3244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (destructor)pysqlite_cache_dealloc, /* tp_dealloc */ 3254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_print */ 3264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getattr */ 3274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattr */ 3284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_compare */ 3294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_repr */ 3304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_number */ 3314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_sequence */ 3324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_mapping */ 3334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_hash */ 3344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_call */ 3354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_str */ 3364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getattro */ 3374710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_setattro */ 3384710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_as_buffer */ 3394710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 3404710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_doc */ 3414710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_traverse */ 3424710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_clear */ 3434710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_richcompare */ 3444710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_weaklistoffset */ 3454710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_iter */ 3464710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_iternext */ 3474710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm cache_methods, /* tp_methods */ 3484710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_members */ 3494710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_getset */ 3504710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_base */ 3514710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_dict */ 3524710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_get */ 3534710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_descr_set */ 3544710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_dictoffset */ 3554710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm (initproc)pysqlite_cache_init, /* tp_init */ 3564710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_alloc */ 3574710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0, /* tp_new */ 3584710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 0 /* tp_free */ 3594710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm}; 3604710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3614710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmextern int pysqlite_cache_setup_types(void) 3624710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm{ 3634710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm int rc; 3644710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3654710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pysqlite_NodeType.tp_new = PyType_GenericNew; 3664710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm pysqlite_CacheType.tp_new = PyType_GenericNew; 3674710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3684710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rc = PyType_Ready(&pysqlite_NodeType); 3694710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm if (rc < 0) { 3704710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return rc; 3714710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm } 3724710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm 3734710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm rc = PyType_Ready(&pysqlite_CacheType); 3744710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm return rc; 3754710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm} 376