- 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
385 lines
11 KiB
C
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;
|
|
}
|