postgresql/src/backend/port/beos/support.c

259 lines
6.2 KiB
C
Raw Normal View History

2000-10-07 16:16:02 +02:00
/*-------------------------------------------------------------------------
*
* support.c
* BeOS Support functions
*
* Copyright (c) 1999-2000, Cyril VELTER
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
/* Support Globals */
char* self_binary=NULL;
port_id beos_dl_port_in=0;
port_id beos_dl_port_out=0;
sem_id beos_shm_sem;
image_id beos_dl_open(char * filename)
{
image_id im;
/* Start the support server */
if (self_binary==NULL)
{
/* Can't start support server without binary name */
elog(NOTICE, "Error loading BeOS support server : can't find binary");
return B_ERROR;
}
else
{
/* If a port doesn't exist, lauch support server */
if ((beos_dl_port_in<=0)||(beos_dl_port_out<=0))
{
/* Create communication port */
beos_dl_port_in=create_port(50,"beos_support_in");
beos_dl_port_out=create_port(50,"beos_support_in");
if ((beos_dl_port_in<=0)||(beos_dl_port_out<=0))
{
elog(NOTICE, "Error loading BeOS support server : can't create communication ports");
return B_ERROR;
}
else
{
char Cmd[4000];
/* Build arg list */
sprintf(Cmd,"%s -beossupportserver %d %d &",self_binary,(int)beos_dl_port_in,(int)beos_dl_port_out);
/* Lauch process */
system(Cmd);
}
}
}
/* Add-on loading */
/* Send command '1' (load) to the support server */
write_port(beos_dl_port_in,1,filename,strlen(filename)+1);
/* Read Object Id */
read_port(beos_dl_port_out,&im,NULL,0);
/* Checking integrity */
if (im<0)
{
elog(NOTICE, "Can't load this add-on ");
return B_ERROR;
}
else
{
/* Map text and data segment in our address space */
char datas[4000];
int32 area;
int32 resu;
void* add;
/* read text segment id and address */
read_port(beos_dl_port_out,&area,datas,4000);
read_port(beos_dl_port_out,(void*)&add,datas,4000);
/* map text segment in our address space */
resu=clone_area(datas,&add,B_EXACT_ADDRESS,B_READ_AREA|B_WRITE_AREA,area);
if (resu<0)
{
/* If we can't map, we are in reload case */
/* delete the mapping */
resu=delete_area(area_for(add));
/* Remap */
resu=clone_area(datas,&add,B_EXACT_ADDRESS,B_READ_AREA|B_WRITE_AREA,area);
if (resu<0)
{
elog(NOTICE, "Can't load this add-on : map text error");
}
}
/* read text segment id and address */
read_port(beos_dl_port_out,&area,datas,4000);
read_port(beos_dl_port_out,(void*)&add,datas,4000);
/* map text segment in our address space */
resu=clone_area(datas,&add,B_EXACT_ADDRESS,B_READ_AREA|B_WRITE_AREA,area);
if (resu<0)
{
/* If we can't map, we are in reload case */
/* delete the mapping */
resu=delete_area(area_for(add));
/* Remap */
resu=clone_area(datas,&add,B_EXACT_ADDRESS,B_READ_AREA|B_WRITE_AREA,area);
if (resu<0)
{
elog(NOTICE, "Can't load this add-on : map data error");
}
}
return im;
}
}
status_t beos_dl_close(image_id im)
{
/* unload add-on */
int32 resu;
write_port(beos_dl_port_in,2,&im,4);
read_port(beos_dl_port_out,&resu,NULL,0);
return resu;
}
/* Main support server loop */
void beos_startup(int argc,char** argv)
{
if (strlen(argv[0]) >= 10 && !strcmp(argv[0] + strlen(argv[0]) - 10, "postmaster"))
{
/* Shared memory cloning protection semaphore */
beos_shm_sem=create_sem(1,"beos_shm_sem");
}
if (argc > 1 && strcmp(argv[1], "-beossupportserver") == 0)
{
port_id port_in;
port_id port_out;
/* Get back port ids from arglist */
sscanf(argv[2],"%d",(int*)(&port_in));
sscanf(argv[3],"%d",(int*)(&port_out));
/* Main server loop */
for (;;)
{
int32 opcode=0;
char datas[4000];
/* Wait for a message from the backend :
1 : load a shared object
2 : unload a shared object
any other : exit support server */
read_port(port_in,&opcode,datas,4000);
switch(opcode)
{
image_id addon;
image_info info_im;
area_info info_ar;
/* Load Add-On */
case 1 :
/* Load shared object */
addon=load_add_on(datas);
/* send back the shared object Id */
write_port(port_out,addon,NULL,0);
/* Get Shared Object infos */
get_image_info(addon,&info_im);
/* get text segment info */
get_area_info(area_for(info_im.text),&info_ar);
/* Send back area_id of text segment */
write_port(port_out,info_ar.area,info_ar.name,strlen(info_ar.name)+1);
/* Send back real address of text segment */
write_port(port_out,(int)info_ar.address,info_ar.name,strlen(info_ar.name)+1);
/* get data segment info */
get_area_info(area_for(info_im.data),&info_ar);
/* Send back area_id of data segment */
write_port(port_out,info_ar.area,info_ar.name,strlen(info_ar.name)+1);
/* Send back real address of data segment */
write_port(port_out,(int)info_ar.address,info_ar.name,strlen(info_ar.name)+1);
break;
/* UnLoad Add-On */
case 2 :
/* Unload shared object and send back the result of the operation */
write_port(port_out,unload_add_on(*((int*)(datas))),NULL,0);
break;
/* Cleanup and exit */
default:
/* Free system resources */
delete_port(port_in);
delete_port(port_out);
/* Exit */
exit(0);
break;
}
}
/* Never be there */
exit(1);
}
}
void beos_backend_startup(char * binary)
{
team_id ct;
thread_info inft;
char nom[50];
char nvnom[50];
area_info inf;
int32 cook=0;
/* remember full path binary name to load dl*/
self_binary=strdup(binary);
/* find the current team */
get_thread_info(find_thread(NULL),&inft);
ct=inft.team;
/* find all area with a name begining by pgsql and destroy / clone then */
/* This operation must be done by only one backend at a time */
if(acquire_sem(beos_shm_sem)==B_OK)
{
while (get_next_area_info(0, &cook, &inf) == B_OK)
{
strcpy(nom,inf.name);
strcpy(nvnom,inf.name);
nom[9]=0;
nvnom[5]='i';
if (!strcmp(nom,"SYSV_IPC_"))
{
void* add;
area_id ar;
add=inf.address;
delete_area(inf.area);
ar=find_area(inf.name);
clone_area(nvnom,&add,B_CLONE_ADDRESS,B_READ_AREA|B_WRITE_AREA,ar);
}
}
release_sem(beos_shm_sem);
}
else
{
/* Fatal error, exiting with error */
exit(1);
}
}