예제 #1
0
int next_obj(void *_cursor) {
  size_t sz;
  void *ptr = NULL;
  
  sky_cursor *cursor = (sky_cursor*)_cursor;
  if(cursor->context == NULL) {
      ptr = DATA3; sz = DATA3_LENGTH;
  } else if(cursor->context == DATA3) {
      ptr = DATA4; sz = DATA4_LENGTH;
  }
  
  if(ptr != NULL) {
      cursor->context = ptr;
      sky_cursor_set_ptr(cursor, ptr, sz);
      return 1;
  }
  else {
      return 0;
  }
}
예제 #2
0
int test_sky_cursor_set_data() {
    // Setup data object & cursor.
    sky_cursor *cursor = sky_cursor_new(-4, 4);
    sky_cursor_set_timestamp_offset(cursor, offsetof(test_t, timestamp));
    sky_cursor_set_ts_offset(cursor, offsetof(test_t, ts));
    sky_cursor_set_property(cursor, -5, offsetof(test_t, action_boolean), sizeof(bool), "boolean");
    sky_cursor_set_property(cursor, -4, offsetof(test_t, action_double), sizeof(double), "float");
    sky_cursor_set_property(cursor, -3, offsetof(test_t, action_int), sizeof(int32_t), "integer");
    sky_cursor_set_property(cursor, -2, offsetof(test_t, action_string), sizeof(sky_string), "string");
    sky_cursor_set_property(cursor, -1, offsetof(test_t, action), sizeof(sky_string), "string");
    sky_cursor_set_property(cursor, 1, offsetof(test_t, object_string), sizeof(sky_string), "string");
    sky_cursor_set_property(cursor, 2, offsetof(test_t, object_int), sizeof(int32_t), "integer");
    sky_cursor_set_property(cursor, 3, offsetof(test_t, object_double), sizeof(double), "float");
    sky_cursor_set_property(cursor, 4, offsetof(test_t, object_boolean), sizeof(bool), "boolean");
    sky_cursor_set_data_sz(cursor, sizeof(test_t));

    sky_cursor_set_ptr(cursor, DATA0, DATA0_LENGTH);
    ASSERT_OBJ_STATE(cursor->data, 0LL, 0, "", "", 0LL, 0, false, "", 0LL, 0, false);

    // Event 1 (State-Only)
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    ASSERT_OBJ_STATE(cursor->data, 0LL, 0, "", "john doe", 1000LL, 100.2, true, "", 0LL, 0, false);
    
    // Event 2 (Action + Action Data)
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    ASSERT_OBJ_STATE(cursor->data, sky_timestamp_shift(1000000LL), 1, "A1", "john doe", 1000LL, 100.2, true, "super", 21LL, 100, true);
    
    // Event 3 (Action-Only)
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    ASSERT_OBJ_STATE(cursor->data, sky_timestamp_shift(2000000LL), 2, "A2", "john doe", 1000LL, 100.2, true, "", 0LL, 0, false);

    // Event 4 (Data-Only)
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    ASSERT_OBJ_STATE(cursor->data, sky_timestamp_shift(3000000LL), 3, "", "frank sinatra", 20LL, -100, false, "", 0LL, 0, false);

    // EOF
    mu_assert_bool(!sky_lua_cursor_next_event(cursor));

    sky_cursor_free(cursor);
    return 0;
}
예제 #3
0
파일: tablet.c 프로젝트: gitaccount2/sky
// Adds an event to the tablet.
//
// tablet - The tablet.
// event  - The event to add.
//
// Returns 0 if successful, otherwise returns -1.
int sky_tablet_add_event(sky_tablet *tablet, sky_event *event)
{
    int rc;
    char *errptr = NULL;
    void *new_data = NULL;
    void *data = NULL;
    sky_data_object *data_object = NULL;
    sky_data_descriptor *descriptor = NULL;
    sky_cursor cursor; memset(&cursor, 0, sizeof(cursor));
    assert(tablet != NULL);
    assert(event != NULL);

    // Make sure that this event is being added to the correct tablet.
    sky_tablet *target_tablet = NULL;
    rc = sky_table_get_target_tablet(tablet->table, event->object_id, &target_tablet);
    check(rc == 0, "Unable to determine target tablet");
    check(tablet == target_tablet, "Event added to invalid tablet; IDX:%d of %d, OID:%d", tablet->index, tablet->table->tablet_count, event->object_id);

    // Retrieve the existing value.
    size_t data_length;
    data = (void*)leveldb_get(tablet->leveldb_db, tablet->readoptions, (const char*)&event->object_id, sizeof(event->object_id), &data_length, &errptr);
    check(errptr == NULL, "LevelDB get error: %s", errptr);
    
    // Find the insertion point on the path.
    size_t insert_offset = 0;
    size_t event_length;
    
    // If the object doesn't exist yet then just set the single event. Easy peasy.
    if(data == NULL) {
        event_length = sky_event_sizeof(event);
        new_data = calloc(1, event_length); check_mem(new_data);
        insert_offset = 0;
    }
    // If the object does exist, we need to find where to insert the event data.
    // Also, we need to strip off any state which is redundant at the point of
    // insertion.
    else {
        void *insert_ptr = NULL;

        // Initialize data descriptor.
        descriptor = sky_data_descriptor_create(); check_mem(descriptor);
        rc = sky_data_descriptor_init_with_event(descriptor, event);
        check(rc == 0, "Unable to initialize data descriptor for event insert");
    
        // Initialize data object.
        data_object = calloc(1, descriptor->data_sz); check_mem(data);

        // Attach data & descriptor to the cursor.
        cursor.data_descriptor = descriptor;
        cursor.data = (void*)data_object;

        // Initialize the cursor.
        rc = sky_cursor_set_ptr(&cursor, data, data_length);
        check(rc == 0, "Unable to set pointer on cursor");
        
        // Loop over cursor until we reach the event insertion point.
        while(!cursor.eof) {
            // Retrieve event insertion pointer once the timestamp is reached.
            if(data_object->ts >= event->timestamp) {
                insert_ptr = cursor.ptr;
                break;
            }
            
            // Move to next event.
            check(sky_cursor_next_event(&cursor) == 0, "Unable to move to next event");
        }

        // If no insertion point was found then append the event to the
        // end of the path.
        if(insert_ptr == NULL) {
            insert_ptr = data + data_length;
        }
        insert_offset = insert_ptr - data;

        // Clear off any object data on the event that matches
        // what is the current state of the event in the database.
        uint32_t i;
        for(i=0; i<event->data_count; i++) {
            // Ignore any action properties.
            if(event->data[i]->key > 0) {
                sky_data_property_descriptor *property_descriptor = &descriptor->property_zero_descriptor[event->data[i]->key];

                // If the values match then splice this from the array.
                // Compare strings.
                void *a = &event->data[i]->value;
                void *b = ((void*)data_object)+property_descriptor->offset;
                size_t n = sky_data_type_sizeof(event->data[i]->data_type);
                
                bool is_equal = false;
                if(event->data[i]->data_type == SKY_DATA_TYPE_STRING) {
                    is_equal = sky_string_bequals((sky_string*)b, event->data[i]->string_value);
                }
                // Compare other types.
                else if(memcmp(a, b, n) == 0) {
                    is_equal = true;
                }

                // If the data is equal then remove it.
                if(is_equal) {
                    sky_event_data_free(event->data[i]);
                    if(i < event->data_count - 1) {
                        memmove(&event->data[i], &event->data[i+1], (event->data_count-i-1) * sizeof(*event->data));
                    }
                    i--;
                    event->data_count--;
                }
            }
        }

        // Determine the serialized size of the event. If the event is
        // completely redundant (e.g. it is a data-only event and the event
        // matches the current object state) then don't allocate space for a
        // new path value.
        event_length = sky_event_sizeof(event);
        if(event_length > 0) {
            // Allocate space for the existing data plus the new data.
            new_data = calloc(1, data_length + event_length); check_mem(new_data);

            // Copy in data before event.
            if(insert_offset > 0) {
                memmove(new_data, data, insert_ptr-data);
            }

            // Copy in data after event.
            if(insert_offset < data_length) {
                event_length = sky_event_sizeof(event);
                memmove(new_data+insert_offset+event_length, data+insert_offset, data_length-insert_offset);
            }
        }
    }
    
    // If no space was allocated then it means the event is redundant and
    // should be ignored.
    if(new_data != NULL) {
        // If the object doesn't exist then just set the event as the data.
        size_t event_sz;
        rc = sky_event_pack(event, new_data + insert_offset, &event_sz);
        check(rc == 0, "Unable to pack event");
        check(event_sz == event_length, "Expected event size (%ld) does not match actual event size (%ld)", event_length, event_sz);

        leveldb_put(tablet->leveldb_db, tablet->writeoptions, (const char*)&event->object_id, sizeof(event->object_id), new_data, data_length + event_length, &errptr);
        check(errptr == NULL, "LevelDB put error: %s", errptr);
    }
    
    free(data_object);
    sky_data_descriptor_free(descriptor);
    free(data);
    free(new_data);
    
    return 0;

error:
    if(errptr) leveldb_free(errptr);
    sky_data_descriptor_free(descriptor);
    if(data) free(data);
    if(new_data) free(new_data);
    if(data_object) free(data_object);
    return -1;
}
예제 #4
0
int test_sky_cursor_sessionize() {
    // Setup data object.
    sky_cursor *cursor = sky_cursor_new(-2, 1);
    sky_cursor_set_timestamp_offset(cursor, offsetof(test_t, timestamp));
    sky_cursor_set_ts_offset(cursor, offsetof(test_t, ts));
    sky_cursor_set_property(cursor, -2, offsetof(test_t, action_int), sizeof(int32_t), "integer");
    sky_cursor_set_property(cursor, -1, offsetof(test_t, action), sizeof(sky_string), "string");
    sky_cursor_set_property(cursor, 1, offsetof(test_t, object_int), sizeof(int32_t), "integer");
    sky_cursor_set_data_sz(cursor, sizeof(test_t));

    // Initialize data and set a 10 second idle time.
    sky_cursor_set_ptr(cursor, DATA1, DATA1_LENGTH);
    sky_cursor_set_session_idle(cursor, 10);
    mu_assert_int_equals(cursor->session_event_index, -1);
    ASSERT_OBJ_STATE2(cursor->data, 0, "", 0LL, 0LL);
    
    // Pre-session
    mu_assert_bool(sky_lua_cursor_next_event(cursor) == false);
    mu_assert_int_equals(cursor->session_event_index, -1);
    ASSERT_OBJ_STATE2(cursor->data, 0, "", 0LL, 0LL);

    // Session 1
    mu_assert_bool(sky_lua_cursor_next_session(cursor));
    mu_assert_int_equals(cursor->session_event_index, -1);
    ASSERT_OBJ_STATE2(cursor->data, 0, "", 0LL, 0LL);

    // Session 1, Event 1
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    mu_assert_int_equals(cursor->session_event_index, 0);
    ASSERT_OBJ_STATE2(cursor->data, 0, "A1", 1000LL, 0LL);
    
    // Session 1, Event 2
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    mu_assert_int_equals(cursor->session_event_index, 1);
    ASSERT_OBJ_STATE2(cursor->data, 1, "A2", 1000LL, 100LL);
    
    // Session 1, Event 3
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    mu_assert_int_equals(cursor->session_event_index, 2);
    ASSERT_OBJ_STATE2(cursor->data, 10, "A3", 1000LL, 200LL);
    
    // Prevent next session!
    mu_assert_bool(sky_lua_cursor_next_event(cursor) == false);
    mu_assert_int_equals(cursor->session_event_index, 2);
    ASSERT_OBJ_STATE2(cursor->data, 10, "A3", 1000LL, 200LL);
    

    // Session 2 (Single Event)
    mu_assert_bool(sky_lua_cursor_next_session(cursor));
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    mu_assert_int_equals(cursor->session_event_index, 0);
    ASSERT_OBJ_STATE2(cursor->data, 20, "A1", 1000LL, 300LL);
    mu_assert_bool(sky_lua_cursor_next_event(cursor) == false);


    // Session 3 (with same data)
    mu_assert_bool(sky_lua_cursor_next_session(cursor));
    mu_assert_int_equals(cursor->session_event_index, -1);
    ASSERT_OBJ_STATE2(cursor->data, 20, "A1", 1000LL, 300LL);

    // Session 3, Event 1
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    mu_assert_int_equals(cursor->session_event_index, 0);
    ASSERT_OBJ_STATE2(cursor->data, 60, "A1", 2000LL, 0LL);

    // Session 3, Event 2
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    mu_assert_int_equals(cursor->session_event_index, 1);
    ASSERT_OBJ_STATE2(cursor->data, 63, "A2", 2000LL, 400LL);

    // Prevent next session!
    mu_assert_bool(sky_lua_cursor_next_event(cursor) == false);
    mu_assert_bool(sky_lua_cursor_next_session(cursor) == false);

    // EOF!
    mu_assert_bool(cursor->eof == true);
    mu_assert_bool(cursor->in_session == false);

    // Reuse cursor.
    sky_cursor_set_ptr(cursor, DATA1, DATA1_LENGTH);
    mu_assert_int_equals(cursor->session_event_index, -1);
    mu_assert_bool(sky_lua_cursor_next_event(cursor));
    mu_assert_int_equals(cursor->session_event_index, 0);
    ASSERT_OBJ_STATE2(cursor->data, 0, "A1", 1000LL, 0LL);
    
    sky_cursor_free(cursor);
    return 0;
}