Files
sics/hdbtable.c
koennecke 99d2485d22 - Connections write timeouts were incorrectly handled in asynnetc. Fixed.
- Implemented the desired run/drive behaviour: drive waits for what it started
  run starts, and success waits for everything to finish. This required
  changes to a lot of files.
- Fixed a bug in remob which supressed required messages
2009-04-17 12:52:01 +00:00

385 lines
11 KiB
C

/**
* Hdbtable is a more generic implementation for a table based on a Hipadaba
* tree structure. This table will be used at various instances in SICS. The general
* approach is that there is a child node called template whose children will be
* the nodes describing each column. Another entry called data will hold the
* rows of the table. Each row is a clone of the template. The result is
* an inefficient mapping of a table into a tree. But then, for smaller tables this
* is good enough and fits nicely into the Hipadaba and gumtree schemes. This file
* provides a couple of commands to deal with such tables. A user of this module will
* have to add content to the template first. And then run readtemplate in order
* to activate the new structure.
*
* I use a descriptor key called rowcount for the row ID management rather then
* the private data structure. This leaves clients of this module to use the
* private data structure at will.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, March 2009
*/
#include <stdlib.h>
#include "sicshipadaba.h"
#include <hdbtable.h>
/*------------------------------------------------------------------------*/
int SaveHdbTable(void *data, char *name, FILE * fd)
{
pSICSOBJ self = (pSICSOBJ) data;
pHdb datanode, row, child;
pDynString val;
datanode = GetHipadabaNode(self->objectNode,"data");
assert(datanode != NULL);
row = datanode->child;
while(row != NULL){
fprintf(fd,"%s addrow ", name);
child = row->child;
while(child != NULL){
val = formatValue(child->value, child);
if(val != NULL){
fprintf(fd," %s", GetCharArray(val));
DeleteDynString(val);
}
child = child->next;
}
fprintf(fd,"\n");
row = row->next;
}
return 1;
}
/*------------------------------------------------------------------------*/
static int ClearTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb node;
node = GetHipadabaNode(self->objectNode,"data");
if(node != NULL){
if(CountHdbChildren(node) < 1){
return 1;
}
DeleteNodeData(node);
RemoveHdbNodeFromParent(node, pCon);
}
node = MakeHipadabaNode("data",HIPNONE,1);
if(node == NULL){
SCWrite(pCon,"ERROR: out of memory in ClearTblCmd", eError);
return 0;
}
AddHipadabaChild(self->objectNode,node,NULL);
SetDescriptorKey(self->pDes,"rowcount","0");
if(pCon != NULL){
SCparChange(pCon);
}
return 1;
}
/*----------------------------------------------------------------------*/
static int AddTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
int count;
char *ct, number[10];
pHdb row, val, child, template;
ct = GetDescriptorKey(self->pDes,"rowcount");
count = atoi(ct);
snprintf(number,10,"%4.4d", count);
row = MakeHipadabaNode(number,HIPNONE,1);
if(row == NULL){
SCWrite(pCon,"ERROR: out of memory in AddTblRow", eError);
return 0;
}
count++;
snprintf(number,10,"%d",count);
SetDescriptorKey(self->pDes,"rowcount",number);
SetHdbProperty(row,"__save","true");
template = GetHipadabaNode(self->objectNode,"template");
assert(template != NULL);
child = template->child;
count = 0;
while(child != NULL){
val = MakeHipadabaNode(child->name,child->value.dataType, child->value.arrayLength);
if(count < nPar){
UpdateHipadabaPar(val,par[count]->value,pCon);
}
AddHipadabaChild(row,val, pCon);
SetHdbProperty(val,"__save","true");
count++;
child = child->next;
}
child = GetHipadabaNode(self->objectNode,"data");
assert(child != NULL);
AddHipadabaChild(child,row, pCon);
if(pCon != NULL){
SCparChange(pCon);
}
return 1;
}
/*----------------------------------------------------------------------*/
static int RepTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
int count;
char path[132];
pHdb row, val, child;
snprintf(path,131,"data/%s", par[0]->value.v.text);
row = GetHipadabaNode(self->objectNode,path);
if(row == NULL){
SCPrintf(pCon,eError,"ERROR: row with ID %s not found", par[0]->value.v.text);
return 0;
}
child = row->child;
count = 1;
while(child != NULL){
if(count < nPar){
UpdateHipadabaPar(child,par[count]->value,pCon);
}
count++;
child = child->next;
}
if(pCon != NULL){
SCparChange(pCon);
}
return 1;
}
/*----------------------------------------------------------------------
* ReadTemplateCmd does something interesting: it rewrites the parameter
* lists of both addrow and reprow according to the template
* ---------------------------------------------------------------------*/
int ReadTableTemplate(pSICSOBJ self, SConnection *con)
{
pHdb node, template, child, cmd;
SConnection *pCon = con;
if(pCon == NULL){
pCon = pServ->dummyCon;
}
template = GetHipadabaNode(self->objectNode,"template");
assert(template != NULL);
node = GetHipadabaNode(self->objectNode,"addrow");
if(node != NULL){
DeleteHipadabaNode(node,pCon);
}
cmd = AddSICSHdbPar(self->objectNode, "addrow", usUser,
MakeSICSFunc(AddTblRowCmd));
if(cmd == NULL){
SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError );
return 0;
}
child = template->child;
while(child != NULL){
node = MakeHipadabaNode(child->name, child->value.dataType, child->value.arrayLength);
if(node == NULL){
SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError );
return 0;
}
AddHipadabaChild(cmd,node,pCon);
child = child->next;
}
cmd = AddSICSHdbPar(self->objectNode, "reprow", usUser,
MakeSICSFunc(AddTblRowCmd));
if(cmd == NULL){
SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError );
return 0;
}
node = MakeHipadabaNode("id",HIPTEXT,1);
AddHipadabaChild(cmd,node, pCon);
child = template->child;
while(child != NULL){
node = MakeHipadabaNode(child->name, child->value.dataType, child->value.arrayLength);
if(node == NULL){
SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError );
return 0;
}
AddHipadabaChild(cmd,node,pCon);
child = child->next;
}
return 1;
}
/*----------------------------------------------------------------------*/
static int ReadTemplateCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
return ReadTableTemplate(self,pCon);
}
/*----------------------------------------------------------------------*/
static int DelRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb row = NULL;
char path[132];
if(nPar < 1){
SCWrite(pCon,"ERROR: need ID of row to kill",eError);
return 0;
}
snprintf(path,132,"data/%s",par[0]->value.v.text);
row = GetHipadabaNode(self->objectNode,path);
if(row == NULL){
SCPrintf(pCon,eError,"ERROR: row with ID %s not found", par[0]->value.v.text);
return 0;
}
DeleteHipadabaNode(row,pCon);
if(pCon != NULL){
SCparChange(pCon);
}
SCSendOK(pCon);
return 1;
}
/*----------------------------------------------------------------------*/
static int GetRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb row = NULL, child;
char path[132];
pDynString result, val;
if(nPar < 1){
SCWrite(pCon,"ERROR: need ID of row to read",eError);
return 0;
}
snprintf(path,132,"data/%s",par[0]->value.v.text);
row = GetHipadabaNode(self->objectNode,path);
if(row == NULL){
SCPrintf(pCon,eError,"ERROR: row with ID %s not found", par[0]->value.v.text);
return 0;
}
result = CreateDynString(128,128);
if(result == NULL){
SCWrite(pCon,"ERROR: out of memory in GetRowCmd", eError);
return 0;
}
child = row->child;
while(child != NULL){
val = formatValue(child->value, child);
if(val != NULL){
DynStringConcat(result,GetCharArray(val));
if(child->next != NULL){
DynStringConcatChar(result,',');
}
DeleteDynString(val);
}
child = child->next;
}
SCWrite(pCon,GetCharArray(result),eValue);
DeleteDynString(result);
return 1;
}
/*----------------------------------------------------------------------*/
static int ListTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb node, row, child, data, template;
char buffer[20];
pDynString list = NULL, val;
list = CreateDynString(25,256);
if(list == NULL){
SCWrite(pCon,"ERROR: out of memory in LisTblCmd", eError);
return 0;
}
/*
* create the list header
*/
DynStringConcat(list," ID");
template = GetHipadabaNode(self->objectNode,"template");
assert(template != NULL);
child = template->child;
while(child != NULL){
snprintf(buffer,20," %8s", child->name);
DynStringConcat(list,buffer);
child = child->next;
}
DynStringConcatChar(list,'\n');
data = GetHipadabaNode(self->objectNode,"data");
assert(data != NULL);
/*
* list the data
*/
row = data->child;
while(row != NULL){
snprintf(buffer,20," %8s", row->name);
DynStringConcat(list,buffer);
child = row->child;
while(child != NULL){
val = formatValue(child->value,child);
snprintf(buffer,20," %8s", GetCharArray(val));
DynStringConcat(list,buffer);
DeleteDynString(val);
child = child->next;
}
DynStringConcatChar(list,'\n');
row = row->next;
}
SCWrite(pCon,GetCharArray(list),eValue);
DeleteDynString(list);
return 1;
}
/*----------------------------------------------------------------------*/
pSICSOBJ MakeHdbTable(char *name, char *hdbclass)
{
pSICSOBJ result = NULL;
pHdb node, cmd;
result = MakeSICSOBJv(name,hdbclass,HIPNONE,usSpy);
if(result == NULL){
return NULL;
}
SetDescriptorKey(result->pDes,"rowcount","0");
SetHdbProperty(result->objectNode,"viewer","mountaingumui.TableViewer");
result->pDes->SaveStatus = SaveHdbTable;
node = MakeHipadabaNode("template",HIPNONE,1);
if(node == NULL){
return NULL;
}
SetHdbProperty(node,"__save","true");
AddHipadabaChild(result->objectNode,node,NULL);
node = MakeHipadabaNode("data",HIPNONE,1);
if(node == NULL){
return NULL;
}
SetHdbProperty(node,"__save","true");
AddHipadabaChild(result->objectNode,node,NULL);
cmd = AddSICSHdbPar(result->objectNode, "clear", usUser,
MakeSICSFunc(ClearTblCmd));
cmd = AddSICSHdbPar(result->objectNode, "print", usUser,
MakeSICSFunc(ListTblCmd));
cmd = AddSICSHdbPar(result->objectNode, "addrow", usUser,
MakeSICSFunc(AddTblRowCmd));
cmd = AddSICSHdbPar(result->objectNode, "reprow", usUser,
MakeSICSFunc(RepTblRowCmd));
cmd = AddSICSHdbPar(result->objectNode, "readtemplate", usUser,
MakeSICSFunc(ReadTemplateCmd));
cmd = AddSICSHdbPar(result->objectNode, "del", usUser,
MakeSICSFunc(DelRowCmd));
node = MakeHipadabaNode("id",HIPTEXT,1);
AddHipadabaChild(cmd,node, NULL);
cmd = AddSICSHdbPar(result->objectNode, "get", usUser,
MakeSICSFunc(GetRowCmd));
node = MakeHipadabaNode("id",HIPTEXT,1);
AddHipadabaChild(cmd,node, NULL);
return result;
}