Пример #1
0
        }  // end flush

        /// <summary>
        /// Inserts a record into the queue (if all conditions are
        /// favourable).  Returns the queue if it becomes full upon insertion.
        /// </summary>
        /// <param name="record">The record to insert into the queue.</param>
        /// <param name="key">A primary key, if any.</param>
        /// <returns>The list of records (if the queue is full), or null.</returns>
        public IList <T> insert(T record, RecordKey key)
        {
            if (this.has_primary_key && key.isValid())
            {
                // We are to update the record even if the primary key already exists
                if (this.update_on_existing_pk)
                {
                    int key_idx;

                    if (this.primary_key_map.TryGetValue(key, out key_idx))
                    {
                        // Key exists, so we need to replace the associated record
                        this.queue[key_idx] = record;
                    }
                    else  // key does not exist; add the record and
                    {     // update the key->record mapping
                        this.queue.Add(record);
                        this.primary_key_map.Add(key, (this.queue.Count - 1));
                    }
                }
                else // do NOT update/add the record if the key already exists
                {
                    if (this.primary_key_map.ContainsKey(key))
                    {
                        return(null);  // yup, the key already exists
                    }
                    // The key does not exist, so add the record and
                    // update the key->record map
                    this.queue.Add(record);
                    this.primary_key_map.Add(key, (this.queue.Count - 1));
                }
            }
            else  // simply add the record
            {
                queue.Add(record);
            }

            // If the queue is full, then flush and return the 'old' queue
            if (queue.Count == capacity)
            {
                return(flush());
            }
            else // no records to return
            {
                return(null);
            }
        } // end insert
Пример #2
0
        }  // end private flush()

        /// <summary>
        /// Queues a record for insertion into Kinetica.  If the queue reaches
        /// the <member cref="batch_size" />, all records in the queue will be
        /// inserted into Kinetica before the method returns.  If an error occurs
        /// while inserting the records, the records will no longer be in the queue
        /// nor in Kinetica; catch <see cref="InsertException{T}"/>  to get the list
        /// of records that were being inserted if needed (for example, to retry).
        /// </summary>
        /// <param name="record">The record to insert.</param>
        /// <exception cref="InsertException{T}" />
        public void insert(T record)
        {
            // Create the record keys
            Utils.RecordKey primary_key = null;  // used to check for uniqueness
            Utils.RecordKey shard_key   = null;  // used to find which worker to send this record to

            // Build the primary key, if any
            if (this.primary_key_builder != null)
            {
                primary_key = this.primary_key_builder.build(record);
            }

            // Build the shard/routing key, if any
            if (this.shard_key_builder != null)
            {
                shard_key = this.shard_key_builder.build(record);
            }

            // Find out which worker to send the record to; then add the record
            // to the approrpriate worker's record queue
            Utils.WorkerQueue <T> worker_queue;
            if (this.routing_table == null)
            {   // no information regarding multiple workers, so get the first/only one
                worker_queue = this.worker_queues[0];
            }
            else if (shard_key == null)
            {   // there is no shard/routing key, so get a random worker
                worker_queue = this.worker_queues[random.Next(this.worker_queues.Count)];
            }
            else
            {   // Get the worker based on the sharding/routing key
                int worker_index = shard_key.route(this.routing_table);
                worker_queue = this.worker_queues[worker_index];
            }

            // Insert the record into the queue
            IList <T> queue = worker_queue.insert(record, primary_key);

            // If inserting the queue resulted in flushing the queue, then flush it
            // properly
            if (queue != null)
            {
                this.flush(queue, worker_queue.url);
            }
        }  // end insert( record )
