211 lines
5.1 KiB
Go
211 lines
5.1 KiB
Go
package main
|
|
|
|
/*
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <errno.h>
|
|
|
|
#include "client.h"
|
|
#include "netio.h"
|
|
#include "controller.capnp.h"
|
|
#include "helper.h"
|
|
|
|
typedef struct {
|
|
xcecli_ctx_t ctx;
|
|
uintptr_t go_handler;
|
|
void* go_apiserver;
|
|
} apiserver_ctx_t;
|
|
|
|
extern int go_callback(uintptr_t, xce_request_t*, apiserver_ctx_t *);
|
|
|
|
static int xce_apiserver_handler(xce_request_t *req, void *arg) {
|
|
int rc = -EINVAL;
|
|
apiserver_ctx_t *ctx = (apiserver_ctx_t *)arg;
|
|
|
|
if (ctx == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (ctx->go_handler != 0) {
|
|
rc = go_callback(ctx->go_handler, req, arg);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int xce_apiserver_init(xce_client_config_t *config, apiserver_ctx_t *ctx) {
|
|
int rc;
|
|
|
|
if ((config == NULL) || (ctx == NULL)) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
rc = xcecli_ctx_init(&(ctx->ctx), config);
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
xcecli_set_handler(ctx->ctx, (xce_request_handler_t)xce_apiserver_handler, ctx);
|
|
|
|
rc = xcecli_start(ctx->ctx);
|
|
if (rc < 0) {
|
|
return rc;
|
|
}
|
|
|
|
rc = xcecli_join(ctx->ctx, HostRole_apiserver, NULL);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static xce_job_t **dataset_jobs(dataset_t *d) {
|
|
return (xce_job_t **)d->rows;
|
|
}
|
|
|
|
static xce_worker_t **dataset_workers(dataset_t *d) {
|
|
return (xce_worker_t **)d->rows;
|
|
}
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"fmt"
|
|
"unsafe"
|
|
"runtime/cgo"
|
|
"log"
|
|
"net/http"
|
|
)
|
|
|
|
type ApiServer struct {
|
|
// add data here
|
|
}
|
|
|
|
//export go_callback
|
|
func go_callback(h C.uintptr_t, req *C.xce_request_t, ctx *C.apiserver_ctx_t) C.int {
|
|
fn := cgo.Handle(h).Value().(func(*C.xce_request_t,*C.apiserver_ctx_t) C.int)
|
|
return fn(req, ctx);
|
|
}
|
|
|
|
func (apiserver *ApiServer) handle_config(config *C.xce_configdata_t) C.int {
|
|
switch (config.data_which) {
|
|
case C.ConfigData_data_clusterconfig:
|
|
fmt.Printf("cluster configuration received\n")
|
|
// Extract configuration information from config
|
|
// - queues
|
|
// - resources information
|
|
// - and other information
|
|
default:
|
|
//
|
|
fmt.Printf("unhandled config request %d\n", config.data_which)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func print_job(job *C.xce_job_t) {
|
|
fmt.Printf("jobid `%v' user `%s' queue `%s'\n",uint64(job.jobid), C.GoString(job.submit.user), C.GoString(job.submit.queue))
|
|
}
|
|
|
|
func print_worker(w *C.xce_worker_t) {
|
|
fmt.Printf("worker `%s'\n", C.GoString(w.name))
|
|
}
|
|
|
|
func (apiserver *ApiServer) handle_job_push(jobs []*C.xce_job_t) C.int {
|
|
// add all jobs to apiserver
|
|
for i := range jobs {
|
|
print_job(jobs[i])
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
func (apiserver *ApiServer) handle_worker_push(workers []*C.xce_worker_t) C.int {
|
|
// add all workers to api server
|
|
for i := range workers {
|
|
print_worker(workers[i])
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func (apiserver *ApiServer)handle_dataset(dataset *C.dataset_t) C.int {
|
|
|
|
fmt.Printf("handle dataset table %d\n", dataset.table)
|
|
switch(dataset.table) {
|
|
case C.Data_data_schedjobs:
|
|
fmt.Printf("%d jobs arrived\n", dataset.nrows)
|
|
var theJobs **C.xce_job_t = C.dataset_jobs(dataset)
|
|
|
|
jobs := unsafe.Slice(theJobs, dataset.nrows)
|
|
|
|
return apiserver.handle_job_push(jobs)
|
|
case C.Data_data_schedworkers:
|
|
fmt.Printf("%d workers arrived\n", dataset.nrows)
|
|
var theWorkers **C.xce_worker_t = C.dataset_workers(dataset)
|
|
|
|
workers := unsafe.Slice(theWorkers, dataset.nrows)
|
|
return apiserver.handle_worker_push(workers)
|
|
default:
|
|
//
|
|
}
|
|
return 0
|
|
}
|
|
func go_req_handler(request *C.xce_request_t, ctx *C.apiserver_ctx_t) C.int {
|
|
var from = C.GoString(request.from.name)
|
|
var body_which = request.body_which
|
|
var apiserver = (*ApiServer)(unsafe.Pointer(ctx.go_apiserver))
|
|
|
|
fmt.Println("api server handler called")
|
|
fmt.Printf("op `%s' body_which %d from %s\n", C.GoString(C.xce_request_op_name(request)), body_which, from)
|
|
|
|
switch (request.opcode) {
|
|
case C.OPCode_push:
|
|
switch (body_which) {
|
|
case C.Request_body_configpushmsg:
|
|
// handle push config
|
|
return apiserver.handle_config((*C.xce_configdata_t)(unsafe.Pointer(C.xce_request_body(request))))
|
|
case C.Request_body_datamsg:
|
|
// handle pushed data msg
|
|
return apiserver.handle_dataset((*C.dataset_t)(unsafe.Pointer(C.xce_request_body(request))))
|
|
default:
|
|
// something wrong
|
|
}
|
|
default:
|
|
}
|
|
|
|
C.free_Request(request)
|
|
|
|
return 0
|
|
}
|
|
|
|
func init_config(config *C.xce_client_config_t) C.int {
|
|
config.nmasters =1
|
|
config.masters[0] = C.CString("localhost")
|
|
config.master_ports[0] = C.int(9990);
|
|
config.from = C.CString("xce_apiserver")
|
|
config.key = C.CString("keepsecret$")
|
|
|
|
return 0
|
|
}
|
|
|
|
func (apiserver *ApiServer) handle_job_query(w http.ResponseWriter, r *http.Request) {
|
|
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
|
|
}
|
|
|
|
func main() {
|
|
var config C.xce_client_config_t
|
|
var ctx C.apiserver_ctx_t
|
|
var apiserver ApiServer
|
|
|
|
init_config(&config)
|
|
|
|
h := cgo.NewHandle(go_req_handler)
|
|
defer h.Delete()
|
|
|
|
ctx.go_handler = C.uintptr_t(h)
|
|
ctx.go_apiserver = unsafe.Pointer(&apiserver)
|
|
|
|
rc := C.xce_apiserver_init(&config, &ctx)
|
|
fmt.Printf("rc %d\n", rc);
|
|
|
|
http.HandleFunc("/jobs", (&apiserver).handle_job_query)
|
|
|
|
log.Fatal(http.ListenAndServe("localhost:8000", nil))
|
|
}
|