/* The child part of the multiprocess demonstration. * Attempts to add 10 entries of {process_x, x} where x is pid, then remove 9 of them. * Uses file locking; the add or remove command will not happen until the lockfile is created successfully. * * argv: argument list passed into this program. */ void run_worker(const char **argv) { char lockfile[250]; strcpy(lockfile, argv[2]); strcat(lockfile, ".lock"); int fd; int pid = getpid(); for (int i = 0; i < 10; i++) { while ((fd = open(lockfile, O_CREAT | O_EXCL)) < 3) { } Person to_add; to_add.id = pid; sprintf(to_add.name, "process_%d", to_add.id); db_add(argv[2], &to_add); close(fd); unlink(lockfile); } for (int i = 0; i < 9; i++) { while ((fd = open(lockfile, O_CREAT | O_EXCL)) < 3) { } char name[30]; sprintf(name, "process_%d", pid); db_remove(argv[2], name); close(fd); unlink(lockfile); } }
long long log_add (logbase_t * base, logrec_t * data) { long long rc; if (base->fasync == 0) rc = db_exlock(base->fd); else rc = 0; if (rc >= 0) { data->crc = count_crc(data, sizeof(logrec_t)-sizeof(int)); rc = db_add(base->fd, data, sizeof(logrec_t)); if (base->fasync == 0) db_unlock(base->fd); } return rc; }
/* Interactive function to add a person. Prompts user for id and name, then invokes DB's add function. * * filepath: the path of the db file. DB will open it. */ void cmd_add(char *filepath) { Person to_add; char buffer[50]; printf("Enter the ID number\n> "); fgets(buffer, 10, stdin); to_add.id = atoi(buffer); printf("Enter their name\n> "); fgets(buffer, 49, stdin); unsigned long end = strlen(buffer) - 1; if (buffer[end] == '\n') buffer[end] = '\0'; strcpy(to_add.name, buffer); db_add(filepath, &to_add); }
int ydb_add(YDB ydb, char *key, unsigned short key_sz, char *value, unsigned int value_sz) { struct db *db = (struct db *) ydb; assert(db->magic == YDB_STRUCT_MAGIC); if(value_sz > MAX_VALUE_SIZE) return(-1); /* TODO: error handling on write? */ DB_LOCK(db); if(db_add(db, key, key_sz, value, value_sz) < 0) { value_sz = -1; goto release; } if(db->gc_finished) { gc_join(db); } release: DB_UNLOCK(db); return(value_sz); }
static int db_nessdb_insert(struct nb_db *db, struct nb_key *key) { struct db_nessdb *t = db->priv; assert (key->size < UINT_MAX); assert (t->value_size < UINT_MAX); struct slice nkey, nval; nkey.len = key->size; nkey.data = key->data; nval.len = t->value_size; nval.data = t->value; int count = db_add(t->instance->db, &nkey, &nval); if (count != 1) { printf("db_add() failed: %d\n", count); return -1; } ++t->sent; return 0; }
/* The worker method for the multithreaded demonstration. Almost identical to the multiprocess worker above. * Each thread will attempt to acquire the lock, add a person with name "thread_x" and id x where x is the threadid assigned by me, then relinquish the lock. * It will do this 10 times, then attempt to remove 9 of those entries (again, reacquiring the mutex per operation, and relinquishing when done with that one operation.) * * arg: void pointer to a single argument passed in from pthread_create(). * * Returns: NULL in all cases. Return type only included for conformance with pthread_create(). */ void* run_threaded_worker(void *arg) { // Unpack the info struct thread_info ti = *(thread_info*)arg; // Each time, acquire the lock, create a person with name and id using threadid from ti, add it, then unlock. for (int i = 0; i < 10; i++) { pthread_mutex_lock(ti.lock); //- CRITICAL SECTION -// Person to_add; to_add.id = ti.threadid; sprintf(to_add.name, "thread_%d", ti.threadid); db_add(ti.path, &to_add); //- END CRITICAL SECTION -// pthread_mutex_unlock(ti.lock); } // Each time, acquire the lock, create the name to look for from threadid in ti, remove it, then unlock. for (int i = 0; i < 9; i++) { pthread_mutex_lock(ti.lock); //- CRITICAL SECTION -// char name[30]; sprintf(name, "thread_%d", ti.threadid); db_remove(ti.path, name); //- END CRITICAL SECTION -// pthread_mutex_unlock(ti.lock); } // Cause we gotta. return NULL; }
void _process_cmd(int fd, struct request *req) { char sent_buf[BUF_SIZE]; struct response *resp; memset(sent_buf, 0, BUF_SIZE); switch(req->cmd){ case CMD_PING:{ resp = response_new(0,OK_PONG); response_detch(resp,sent_buf); write(fd,sent_buf,strlen(sent_buf)); request_free_value(req); response_free(resp); break; } case CMD_SET:{ struct slice sk, sv; if(req->argc == 3) { sk.len = req->argv[1]->len; sk.data = req->argv[1]->data; sv.len = req->argv[2]->len; sv.data = req->argv[2]->data; db_add(_svr.db, &sk, &sv); resp = response_new(0,OK); response_detch(resp,sent_buf); write(fd,sent_buf,strlen(sent_buf)); request_free_value(req); response_free(resp); break; } goto __default; } case CMD_MSET:{ int i; int c = req->argc; for (i = 1; i < c; i += 2) { struct slice sk, sv; sk.len = req->argv[i]->len; sk.data = req->argv[i]->data; sv.len = req->argv[i+1]->len; sv.data = req->argv[i+1]->data; db_add(_svr.db, &sk, &sv); } resp = response_new(0, OK); response_detch(resp, sent_buf); write(fd,sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); break; } case CMD_GET:{ int ret; struct slice sk; struct slice sv; if (req->argc == 2) { sk.len = req->argv[1]->len; sk.data = req->argv[1]->data; ret = db_get(_svr.db, &sk, &sv); if (ret == 1) { resp = response_new(1,OK_200); resp->argv[0] = sv.data; } else { resp = response_new(0,OK_404); resp->argv[0] = NULL; } response_detch(resp, sent_buf); write(fd,sent_buf,strlen(sent_buf)); request_free_value(req); response_free(resp); if (ret == 1) free(sv.data); break; } goto __default; } case CMD_MGET:{ int i; int ret; int c=req->argc; int sub_c=c-1; char **vals = calloc(c, sizeof(char*)); resp=response_new(sub_c, OK_200); for (i = 1; i < c; i++){ struct slice sk; struct slice sv; sk.len = req->argv[i]->len; sk.data = req->argv[i]->data; ret = db_get(_svr.db, &sk, &sv); if (ret == 1) vals[i-1] = sv.data; else vals[i-1] = NULL; resp->argv[i-1] = vals[i-1]; } response_detch(resp, sent_buf); write(fd, sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); for (i = 0; i < sub_c; i++){ if (vals[i]) free(vals[i]); } free(vals); break; } case CMD_INFO:{ char *infos; infos = db_info(_svr.db); resp = response_new(1, OK_200); resp->argv[0] = infos; response_detch(resp, sent_buf); write(fd,sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); break; } case CMD_DEL:{ int i; for (i = 1; i < req->argc; i++){ struct slice sk; sk.len = req->argv[i]->len; sk.data = req->argv[i]->data; db_remove(_svr.db, &sk); } resp = response_new(0, OK); response_detch(resp, sent_buf); write(fd, sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); break; } case CMD_EXISTS:{ struct slice sk; sk.len = req->argv[1]->len; sk.data = req->argv[1]->data; int ret= db_exists(_svr.db, &sk); if(ret) write(fd,":1\r\n",4); else write(fd,":-1\r\n",5); } break; case CMD_SHUTDOWN: __ERROR("siloserver shutdown..."); db_close(_svr.db); exit(2); break; __default: default:{ resp = response_new(0, ERR); response_detch(resp, sent_buf); write(fd, sent_buf, strlen(sent_buf)); request_free_value(req); response_free(resp); break; } } }
int scan_xml_tracks_section(int action, char *info) { static int state; static int current_track_id; static int current_field; static int is_streaming; static MP3FILE mp3; static char *song_path=NULL; char real_path[PATH_MAX]; MP3FILE *pmp3; int added_id; if(action == RXML_EVT_OPEN) { state = XML_TRACK_ST_INITIAL; memset((void*)&mp3,0,sizeof(MP3FILE)); song_path = NULL; return 0; } /* walk through the states */ switch(state) { case XML_TRACK_ST_INITIAL: /* expection only a <dict> */ MAYBESETSTATE_TR(RXML_EVT_BEGIN,"dict",XML_TRACK_ST_MAIN_DICT); return XML_STATE_ERROR; break; case XML_TRACK_ST_MAIN_DICT: /* either get a <key>, or a </dict> */ MAYBESETSTATE_TR(RXML_EVT_BEGIN,"key",XML_TRACK_ST_EXPECTING_TRACK_ID); if ((action == RXML_EVT_END) && (strcasecmp(info,"dict") == 0)) { return XML_STATE_PREAMBLE; } return XML_STATE_ERROR; break; case XML_TRACK_ST_EXPECTING_TRACK_ID: /* this is somewhat loose - <key>id</key> */ MAYBESETSTATE_TR(RXML_EVT_BEGIN,"key",XML_TRACK_ST_EXPECTING_TRACK_ID); MAYBESETSTATE_TR(RXML_EVT_END,"key",XML_TRACK_ST_EXPECTING_TRACK_DICT); if (action == RXML_EVT_TEXT) { current_track_id = atoi(info); DPRINTF(E_DBG,L_SCAN,"Scanning iTunes id #%d\n",current_track_id); } else { return XML_STATE_ERROR; } break; case XML_TRACK_ST_EXPECTING_TRACK_DICT: /* waiting for a dict */ MAYBESETSTATE_TR(RXML_EVT_BEGIN,"dict",XML_TRACK_ST_TRACK_INFO); return XML_STATE_ERROR; break; case XML_TRACK_ST_TRACK_INFO: /* again, kind of loose */ MAYBESETSTATE_TR(RXML_EVT_BEGIN,"key",XML_TRACK_ST_TRACK_INFO); MAYBESETSTATE_TR(RXML_EVT_END,"key",XML_TRACK_ST_TRACK_DATA); if(action == RXML_EVT_TEXT) { current_field=scan_xml_get_tagindex(info); if(current_field == SCAN_XML_T_DISABLED) { mp3.disabled = 1; } else if(current_field == SCAN_XML_T_COMPILATION) { mp3.compilation = 1; } } else if((action == RXML_EVT_END) && (strcmp(info,"dict")==0)) { state = XML_TRACK_ST_MAIN_DICT; /* but more importantly, we gotta process the track */ is_streaming = 0; if((song_path) && strncasecmp(song_path,"http://",7) == 0) is_streaming = 1; if((!is_streaming)&&scan_xml_translate_path(song_path,real_path)) { /* FIXME: Error handling */ pmp3=db_fetch_path(NULL,real_path,0); if(!pmp3) { /* file doesn't exist... let's add it? */ scan_filename(real_path,SCAN_TEST_COMPDIR,NULL,NULL); pmp3=db_fetch_path(NULL,real_path,0); } if(pmp3) { /* Update the existing record with the * updated stuff we got from the iTunes xml file */ MAYBECOPYSTRING(title); MAYBECOPYSTRING(artist); MAYBECOPYSTRING(album); MAYBECOPYSTRING(genre); MAYBECOPYSTRING(comment); MAYBECOPYSTRING(composer); MAYBECOPY(song_length); MAYBECOPY(track); MAYBECOPY(total_tracks); MAYBECOPY(year); MAYBECOPY(bitrate); MAYBECOPY(samplerate); MAYBECOPY(play_count); MAYBECOPY(rating); MAYBECOPY(disc); MAYBECOPY(total_discs); MAYBECOPY(time_added); MAYBECOPY(disabled); MAYBECOPYSTRING(album_artist); /* must add to the red-black tree */ scan_xml_add_lookup(current_track_id,pmp3->id); make_composite_tags(pmp3); db_add(NULL,pmp3,NULL); db_dispose_item(pmp3); } } else if(is_streaming) { /* add/update a http:// url */ pmp3=db_fetch_path(NULL,scan_xml_file,current_track_id); if(!pmp3) { /* gotta add it! */ DPRINTF(E_DBG,L_SCAN,"Adding %s\n",song_path); pmp3 = calloc(sizeof(MP3FILE),1); if(!pmp3) DPRINTF(E_FATAL,L_SCAN, "malloc: scan_xml_tracks_section\n"); } else { DPRINTF(E_DBG,L_SCAN,"updating %s\n",song_path); } pmp3->url = strdup(song_path); pmp3->type = strdup("pls"); pmp3->description = strdup("Playlist URL"); pmp3->data_kind = 1; pmp3->item_kind = 2; pmp3->path = strdup(scan_xml_file); pmp3->index = current_track_id; MAYBECOPYSTRING(title); MAYBECOPYSTRING(artist); MAYBECOPYSTRING(album); MAYBECOPYSTRING(genre); MAYBECOPYSTRING(comment); MAYBECOPY(bitrate); MAYBECOPY(samplerate); MAYBECOPY(play_count); MAYBECOPY(rating); MAYBECOPY(time_added); MAYBECOPY(disabled); MAYBECOPYSTRING(album_artist); make_composite_tags(pmp3); if(db_add(NULL,pmp3,&added_id) == DB_E_SUCCESS) { scan_xml_add_lookup(current_track_id,added_id); DPRINTF(E_DBG,L_SCAN,"Added %s\n",song_path); } else { DPRINTF(E_DBG,L_SCAN,"Error adding %s\n",song_path); } db_dispose_item(pmp3); } /* cleanup what's left */ MAYBEFREE(mp3.title); MAYBEFREE(mp3.artist); MAYBEFREE(mp3.album); MAYBEFREE(mp3.genre); MAYBEFREE(mp3.comment); MAYBEFREE(mp3.album_artist); MAYBEFREE(song_path); memset((void*)&mp3,0,sizeof(MP3FILE)); } else { return XML_STATE_ERROR; } break; case XML_TRACK_ST_TRACK_DATA: if(action == RXML_EVT_BEGIN) { break; } else if(action == RXML_EVT_TEXT) { if(current_field == SCAN_XML_T_NAME) { mp3.title = strdup(info); } else if(current_field == SCAN_XML_T_ARTIST) { mp3.artist = strdup(info); } else if(current_field == SCAN_XML_T_ALBUM) { mp3.album = strdup(info); } else if(current_field == SCAN_XML_T_GENRE) { mp3.genre = strdup(info); } else if(current_field == SCAN_XML_T_TOTALTIME) { mp3.song_length = atoi(info); } else if(current_field == SCAN_XML_T_TRACKNUMBER) { mp3.track = atoi(info); } else if(current_field == SCAN_XML_T_TRACKCOUNT) { mp3.total_tracks = atoi(info); } else if(current_field == SCAN_XML_T_YEAR) { mp3.year = atoi(info); } else if(current_field == SCAN_XML_T_BITRATE) { mp3.bitrate = atoi(info); } else if(current_field == SCAN_XML_T_SAMPLERATE) { mp3.samplerate = atoi(info); } else if(current_field == SCAN_XML_T_PLAYCOUNT) { mp3.play_count = atoi(info); } else if(current_field == SCAN_XML_T_RATING) { mp3.rating = atoi(info); } else if(current_field == SCAN_XML_T_DISCNO) { mp3.disc = atoi(info); } else if(current_field == SCAN_XML_T_DISCCOUNT) { mp3.total_discs = atoi(info); } else if(current_field == SCAN_XML_T_LOCATION) { song_path = scan_xml_urldecode(info,0); DPRINTF(E_DBG,L_SCAN,"scan_path: %s\n",song_path); } else if(current_field == SCAN_XML_T_DATE_ADDED) { mp3.time_added = scan_xml_datedecode(info); } else if(current_field == SCAN_XML_T_COMMENTS) { mp3.comment = strdup(info); } else if(current_field == SCAN_XML_T_COMPOSER) { mp3.composer = strdup(info); } else if(current_field == SCAN_XML_T_ALBUM_ARTIST) { mp3.album_artist = strdup(info); } } else if(action == RXML_EVT_END) { state = XML_TRACK_ST_TRACK_INFO; } else { return XML_STATE_ERROR; } break; default: return XML_STATE_ERROR; } return XML_STATE_TRACKS; }
JNIEXPORT jint JNICALL Java_org_nessdb_DB_set(JNIEnv *jenv, jobject clazz, jlong ptr, jbyteArray jkey, jint jklen, jbyteArray jval, jint jvlen) { (void)clazz; char *key, *ktmp = NULL, *val, *vtmp = NULL; struct slice sk, sv; int ret = 0; struct nessdb *_db = (struct nessdb *)ptr; if (!_db) { __ERROR("set-->db is null, pls open first"); return ret; } if (jklen >= NESSDB_MAX_KEY_SIZE) { __ERROR("key length too long...%d", jklen); return (-1); } if (jklen == 0 || jvlen == 0) return ret; memset(&sk, 0, sizeof(struct slice)); memset(&sv, 0, sizeof(struct slice)); key = (char*)(*jenv)->GetByteArrayElements(jenv, jkey, NULL); val = (char*)(*jenv)->GetByteArrayElements(jenv, jval, NULL); if (key == NULL || val == NULL) goto RET; ktmp = malloc(jklen + 1); memset(ktmp, 0, jklen + 1); memcpy(ktmp, key, jklen); vtmp = malloc(jvlen + 1); memset(vtmp, 0, jvlen + 1); memcpy(vtmp, val, jvlen); sk.data = ktmp; sk.len = jklen; sv.data = vtmp; sv.len = jvlen; ret = db_add(_db, &sk, &sv); RET: /* release */ if (key) { (*jenv)->ReleaseByteArrayElements(jenv, jkey, (jbyte*)key, JNI_COMMIT); if (ktmp) free(ktmp); } if (val){ (*jenv)->ReleaseByteArrayElements(jenv, jval, (jbyte*)val, JNI_COMMIT); if (vtmp) free(vtmp); } return ret; }