Пример #3
0
        }         // end constructor RecordKeyBuilder

        /// <summary>
        /// Build a RecordKey object based on a record.
        /// </summary>
        /// <param name="record">The object based on which the key is to
        /// be built.</param>
        /// <returns>The record key that helps is routing this record
        /// correctly.</returns>
        public RecordKey build(T record)
        {
            // Can't build a key if the buffer size is zero!
            if (this.buffer_size == 0)
            {
                return(null);
            }

            // Create the empty key
            RecordKey key = new RecordKey(this.buffer_size);

            // Add each routing column's value to the key
            for (int i = 0; i < this.routing_column_indices.Count; ++i)
            {
                // Get the column (with type and name)
                KineticaType.Column column = this.ktype.getColumns()[this.routing_column_indices[i]];

                // Get the value out of the record using the column's name and reflection
                var value = record.GetType().GetProperty(column.getName()).GetValue(record, null);

                switch (this.column_types[i])
                {
                case ColumnType.CHAR1:
                    key.addCharN((string)value, 1);
                    break;

                case ColumnType.CHAR2:
                    key.addCharN((string)value, 2);
                    break;

                case ColumnType.CHAR4:
                    key.addCharN((string)value, 4);
                    break;

                case ColumnType.CHAR8:
                    key.addCharN((string)value, 8);
                    break;

                case ColumnType.CHAR16:
                    key.addCharN((string)value, 16);
                    break;

                case ColumnType.CHAR32:
                    key.addCharN((string)value, 32);
                    break;

                case ColumnType.CHAR64:
                    key.addCharN((string)value, 64);
                    break;

                case ColumnType.CHAR128:
                    key.addCharN((string)value, 128);
                    break;

                case ColumnType.CHAR256:
                    key.addCharN((string)value, 256);
                    break;

                case ColumnType.DATE:
                    key.addDate((string)value);
                    break;

                case ColumnType.DATETIME:
                    key.addDateTime((string)value);
                    break;

                case ColumnType.DECIMAL:
                    key.addDecimal((string)value);
                    break;

                case ColumnType.DOUBLE:
                    key.addDouble((double?)value);
                    break;

                case ColumnType.FLOAT:
                    key.addFloat((float?)value);
                    break;

                case ColumnType.INT:
                    key.addInt((int?)value);
                    break;

                case ColumnType.INT8:
                    key.addInt8((int?)value);
                    break;

                case ColumnType.INT16:
                    key.addInt16((int?)value);
                    break;

                case ColumnType.IPV4:
                    key.addIPv4((string)value);
                    break;

                case ColumnType.LONG:
                    key.addLong((long?)value);
                    break;

                case ColumnType.STRING:
                    key.addString((string)value);
                    break;

                case ColumnType.TIME:
                    key.addTime((string)value);
                    break;

                case ColumnType.TIMESTAMP:
                    key.addTimeStamp((long?)value);
                    break;
                } // end switch
            }     // end for loop

            // Compute the hash for the key and return it
            key.computHashes();
            return(key);
        }  // end build()
        }   // end constructor RecordRetriever

        /// <summary>
        /// Retrieves records for a given shard key, optionally further limited by an
        /// additional expression. All records matching the key and satisfying the
        /// expression will be returned, up to the system-defined limit. For
        /// multi-head mode the request will be sent directly to the appropriate
        /// worker.
        /// <br />
        /// All fields in both the shard key and the expression must have defined
        /// attribute indexes, unless the shard key is also a primary key and all
        /// referenced fields are in the primary key. The expression must be
        /// limited to basic equality and inequality comparisons that can be
        /// evaluated using the attribute indexes.
        /// </summary>
        ///
        /// <param name="record">The record based on whose shard column values
        /// records will be fetched from the table.</param>
        /// <param name="expression">An optional expression.  Default is
        /// null.</param>
        ///
        /// <returns>A GetRecordsResponse object with the decoded retrieved
        /// values.</returns>
        public GetRecordsResponse <T> getRecordsByKey(T record,
                                                      string expression = null)
        {
            if (this.shard_key_builder == null)
            {
                throw new KineticaException("Cannot get by key from unsharded table: " + this.table_name);
            }

            try
            {
                // Build the expression
                string full_expression = this.shard_key_builder.buildExpression(record);
                if (full_expression == null)
                {
                    throw new KineticaException("No expression could be made from given record.");
                }
                if (expression != null)
                {
                    full_expression = (full_expression + " and (" + expression + ")");
                }

                // Create the options map for the /get/records call
                IDictionary <string, string> options = new Dictionary <string, string>();
                options[GetRecordsRequest.Options.EXPRESSION]        = full_expression;
                options[GetRecordsRequest.Options.FAST_INDEX_LOOKUP] = GetRecordsRequest.Options.TRUE;

                // Create a /get/records request packet
                GetRecordsRequest request = new GetRecordsRequest(this.table_name,
                                                                  0, Kinetica.END_OF_SET,
                                                                  options);

                // Submit the /get/records request
                if (this.routing_table == null)
                {   // No routing information is available; talk to rank-0
                    return(kineticaDB.getRecords <T>(request));
                }
                else // Talk to the appropriate worker rank
                {
                    // Create the appropriate response objects
                    RawGetRecordsResponse  raw_response     = new RawGetRecordsResponse();
                    GetRecordsResponse <T> decoded_response = new GetRecordsResponse <T>();

                    // Find the appropriate worker rank
                    Utils.RecordKey shard_key = this.shard_key_builder.build(record);
                    System.Uri      url       = this.worker_queues[shard_key.route(this.routing_table)].url;
                    // Make the call
                    raw_response = this.kineticaDB.SubmitRequest <RawGetRecordsResponse>(url, request);

                    // Set up the values of the decoded response properly
                    decoded_response.table_name              = raw_response.table_name;
                    decoded_response.type_name               = raw_response.type_name;
                    decoded_response.type_schema             = raw_response.type_schema;
                    decoded_response.has_more_records        = raw_response.has_more_records;
                    decoded_response.total_number_of_records = raw_response.total_number_of_records;

                    // Decode the records
                    kineticaDB.DecodeRawBinaryDataUsingRecordType(ktype,
                                                                  raw_response.records_binary,
                                                                  decoded_response.data);
                    return(decoded_response);
                }
            } catch (KineticaException ex)
            {
                throw new KineticaException("Error in retrieving records by key: ", ex);
            } catch (Exception ex)
            {
                throw new KineticaException("Error in retrieving records by key: ", ex);
            }
        }  // end getRecordsByKey()