1/** 2 * \file 3 * \brief Stubs of Octopus implementation 4 * 5 * Warning: This implementation provides only the very basic functionality 6 * needed by the name service API in libbarrelfish! 7 */ 8/* 9 * Copyright (c) 2011, ETH Zurich. 10 * All rights reserved. 11 * 12 * This file is distributed under the terms in the attached LICENSE file. 13 * If you do not find this file, copies can be found by writing to: 14 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 15 */ 16 17#include <stdio.h> 18#include <string.h> 19 20#include <pcre.h> 21 22#include <barrelfish/barrelfish.h> 23#include <if/octopus_defs.h> 24 25#include <octopus_server/debug.h> 26#include <octopus_server/query.h> 27#include <octopus/parser/ast.h> 28#include <octopus/definitions.h> 29#include <octopus/getset.h> // for SET_SEQUENTIAL define 30 31#define MAX_RECORDS 1024 32#define RECORD_NAME(ast) ((ast)->u.on.name->u.in.str) 33#define RECORD_NAME_REGEX(ast) ((ast)->u.on.name->u.cnsn.value->u.sn.str) 34 35// cnsn 36 37struct wait_queue; 38struct wait_queue { 39 struct oct_reply_state* ors; 40 struct wait_queue* next; 41}; 42 43struct record { 44 char* name; 45 struct ast_object* record; 46 struct wait_queue* waiting_parties; 47}; 48 49static struct record record_storage[MAX_RECORDS] = { { NULL, NULL, NULL } }; 50 51static void transform_to_string(struct ast_object* ast, char* str) 52{ 53 assert(ast != NULL); 54 assert(str != NULL); 55 size_t idx = 0; 56 57 idx += sprintf(str + idx, "%s { ", RECORD_NAME(ast)); 58 59 struct ast_object* attr = ast->u.on.attrs; 60 while (attr != NULL) { 61 assert(attr->type == nodeType_Attribute); 62 63 struct ast_object* pair = attr->u.an.attr; 64 assert(pair != NULL); 65 assert(pair->type == nodeType_Pair); 66 67 struct ast_object* left = pair->u.pn.left; 68 struct ast_object* right = pair->u.pn.right; 69 ;assert(left != NULL); 70 assert(right != NULL); 71 72 assert(left->type == nodeType_Ident); 73 idx += sprintf(str + idx, "%s: ", left->u.in.str); 74 75 switch(right->type) { 76 case nodeType_String: 77 idx += sprintf(str + idx, "%s", right->u.sn.str); 78 break; 79 case nodeType_Constant: 80 idx += sprintf(str + idx, "%"PRId64"", right->u.cn.value); 81 break; 82 case nodeType_Ident: 83 idx += sprintf(str + idx, "%s ", right->u.in.str); 84 break; 85 default: 86 USER_PANIC("Unsupported node type: %u\n", right->type); 87 } 88 89 attr = attr->u.an.next; 90 if (attr != NULL) { 91 idx += sprintf(str + idx, ", "); 92 } 93 } 94 95 idx += sprintf(str + idx, " }"); 96 str[idx + 1] = '\0'; 97 98 OCT_DEBUG("transform to string: %s\n", str); 99} 100 101static void copy_ast(struct ast_object** copy, struct ast_object* ast) 102{ 103 if (ast == NULL) { 104 return; 105 } 106 107 *copy = malloc(sizeof(struct ast_object)); 108 memcpy(*copy, ast, sizeof(struct ast_object)); 109 110 switch (ast->type) { 111 case nodeType_Object: 112 copy_ast(&(*copy)->u.on.name, ast->u.on.name); 113 copy_ast(&(*copy)->u.on.attrs, ast->u.on.attrs); 114 break; 115 116 case nodeType_Attribute: 117 copy_ast(&(*copy)->u.an.attr, ast->u.an.attr); 118 copy_ast(&(*copy)->u.an.next, ast->u.an.next); 119 break; 120 121 case nodeType_Pair: 122 copy_ast(&(*copy)->u.pn.left, ast->u.pn.left); 123 copy_ast(&(*copy)->u.pn.right, ast->u.pn.right); 124 break; 125 126 case nodeType_Ident: 127 (*copy)->u.in.str = strdup(ast->u.in.str); 128 break; 129 130 case nodeType_String: 131 (*copy)->u.sn.str = strdup(ast->u.sn.str); 132 break; 133 134 case nodeType_Constant: 135 // Nothing to copy 136 break; 137 138 default: 139 OCT_DEBUG("node is: %d\n", ast->type); 140 assert(!"Unsupported Node!"); 141 break; 142 } 143} 144 145errval_t get_record(struct ast_object* ast, struct oct_query_state* sqs) 146{ 147 OCT_DEBUG("get record %s\n", RECORD_NAME(ast)); 148 assert(ast != NULL); 149 assert(sqs != NULL); 150 151 for (size_t i = 0; i < MAX_RECORDS; i++) { 152 struct record* entry = &record_storage[i]; 153 if (entry->name == NULL) { 154 continue; 155 } 156 157 if (strcmp(RECORD_NAME(ast), entry->name) == 0 && entry->record != NULL) { 158 transform_to_string(entry->record, sqs->std_out.buffer); 159 return SYS_ERR_OK; 160 } 161 } 162 163 return OCT_ERR_NO_RECORD; 164} 165 166static void wakeup_clients(struct record* entry) 167{ 168 struct wait_queue* cur = entry->waiting_parties; 169 170 // Walk through list, wake up all clients 171 while (cur != NULL) { 172 assert(cur->ors != NULL); 173 assert(cur->ors->reply != NULL); 174 assert(cur->ors->binding != NULL); 175 transform_to_string(entry->record, 176 cur->ors->query_state.std_out.buffer); 177 OCT_DEBUG( 178 "wakeup %p for %s\n", cur->ors->binding, cur->ors->query_state.std_out.buffer); 179 cur->ors->reply(cur->ors->binding, cur->ors); 180 181 struct wait_queue* next = cur->next; 182 free(cur); 183 cur = next; 184 } 185 186 entry->waiting_parties = NULL; 187} 188 189errval_t set_record(struct ast_object* ast, uint64_t mode, 190 struct oct_query_state* sqs) 191{ 192 assert(ast != NULL); 193 assert(sqs != NULL); 194 assert(mode == 0); 195 196 for (size_t i = 0; i < MAX_RECORDS; i++) { 197 struct record* entry = &record_storage[i]; 198 if (entry->name == NULL) { 199 continue; 200 } 201 202 OCT_DEBUG("found record: %s\n", entry->name); 203 if (strcmp(RECORD_NAME(ast), entry->name) == 0) { 204 assert(entry->record == NULL); 205 copy_ast(&entry->record, ast); 206 207 wakeup_clients(entry); 208 return SYS_ERR_OK; 209 } 210 } 211 212 for (size_t i = 0; i < MAX_RECORDS; i++) { 213 struct record* entry = &record_storage[i]; 214 if (entry->name == NULL) { 215 entry->name = strdup(RECORD_NAME(ast)); 216 copy_ast(&entry->record, ast); 217 218 assert(entry->waiting_parties == NULL); 219 return SYS_ERR_OK; 220 } 221 } 222 223 assert(!"No more storage space!"); 224 return OCT_ERR_NO_RECORD; 225} 226 227errval_t del_record(struct ast_object* ast, struct oct_query_state* sqs) 228{ 229 assert(ast != NULL); 230 assert(sqs != NULL); 231 232 for (size_t i = 0; i < MAX_RECORDS; i++) { 233 struct record* entry = &record_storage[i]; 234 if (entry->name == NULL) { 235 continue; 236 } 237 238 if (strcmp(RECORD_NAME(ast), entry->name) == 0) { 239 assert(entry->record != NULL); 240 241 free(entry->name); 242 entry->name = NULL; 243 free_ast(entry->record); 244 entry->record = NULL; 245 246 // Free the waiting list, this should be NULL anyways I guess 247 struct wait_queue* cur = entry->waiting_parties; 248 while (cur != NULL) { 249 struct wait_queue* next = cur->next; 250 free(cur); 251 cur = next; 252 } 253 entry->waiting_parties = NULL; 254 255 return SYS_ERR_OK; 256 } 257 } 258 259 return OCT_ERR_NO_RECORD; 260} 261 262/** 263 * TODO: this can only regex match on record name at the moment. 264 */ 265errval_t get_record_names(struct ast_object* ast, struct oct_query_state* sqs) 266{ 267 const char* errptr = NULL; 268 int erroffset = 0; 269 unsigned char tableptr; 270 271 char** names = calloc(sizeof(char*), MAX_RECORDS); 272 size_t names_cur = 0; 273 274 OCT_DEBUG("%s:%s:%d: About to pcre_compile: %s\n", 275 __FILE__, __FUNCTION__, __LINE__, RECORD_NAME_REGEX(ast)); 276 pcre* reg = pcre_compile(RECORD_NAME_REGEX(ast), 0, &errptr, &erroffset, &tableptr); 277 if (reg == NULL) { 278 OCT_DEBUG("Failed to compile the regex errptr = %s erroroffset = %d", 279 errptr, erroffset); 280 return OCT_ERR_PARSER_FAIL; 281 } 282 283 for (size_t i = 0; i < MAX_RECORDS; i++) { 284 struct record* entry = &record_storage[i]; 285 if (entry->name == NULL) { 286 continue; 287 } 288 289 int results[1]; 290 int rc = pcre_exec(reg, NULL, entry->name, strlen(entry->name), 291 0, 0, results, 1); 292 if (rc == 0) { 293 OCT_DEBUG("%s:%s:%d: We have a match\n", 294 __FILE__, __FUNCTION__, __LINE__); 295 names[names_cur++] = entry->name; 296 } 297 else if (rc < 0) { 298 OCT_DEBUG("%s:%s:%d: pcre_exec failed matching %s with rc = %d.\n", 299 __FILE__, __FUNCTION__, __LINE__, entry->name, rc); 300 } 301 } 302 if (names_cur == 0) { 303 return OCT_ERR_NO_RECORD; 304 } 305 306 // Form a comma separated string to send back over flounder 307 names_cur = 0; 308 int max_bytes = MAX_QUERY_LENGTH; 309 sqs->std_out.buffer[0] = '\0'; 310 311 while(names[names_cur] != NULL) { 312 strncat(sqs->std_out.buffer, names[names_cur], max_bytes); 313 max_bytes -= strlen(names[names_cur]); 314 names_cur++; 315 if (names[names_cur] != NULL) { 316 strncat(sqs->std_out.buffer, ",", max_bytes--); 317 } 318 assert(max_bytes > 0); 319 } 320 321 free(names); 322 return SYS_ERR_OK; 323} 324 325errval_t set_watch(struct octopus_binding* b, struct ast_object* ast, 326 uint64_t mode, struct oct_reply_state* drs, uint64_t* wid) 327{ 328 OCT_DEBUG("set_watch %s\n", RECORD_NAME(ast)); 329 330 assert(ast != NULL); 331 assert(mode == OCT_ON_SET); 332 333 struct record* entry = NULL; 334 for (size_t i = 0; i < MAX_RECORDS; i++) { 335 entry = &record_storage[i]; 336 if (entry->name == NULL) { 337 continue; 338 } 339 340 if (strcmp(RECORD_NAME(ast), entry->name) == 0) { 341 goto insert; 342 } 343 } 344 for (size_t i = 0; i < MAX_RECORDS; i++) { 345 entry = &record_storage[i]; 346 if (entry->name == NULL) { 347 entry->name = strdup(RECORD_NAME(ast)); 348 entry->record = NULL; 349 entry->waiting_parties = NULL; 350 goto insert; 351 } 352 }assert(!"Out of record space."); 353 354 insert: if (strcmp(RECORD_NAME(ast), entry->name) == 0) { 355 assert(entry->record == NULL); 356 struct wait_queue* wq = malloc(sizeof(struct wait_queue)); 357 wq->next = NULL; 358 wq->ors = drs; 359 360 // Insert wq into waiting_parties of entry 361 struct wait_queue** cur = &entry->waiting_parties; 362 for (; *cur != NULL; cur = &(*cur)->next) { 363 // Walk to the end of the list 364 } 365 *cur = wq; 366 } 367 368 *wid = 1; 369 return SYS_ERR_OK; 370} 371 372errval_t del_watch(struct octopus_binding* b, octopus_trigger_id_t id, 373 struct oct_query_state* dqs) 374{ 375 assert(!"NYI"); 376 return OCT_ERR_INVALID_ID; 377} 378 379struct octopus_binding* get_event_binding(struct octopus_binding* b) 380{ 381 assert(!"NYI"); 382 return b; 383} 384 385errval_t add_subscription(struct octopus_binding* b, struct ast_object* ast, 386 uint64_t trigger_fn, uint64_t state, struct oct_reply_state* drs) 387{ 388 assert(!"NYI"); 389 return OCT_ERR_NO_SUBSCRIPTION; 390} 391 392errval_t del_subscription(struct octopus_binding* b, uint64_t id, 393 struct oct_query_state* sqs) 394{ 395 assert(!"NYI"); 396 return OCT_ERR_NO_SUBSCRIPTION; 397} 398 399errval_t find_subscribers(struct ast_object* ast, struct oct_query_state* sqs) 400{ 401 assert(!"NYI"); 402 return OCT_ERR_NO_SUBSCRIBERS; 403} 404 405errval_t set_binding(octopus_binding_type_t type, uint64_t id, void* binding) 406{ 407 return SYS_ERR_OK; 408} 409