Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Upgrade to phpcassa 1.0.a.2 for better 1.0 support!

  • Loading branch information...
commit 0a11408e2b481ab85b5554d632b2b389a70daedd 1 parent cd4a243
@sebgiroux authored
Showing with 10,735 additions and 11,877 deletions.
  1. +95 −77 columnfamily_action.php
  2. +1 −1  helper/ClusterHelper.php
  3. +27 −0 include/autoload.php
  4. +0 −3  include/conf.inc.php
  5. +7 −5 include/kernel.inc.php
  6. +0 −34 include/phpcassa/.gitignore
  7. +0 −18 include/phpcassa/AUTHORS
  8. +62 −0 include/phpcassa/Batch/CfMutator.php
  9. +148 −0 include/phpcassa/Batch/Mutator.php
  10. +0 −147 include/phpcassa/CHANGES
  11. +1,099 −0 include/phpcassa/ColumnFamily.php
  12. +40 −0 include/phpcassa/ColumnSlice.php
  13. +26 −155 include/phpcassa/{connection.php → Connection/ConnectionPool.php}
  14. +76 −0 include/phpcassa/Connection/ConnectionWrapper.php
  15. +10 −0 include/phpcassa/Connection/MaxRetriesException.php
  16. +11 −0 include/phpcassa/Connection/NoServerAvailable.php
  17. +0 −16 include/phpcassa/INSTALLING
  18. +26 −0 include/phpcassa/Index/IndexClause.php
  19. +32 −0 include/phpcassa/Index/IndexExpression.php
  20. +192 −0 include/phpcassa/Iterator/ColumnFamilyIterator.php
  21. +66 −0 include/phpcassa/Iterator/IndexedColumnFamilyIterator.php
  22. +66 −0 include/phpcassa/Iterator/RangeColumnFamilyIterator.php
  23. +0 −19 include/phpcassa/LICENSE
  24. +0 −77 include/phpcassa/README.mkd
  25. +88 −0 include/phpcassa/Schema/DataType.php
  26. +9 −0 include/phpcassa/Schema/DataType/AsciiType.php
  27. +21 −0 include/phpcassa/Schema/DataType/BooleanType.php
  28. +11 −0 include/phpcassa/Schema/DataType/BytesType.php
  29. +19 −0 include/phpcassa/Schema/DataType/CassandraType.php
  30. +92 −0 include/phpcassa/Schema/DataType/CompositeType.php
  31. +27 −0 include/phpcassa/Schema/DataType/DoubleType.php
  32. +27 −0 include/phpcassa/Schema/DataType/FloatType.php
  33. +48 −0 include/phpcassa/Schema/DataType/IntegerType.php
  34. +12 −0 include/phpcassa/Schema/DataType/LexicalUUIDType.php
  35. +107 −0 include/phpcassa/Schema/DataType/LongType.php
  36. +4 −0 include/phpcassa/Schema/DataType/Serialized.php
  37. +11 −0 include/phpcassa/Schema/DataType/TimeUUIDType.php
  38. +9 −0 include/phpcassa/Schema/DataType/UTF8Type.php
  39. +28 −0 include/phpcassa/Schema/DataType/UUIDType.php
  40. +20 −0 include/phpcassa/Schema/StrategyClass.php
  41. +491 −0 include/phpcassa/SuperColumnFamily.php
  42. +49 −178 include/phpcassa/{sysmanager.php → SystemManager.php}
  43. +87 −49 include/phpcassa/{uuid.php → UUID.php}
  44. +8 −0 include/phpcassa/UUID/UUIDException.php
  45. +23 −0 include/phpcassa/Util/Clock.php
  46. +0 −1,396 include/phpcassa/columnfamily.php
  47. +0 −11 include/phpcassa/debian/changelog
  48. +0 −1  include/phpcassa/debian/compat
  49. +0 −27 include/phpcassa/debian/control
  50. +0 −23 include/phpcassa/debian/copyright
  51. +0 −1  include/phpcassa/debian/docs
  52. +0 −5 include/phpcassa/debian/libphpcassa-php5.install
  53. +0 −1  include/phpcassa/debian/phpcassa-doc.install
  54. +0 −56 include/phpcassa/debian/rules
  55. +0 −1  include/phpcassa/debian/source/format
  56. +0 −89 include/phpcassa/doc/Makefile
  57. +0 −1  include/phpcassa/doc/__init__.py
  58. +0 −1  include/phpcassa/doc/changelog.rst
  59. +0 −154 include/phpcassa/doc/conf.py
  60. +0 −77 include/phpcassa/doc/index.rst
  61. +0 −28 include/phpcassa/doc/installation.rst
  62. +0 −377 include/phpcassa/doc/sphinxtogithub.py
  63. +0 −8 include/phpcassa/doc/troubleshooting.rst
  64. +0 −403 include/phpcassa/doc/tutorial.rst
  65. +0 −13 include/phpcassa/test/all_tests.php
  66. +0 −626 include/phpcassa/test/cassandra.yaml
  67. +0 −746 include/phpcassa/test/test_autopacking.php
  68. +0 −807 include/phpcassa/test/test_columnfamily.php
  69. +0 −65 include/phpcassa/test/test_large_ops.php
  70. +0 −153 include/phpcassa/test/test_pooling.php
  71. +0 −105 include/phpcassa/test/test_sysmanager.php
  72. +0 −51 include/phpcassa/thrift/autoload.php
  73. +0 −4,419 include/phpcassa/thrift/packages/cassandra/Cassandra.php
  74. +0 −13 include/phpcassa/thrift/packages/cassandra/cassandra_constants.php
  75. +0 −1,432 include/phpcassa/thrift/packages/cassandra/cassandra_types.php
  76. 0  include/{phpcassa → }/thrift/Thrift.php
  77. 0  include/{phpcassa → }/thrift/ext/thrift_protocol/config.m4
  78. 0  include/{phpcassa → }/thrift/ext/thrift_protocol/config.w32
  79. +1 −1  include/{phpcassa → }/thrift/ext/thrift_protocol/php_thrift_protocol.cpp
  80. 0  include/{phpcassa → }/thrift/ext/thrift_protocol/php_thrift_protocol.h
  81. +54 −0 include/thrift/packages/cassandra/Cassandra.php
  82. +37 −0 include/thrift/packages/cassandra/cassandra.AuthenticationException.php
  83. +47 −0 include/thrift/packages/cassandra/cassandra.AuthenticationRequest.php
  84. +37 −0 include/thrift/packages/cassandra/cassandra.AuthorizationException.php
  85. +2,037 −0 include/thrift/packages/cassandra/cassandra.Cassandra.client.php
  86. +56 −0 include/thrift/packages/cassandra/cassandra.Cassandra_add_args.php
  87. +52 −0 include/thrift/packages/cassandra/cassandra.Cassandra_add_result.php
  88. +65 −0 include/thrift/packages/cassandra/cassandra.Cassandra_batch_mutate_args.php
  89. +52 −0 include/thrift/packages/cassandra/cassandra.Cassandra_batch_mutate_result.php
  90. +31 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_cluster_name_args.php
  91. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_cluster_name_result.php
  92. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_keyspace_args.php
  93. +52 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_keyspace_result.php
  94. +31 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_keyspaces_args.php
  95. +50 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_keyspaces_result.php
  96. +31 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_partitioner_args.php
  97. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_partitioner_result.php
  98. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_ring_args.php
  99. +50 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_ring_result.php
  100. +31 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_schema_versions_args.php
  101. +57 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_schema_versions_result.php
  102. +31 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_snitch_args.php
  103. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_snitch_result.php
  104. +54 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_splits_args.php
  105. +49 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_splits_result.php
  106. +31 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_version_args.php
  107. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_describe_version_result.php
  108. +44 −0 include/thrift/packages/cassandra/cassandra.Cassandra_execute_cql_query_args.php
  109. +64 −0 include/thrift/packages/cassandra/cassandra.Cassandra_execute_cql_query_result.php
  110. +48 −0 include/thrift/packages/cassandra/cassandra.Cassandra_execute_prepared_cql_query_args.php
  111. +64 −0 include/thrift/packages/cassandra/cassandra.Cassandra_execute_prepared_cql_query_result.php
  112. +50 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_args.php
  113. +56 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_count_args.php
  114. +57 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_count_result.php
  115. +57 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_indexed_slices_args.php
  116. +62 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_indexed_slices_result.php
  117. +55 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_paged_slice_args.php
  118. +62 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_paged_slice_result.php
  119. +57 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_range_slices_args.php
  120. +62 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_range_slices_result.php
  121. +64 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_result.php
  122. +56 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_slice_args.php
  123. +62 −0 include/thrift/packages/cassandra/cassandra.Cassandra_get_slice_result.php
  124. +56 −0 include/thrift/packages/cassandra/cassandra.Cassandra_insert_args.php
  125. +52 −0 include/thrift/packages/cassandra/cassandra.Cassandra_insert_result.php
  126. +40 −0 include/thrift/packages/cassandra/cassandra.Cassandra_login_args.php
  127. +46 −0 include/thrift/packages/cassandra/cassandra.Cassandra_login_result.php
  128. +60 −0 include/thrift/packages/cassandra/cassandra.Cassandra_multiget_count_args.php
  129. +65 −0 include/thrift/packages/cassandra/cassandra.Cassandra_multiget_count_result.php
  130. +60 −0 include/thrift/packages/cassandra/cassandra.Cassandra_multiget_slice_args.php
  131. +70 −0 include/thrift/packages/cassandra/cassandra.Cassandra_multiget_slice_result.php
  132. +44 −0 include/thrift/packages/cassandra/cassandra.Cassandra_prepare_cql_query_args.php
  133. +46 −0 include/thrift/packages/cassandra/cassandra.Cassandra_prepare_cql_query_result.php
  134. +55 −0 include/thrift/packages/cassandra/cassandra.Cassandra_remove_args.php
  135. +50 −0 include/thrift/packages/cassandra/cassandra.Cassandra_remove_counter_args.php
  136. +52 −0 include/thrift/packages/cassandra/cassandra.Cassandra_remove_counter_result.php
  137. +52 −0 include/thrift/packages/cassandra/cassandra.Cassandra_remove_result.php
  138. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_set_cql_version_args.php
  139. +40 −0 include/thrift/packages/cassandra/cassandra.Cassandra_set_cql_version_result.php
  140. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_set_keyspace_args.php
  141. +40 −0 include/thrift/packages/cassandra/cassandra.Cassandra_set_keyspace_result.php
  142. +40 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_add_column_family_args.php
  143. +51 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_add_column_family_result.php
  144. +40 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_add_keyspace_args.php
  145. +51 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_add_keyspace_result.php
  146. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_drop_column_family_args.php
  147. +51 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_drop_column_family_result.php
  148. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_drop_keyspace_args.php
  149. +51 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_drop_keyspace_result.php
  150. +40 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_update_column_family_args.php
  151. +51 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_update_column_family_result.php
  152. +40 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_update_keyspace_args.php
  153. +51 −0 include/thrift/packages/cassandra/cassandra.Cassandra_system_update_keyspace_result.php
  154. +39 −0 include/thrift/packages/cassandra/cassandra.Cassandra_truncate_args.php
  155. +52 −0 include/thrift/packages/cassandra/cassandra.Cassandra_truncate_result.php
  156. +215 −0 include/thrift/packages/cassandra/cassandra.CfDef.php
  157. +54 −0 include/thrift/packages/cassandra/cassandra.Column.php
  158. +67 −0 include/thrift/packages/cassandra/cassandra.ColumnDef.php
  159. +58 −0 include/thrift/packages/cassandra/cassandra.ColumnOrSuperColumn.php
  160. +44 −0 include/thrift/packages/cassandra/cassandra.ColumnParent.php
  161. +49 −0 include/thrift/packages/cassandra/cassandra.ColumnPath.php
  162. +44 −0 include/thrift/packages/cassandra/cassandra.CounterColumn.php
  163. +49 −0 include/thrift/packages/cassandra/cassandra.CounterSuperColumn.php
  164. +70 −0 include/thrift/packages/cassandra/cassandra.CqlMetadata.php
  165. +53 −0 include/thrift/packages/cassandra/cassandra.CqlPreparedResult.php
  166. +60 −0 include/thrift/packages/cassandra/cassandra.CqlResult.php
  167. +49 −0 include/thrift/packages/cassandra/cassandra.CqlRow.php
  168. +50 −0 include/thrift/packages/cassandra/cassandra.Deletion.php
  169. +49 −0 include/thrift/packages/cassandra/cassandra.EndpointDetails.php
  170. +54 −0 include/thrift/packages/cassandra/cassandra.IndexClause.php
  171. +49 −0 include/thrift/packages/cassandra/cassandra.IndexExpression.php
  172. +37 −0 include/thrift/packages/cassandra/cassandra.InvalidRequestException.php
  173. +44 −0 include/thrift/packages/cassandra/cassandra.KeyCount.php
  174. +69 −0 include/thrift/packages/cassandra/cassandra.KeyRange.php
  175. +49 −0 include/thrift/packages/cassandra/cassandra.KeySlice.php
  176. +77 −0 include/thrift/packages/cassandra/cassandra.KsDef.php
  177. +46 −0 include/thrift/packages/cassandra/cassandra.Mutation.php
  178. +31 −0 include/thrift/packages/cassandra/cassandra.NotFoundException.php
  179. +31 −0 include/thrift/packages/cassandra/cassandra.SchemaDisagreementException.php
  180. +49 −0 include/thrift/packages/cassandra/cassandra.SlicePredicate.php
  181. +54 −0 include/thrift/packages/cassandra/cassandra.SliceRange.php
  182. +49 −0 include/thrift/packages/cassandra/cassandra.SuperColumn.php
  183. +31 −0 include/thrift/packages/cassandra/cassandra.TimedOutException.php
  184. +72 −0 include/thrift/packages/cassandra/cassandra.TokenRange.php
  185. +31 −0 include/thrift/packages/cassandra/cassandra.UnavailableException.php
  186. +15 −0 include/thrift/packages/cassandra/cassandra_constants.php
  187. +215 −0 include/thrift/packages/cassandra/cassandra_types.php
  188. 0  include/{phpcassa → }/thrift/protocol/TBinaryProtocol.php
  189. +1 −0  include/{phpcassa → }/thrift/protocol/TBinarySerializer.php
  190. +4 −2 include/{phpcassa → }/thrift/protocol/TProtocol.php
  191. 0  include/{phpcassa → }/thrift/transport/TBufferedTransport.php
  192. 0  include/{phpcassa → }/thrift/transport/TFramedTransport.php
  193. +2 −2 include/{phpcassa → }/thrift/transport/THttpClient.php
  194. 0  include/{phpcassa → }/thrift/transport/TMemoryBuffer.php
  195. 0  include/{phpcassa → }/thrift/transport/TNullTransport.php
  196. 0  include/{phpcassa → }/thrift/transport/TPhpStream.php
  197. 0  include/{phpcassa → }/thrift/transport/TServerSocket.php
  198. 0  include/{phpcassa → }/thrift/transport/TServerTransport.php
  199. 0  include/{phpcassa → }/thrift/transport/TSocket.php
  200. 0  include/{phpcassa → }/thrift/transport/TSocketPool.php
  201. 0  include/{phpcassa → }/thrift/transport/TTransport.php
  202. 0  include/{phpcassa → }/thrift/transport/TTransportFactory.php
  203. +8 −3 views/columnfamily_details.php
View
172 columnfamily_action.php
@@ -9,6 +9,11 @@
require('include/kernel.inc.php');
require('include/verify_login.inc.php');
+ use phpcassa\Connection\ConnectionPool;
+ use phpcassa\ColumnFamily;
+ use phpcassa\SuperColumnFamily;
+ use cassandra\IndexType;
+
$included_header = false;
$is_valid_action = false;
$action = '';
@@ -253,40 +258,28 @@
$columnfamily_name = $_GET['columnfamily_name'];
}
- $cf = ColumnFamilyHelper::getCFInKeyspace($keyspace_name,$columnfamily_name);
+ $cf_def = ColumnFamilyHelper::getCFInKeyspace($keyspace_name,$columnfamily_name);
+ $is_super_cf = $cf_def->column_type == 'Super';
try {
$pool = new ConnectionPool($keyspace_name, $cluster_helper->getArrayOfNodesForCurrentCluster(),null,5,5000,5000,10000,$cluster_helper->getCredentialsForCurrentCluster());
- $column_family = new ColumnFamily($pool, $columnfamily_name);
+
+ if ($is_super_cf) {
+ $column_family = new SuperColumnFamily($pool, $columnfamily_name);
+ }
+ else {
+ $column_family = new ColumnFamily($pool, $columnfamily_name);
+ }
$vw_vars['results'] = '';
$time_start = microtime(true);
if (count($tab_keys) == 1) {
- $output = array();
- $nb_iterations = 0;
- $last_column_name = '';
-
- do {
- $output = array_merge($output,$column_family->get($tab_keys[0],null,$last_column_name,'',false,COLUMNS_TO_FETCH_PER_ITERATION));
- end($output);
- $last_column_name = key($output);
- $nb_iterations++;
- } while (count($output) == COLUMNS_TO_FETCH_PER_ITERATION && $nb_iterations < (MAXIMUM_COLUMNS_TO_FETCH / COLUMNS_TO_FETCH_PER_ITERATION));
-
+ $output = $column_family->get($tab_keys[0]);
$output = array($tab_keys[0] => $output);
}
else {
- $output = array();
- $nb_iterations = 0;
- $last_column_name = '';
-
- do {
- $output = array_merge($output,$column_family->multiget($tab_keys,null,$last_column_name,'',false,COLUMNS_TO_FETCH_PER_ITERATION));
- end($output);
- $last_column_name = key($output);
- $nb_iterations++;
- } while (count($output) == COLUMNS_TO_FETCH_PER_ITERATION && $nb_iterations < (MAXIMUM_COLUMNS_TO_FETCH / COLUMNS_TO_FETCH_PER_ITERATION));
+ $output = $column_family->multiget($tab_keys);
}
$time_end = microtime(true);
@@ -340,8 +333,17 @@
try {
$pool = new ConnectionPool($keyspace_name, $cluster_helper->getArrayOfNodesForCurrentCluster(),null,5,5000,5000,10000,$cluster_helper->getCredentialsForCurrentCluster());
- $column_family = new ColumnFamily($pool, $columnfamily_name);
+
+ $cf_def = ColumnFamilyHelper::getCFInKeyspace($keyspace_name,$columnfamily_name);
+ $is_super_cf = $cf_def->column_type == 'Super';
+ if ($is_super_cf) {
+ $column_family = new SuperColumnFamily($pool, $columnfamily_name);
+ }
+ else {
+ $column_family = new ColumnFamily($pool, $columnfamily_name);
+ }
+
$no_index_expression = 0;
$arr_index_expression = array();
@@ -484,7 +486,15 @@
$key = $_POST['key'];
$pool = new ConnectionPool($keyspace_name, $cluster_helper->getArrayOfNodesForCurrentCluster(),null,5,5000,5000,10000,$cluster_helper->getCredentialsForCurrentCluster());
- $column_family = new ColumnFamily($pool, $columnfamily_name);
+ $cf_def = ColumnFamilyHelper::getCFInKeyspace($keyspace_name,$columnfamily_name);
+ $is_super_cf = $cf_def->column_type == 'Super';
+
+ if ($is_super_cf) {
+ $column_family = new SuperColumnFamily($pool, $columnfamily_name);
+ }
+ else {
+ $column_family = new ColumnFamily($pool, $columnfamily_name);
+ }
$no_column = 1;
@@ -642,9 +652,30 @@
$vw_vars['keyspace_name'] = $keyspace_name;
$vw_vars['columnfamily_name'] = $columnfamily_name;
- try {
+ try {
+ $describe_keyspace = $sys_manager->describe_keyspace($keyspace_name);
+
+ $cf_def = null;
+ foreach ($describe_keyspace->cf_defs as $cfdef) {
+ if ($cfdef->name == $columnfamily_name) {
+ $cf_def = $cfdef;
+ break;
+ }
+ }
+
+ $is_super_cf = $cf_def->column_type == 'Super';
+
+ $vw_row_vars['is_super_cf'] = $is_super_cf;
+ $vw_row_vars['is_counter_column'] = $cf_def->default_validation_class == 'org.apache.cassandra.db.marshal.CounterColumnType';
+
$pool = new ConnectionPool($keyspace_name, $cluster_helper->getArrayOfNodesForCurrentCluster(),null,5,5000,5000,10000,$cluster_helper->getCredentialsForCurrentCluster());
- $column_family = new ColumnFamily($pool, $columnfamily_name);
+
+ if ($is_super_cf) {
+ $column_family = new SuperColumnFamily($pool, $columnfamily_name);
+ }
+ else {
+ $column_family = new ColumnFamily($pool, $columnfamily_name);
+ }
// Increment counter
if (isset($_GET['increment'])) {
@@ -709,41 +740,12 @@
$nb_rows = 5;
if (isset($_GET['nb_rows']) && is_numeric($_GET['nb_rows']) && $_GET['nb_rows'] > 0) $nb_rows = $_GET['nb_rows'];
$vw_vars['nb_rows'] = $nb_rows;
-
- $describe_keyspace = $sys_manager->describe_keyspace($keyspace_name);
-
- $cf_def = null;
- foreach ($describe_keyspace->cf_defs as $cfdef) {
- if ($cfdef->name == $columnfamily_name) {
- $cf_def = $cfdef;
- break;
- }
- }
-
- $vw_row_vars['is_super_cf'] = $cf_def->column_type == 'Super';
- $vw_row_vars['is_counter_column'] = $column_family->cfdef->default_validation_class == 'org.apache.cassandra.db.marshal.CounterColumnType';
-
+
$included_header = true;
- echo getHTML('header.php');
-
- $output = array();
- $nb_iterations = 0;
- $last_column_name = '';
+ echo getHTML('header.php');
+
+ $output = $column_family->get_range($offset_key,'',$nb_rows,null);
- do {
- $output_to_merge = $column_family->get_range($offset_key,'',$nb_rows,null,$last_column_name,'',false,COLUMNS_TO_FETCH_PER_ITERATION);
-
- $count = 0;
- foreach ($output_to_merge as $key => $value) {
- $output[$key] = $value;
- $count++;
- }
-
- end($output_to_merge);
- $last_column_name = key($output_to_merge);
- $nb_iterations++;
- } while ($count == COLUMNS_TO_FETCH_PER_ITERATION && $nb_iterations < (MAXIMUM_COLUMNS_TO_FETCH / COLUMNS_TO_FETCH_PER_ITERATION));
-
$vw_vars['results'] = '';
$nb_results = 0;
@@ -825,6 +827,8 @@
if (!isset($vw_vars['error_message'])) $vw_vars['error_message'] = '';
$cf_def = ColumnFamilyHelper::getCFInKeyspace($keyspace_name,$columnfamily_name);
+
+ $is_super_cf = $cf_def->column_type == 'Super';
$vw_vars['is_super_cf'] = $cf_def->column_type == 'Super';
$vw_vars['key'] = $key;
@@ -834,21 +838,17 @@
try {
$pool = new ConnectionPool($keyspace_name, $cluster_helper->getArrayOfNodesForCurrentCluster(),null,5,5000,5000,10000,$cluster_helper->getCredentialsForCurrentCluster());
- $column_family = new ColumnFamily($pool, $columnfamily_name);
- $vw_vars['results'] = '';
-
- $output = array();
- $nb_iterations = 0;
- $last_column_name = '';
-
- do {
- $output = array_merge($output,$column_family->get($key,null,$last_column_name,'',false,COLUMNS_TO_FETCH_PER_ITERATION));
- end($output);
- $last_column_name = key($output);
- $nb_iterations++;
- } while (count($output) == COLUMNS_TO_FETCH_PER_ITERATION && $nb_iterations < (MAXIMUM_COLUMNS_TO_FETCH / COLUMNS_TO_FETCH_PER_ITERATION));
+ if ($is_super_cf) {
+ $column_family = new SuperColumnFamily($pool, $columnfamily_name);
+ }
+ else {
+ $column_family = new ColumnFamily($pool, $columnfamily_name);
+ }
+ $vw_vars['results'] = '';
+
+ $output = $column_family->get($key);
$vw_vars['output'] = $output;
}
catch (Exception $e) {
@@ -890,7 +890,16 @@
try {
$pool = new ConnectionPool($keyspace_name, $cluster_helper->getArrayOfNodesForCurrentCluster(),null,5,5000,5000,10000,$cluster_helper->getCredentialsForCurrentCluster());
- $column_family = new ColumnFamily($pool, $columnfamily_name);
+
+ $cf_def = ColumnFamilyHelper::getCFInKeyspace($keyspace_name,$columnfamily_name);
+ $is_super_cf = $cf_def->column_type == 'Super';
+
+ if ($is_super_cf) {
+ $column_family = new SuperColumnFamily($pool, $columnfamily_name);
+ }
+ else {
+ $column_family = new ColumnFamily($pool, $columnfamily_name);
+ }
$column_family->remove($key,null,$super_column_key);
@@ -937,16 +946,25 @@
try {
$pool = new ConnectionPool($keyspace_name, $cluster_helper->getArrayOfNodesForCurrentCluster(),null,5,5000,5000,10000,$cluster_helper->getCredentialsForCurrentCluster());
- $column_family = new ColumnFamily($pool, $columnfamily_name);
+
+ $cf_def = ColumnFamilyHelper::getCFInKeyspace($keyspace_name,$columnfamily_name);
+ $is_super_cf = $cf_def->column_type == 'Super';
+
+ if ($is_super_cf) {
+ $column_family = new SuperColumnFamily($pool, $columnfamily_name);
+ }
+ else {
+ $column_family = new ColumnFamily($pool, $columnfamily_name);
+ }
if ($action == 'dec') {
$value *= -1;
}
- $column_family->add($key, $column, $value,$super_column);
+ $column_family->add($key, $super_column, $column, $value);
$new_value = $column_family->get($key);
-
+
if ($column_family->cfdef->column_type == 'Super') {
$new_value = $new_value[$super_column][$column];
}
View
2  helper/ClusterHelper.php
@@ -38,7 +38,7 @@ public function getClusterIndex() {
*/
public function getClusterNameForIndex($index) {
try {
- $sys_manager = new SystemManager($this->getArrayOfNodesForIndex($index),$this->getCredentialsForIndex($index),1500,1500);
+ $sys_manager = new SystemManager($this->getRandomNodeForIndex($index),$this->getCredentialsForIndex($index),1500,1500);
return $sys_manager->describe_cluster_name();
}
View
27 include/autoload.php
@@ -0,0 +1,27 @@
+<?php
+
+$GLOBALS['THRIFT_ROOT'] = __DIR__.'/thrift';
+if (! isset($GLOBALS['THRIFT_AUTOLOAD'])) {
+ $GLOBALS['THRIFT_AUTOLOAD'] = array();
+}
+
+spl_autoload_register(function($className){
+ if (strpos($className, 'phpcassa') === 0) {
+ require_once __DIR__.'/'.str_replace('\\', '/', $className).'.php';
+ } else {
+ // Find the thrift-generated class file
+ global $THRIFT_AUTOLOAD;
+ $classl = strtolower($className);
+ if ($classl[0] == "\\") {
+ $classl = substr($classl, 1);
+ }
+ if (isset($THRIFT_AUTOLOAD[$classl])) {
+ require_once $GLOBALS['THRIFT_ROOT'].'/packages/'.$THRIFT_AUTOLOAD[$classl];
+ } else {
+ return false;
+ }
+ }
+});
+
+// This sets up the THRIFT_AUTOLOAD map
+require_once __DIR__.'/thrift/packages/cassandra/Cassandra.php';
View
3  include/conf.inc.php
@@ -39,7 +39,4 @@
define('CCA_PASSWORD','');
define('MX4J_HTTP_ADAPTOR_PORT',8081);
-
- define('MAXIMUM_COLUMNS_TO_FETCH',10000);
- define('COLUMNS_TO_FETCH_PER_ITERATION',1000);
?>
View
12 include/kernel.inc.php
@@ -6,9 +6,9 @@
@copyright All rights reserved - 2011
*/
- require('include/phpcassa/connection.php');
- require('include/phpcassa/columnfamily.php');
- require('include/phpcassa/sysmanager.php');
+ require('include/autoload.php');
+
+ use phpcassa\SystemManager;
require('include/lang/english.php');
@@ -17,6 +17,8 @@
require('helper/MX4J.php');
require('conf.inc.php');
+
+ error_reporting(E_ALL);
define('MINIMUM_THRIFT_API_VERSION_FOR_COUNTERS','19.10.0');
@@ -30,12 +32,12 @@
}
try {
- $sys_manager = new SystemManager($cluster_helper->getArrayOfNodesForCurrentCluster(),$cluster_helper->getCredentialsForCurrentCluster(),1500,1500);
+ $sys_manager = new SystemManager($cluster_helper->getRandomNodeForCurrentCluster(),$cluster_helper->getCredentialsForCurrentCluster(),1500,1500);
}
catch (NoServerAvailable $e) {
die(getHTML('header.php').getHTML('server_error.php',array('error_message' => displayErrorMessage('cassandra_server_error',array('error_message' => $e->getMessage())))).getHTML('footer.php'));
}
-
+
/*
Get the specified view and replace the php variables
*/
View
34 include/phpcassa/.gitignore
@@ -1,34 +0,0 @@
-*.swp
-*.swo
-*.diff
-*.pyc
-doc/_build/*
-thrift/ext/thrift_protocol/.deps
-thrift/ext/thrift_protocol/.libs/
-thrift/ext/thrift_protocol/Makefile
-thrift/ext/thrift_protocol/Makefile.fragments
-thrift/ext/thrift_protocol/Makefile.global
-thrift/ext/thrift_protocol/Makefile.objects
-thrift/ext/thrift_protocol/acinclude.m4
-thrift/ext/thrift_protocol/aclocal.m4
-thrift/ext/thrift_protocol/autom4te.cache/
-thrift/ext/thrift_protocol/build/
-thrift/ext/thrift_protocol/config.guess
-thrift/ext/thrift_protocol/config.h
-thrift/ext/thrift_protocol/config.h.in
-thrift/ext/thrift_protocol/config.log
-thrift/ext/thrift_protocol/config.nice
-thrift/ext/thrift_protocol/config.status
-thrift/ext/thrift_protocol/config.sub
-thrift/ext/thrift_protocol/configure
-thrift/ext/thrift_protocol/configure.in
-thrift/ext/thrift_protocol/install-sh
-thrift/ext/thrift_protocol/libtool
-thrift/ext/thrift_protocol/ltmain.sh
-thrift/ext/thrift_protocol/missing
-thrift/ext/thrift_protocol/mkinstalldirs
-thrift/ext/thrift_protocol/modules/
-thrift/ext/thrift_protocol/php_thrift_protocol.lo
-thrift/ext/thrift_protocol/run-tests.php
-thrift/ext/thrift_protocol/thrift_protocol.la
-thrift/ext/thrift_protocol/tmp-php.ini
View
18 include/phpcassa/AUTHORS
@@ -1,18 +0,0 @@
-Hoan Ton-That (hoan.tonthat@gmail.com)
-Benjamin Sussman (ben@fwix.com)
-Anthony ROUX (anthony.rx43@gmail.com)
-Vadim Derkach
-Zach Buller (zachbuller@gmail.com)
-Timandes
-Todd Zusman
-Yancho Georgiev (yancho@inspirestudio.net)
-Pieter Maes (maescool@gmail.com)
-Tyler Hobbs
-Artur Kotyrba
-Sébastien Giroux
-Paul Cannon
-Chris Campbell
-David McNelis
-William Oberman
-Wing Lian
-Max Wheeler
View
62 include/phpcassa/Batch/CfMutator.php
@@ -0,0 +1,62 @@
+<?
+namespace phpcassa\Batch;
+
+use phpcassa\Batch\Mutator;
+
+/**
+ * A convenience subclass of phpcassa\Batch\Mutator for dealing
+ * with batch operations on a single column family.
+ *
+ * @package phpcassa\Batch
+ */
+class CfMutator extends Mutator {
+
+ protected $cf;
+
+ /**
+ * Initialize a mutator for a given column family.
+ *
+ * @param phpcassa\ColumnFamily $column_family an initialized instanced
+ * of ColumnFamily; this object's pool will be used for all
+ * operations.
+ * @param phpcassa\ConsistencyLevel $consistency_level the default consistency
+ * level this mutator will write at, with a default of
+ * ConsistencyLevel::ONE
+ */
+ public function __construct($column_family, $write_consistency_level=null) {
+ $this->cf = $column_family;
+ if ($write_consistency_level === null)
+ $wcl = $column_family->write_consistency_level;
+ else
+ $wcl = $write_consistency_level;
+ parent::__construct($column_family->pool, $wcl);
+ }
+
+ /**
+ * Add an insertion to the buffer.
+ *
+ * @param mixed $key the row key
+ * @param mixed[] $columns an array of columns to insert, whose format
+ * should match $column_family->insert_format
+ * @param int $timestamp an optional timestamp (default is "now", when
+ * this function is called, not when send() is called)
+ * @param int $ttl a TTL to apply to all columns inserted here
+ */
+ public function insert($key, $columns, $timestamp=null, $ttl=null) {
+ return parent::insert($this->cf, $key, $columns, $timestamp, $ttl);
+ }
+
+ /**
+ * Add a deletion to the buffer.
+ *
+ * @param mixed $key the row key
+ * @param mixed[] $columns a list of columns or super columns to delete
+ * @param mixed $supercolumn if you want to delete only some subcolumns from
+ * a single super column, set this to the super column name
+ * @param int $timestamp an optional timestamp (default is "now", when
+ * this function is called, not when send() is called)
+ */
+ public function remove($key, $columns=null, $super_column=null, $timestamp=null) {
+ return parent::remove($this->cf, $key, $columns, $super_column, $timestamp);
+ }
+}
View
148 include/phpcassa/Batch/Mutator.php
@@ -0,0 +1,148 @@
+<?
+namespace phpcassa\Batch;
+
+use phpcassa\Util\Clock;
+
+use cassandra\ConsistencyLevel;
+use cassandra\Deletion;
+use cassandra\Mutation;
+use cassandra\SlicePredicate;
+
+/**
+ * Allows you to group multiple mutations across one or more
+ * keys and column families into a single batch operation.
+ *
+ * @package phpcassa\Batch
+ */
+class Mutator
+{
+ protected $pool;
+ protected $buffer;
+ protected $cl;
+
+ /**
+ * Intialize a mutator with a connection pool and consistency level.
+ *
+ * @param phpcassa\Connection\ConnectionPool $pool the connection pool to
+ * use for all operations
+ * @param cassandra\ConsistencyLevel $consistency_level the default consistency
+ * level this mutator will write at, with a default of
+ * ConsistencyLevel::ONE
+ */
+ public function __construct($pool,
+ $consistency_level=ConsistencyLevel::ONE) {
+ $this->pool = $pool;
+ $this->buffer = array();
+ $this->cl = $consistency_level;
+ }
+
+ protected function enqueue($key, $cf, $mutations) {
+ $mut = array($key, $cf->column_family, $mutations);
+ $this->buffer[] = $mut;
+ }
+
+ /**
+ * Send all buffered mutations.
+ *
+ * If an error occurs, the buffer will be preserverd, allowing you to
+ * attempt to call send() again later or take other recovery actions.
+ *
+ * @param cassandra\ConsistencyLevel $consistency_level optional
+ * override for the mutator's default consistency level
+ */
+ public function send($consistency_level=null) {
+ if ($consistency_level === null)
+ $wcl = $this->cl;
+ else
+ $wcl = $consistency_level;
+
+ $mutations = array();
+ foreach ($this->buffer as $mut_set) {
+ list($key, $cf, $cols) = $mut_set;
+
+ if (isset($mutations[$key])) {
+ $key_muts = $mutations[$key];
+ } else {
+ $key_muts = array();
+ }
+
+ if (isset($key_muts[$cf])) {
+ $cf_muts = $key_muts[$cf];
+ } else {
+ $cf_muts = array();
+ }
+
+ $cf_muts = array_merge($cf_muts, $cols);
+ $key_muts[$cf] = $cf_muts;
+ $mutations[$key] = $key_muts;
+ }
+
+ if (!empty($mutations)) {
+ $this->pool->call('batch_mutate', $mutations, $wcl);
+ }
+ $this->buffer = array();
+ }
+
+ /**
+ * Add an insertion to the buffer.
+ *
+ * @param phpcassa\ColumnFamily $column_family an initialized
+ * ColumnFamily instance
+ * @param mixed $key the row key
+ * @param mixed[] $columns an array of columns to insert, whose format
+ * should match $column_family->insert_format
+ * @param int $timestamp an optional timestamp (default is "now", when
+ * this function is called, not when send() is called)
+ * @param int $ttl a TTL to apply to all columns inserted here
+ */
+ public function insert($column_family, $key, $columns, $timestamp=null, $ttl=null) {
+ if (!empty($columns)) {
+ if ($timestamp === null)
+ $timestamp = Clock::get_time();
+ $key = $column_family->pack_key($key);
+ $mut_list = $column_family->make_mutation($columns, $timestamp, $ttl);
+ $this->enqueue($key, $column_family, $mut_list);
+ }
+ return $this;
+ }
+
+ /**
+ * Add a deletion to the buffer.
+ *
+ * @param phpcassa\ColumnFamily $column_family an initialized
+ * ColumnFamily instance
+ * @param mixed $key the row key
+ * @param mixed[] $columns a list of columns or super columns to delete
+ * @param mixed $supercolumn if you want to delete only some subcolumns from
+ * a single super column, set this to the super column name
+ * @param int $timestamp an optional timestamp (default is "now", when
+ * this function is called, not when send() is called)
+ */
+ public function remove($column_family, $key, $columns=null, $super_column=null, $timestamp=null) {
+ if ($timestamp === null)
+ $timestamp = Clock::get_time();
+ $deletion = new Deletion();
+ $deletion->timestamp = $timestamp;
+
+ if ($super_column !== null) {
+ $deletion->super_column = $column_family->pack_name($super_column, true);
+ }
+ if ($columns !== null) {
+ $is_super = $column_family->is_super && $super_column === null;
+ $packed_cols = array();
+ foreach ($columns as $col) {
+ $packed_cols[] = $column_family->pack_name($col, $is_super);
+ }
+ $predicate = new SlicePredicate();
+ $predicate->column_names = $packed_cols;
+ $deletion->predicate = $predicate;
+ }
+
+ $mutation = new Mutation();
+ $mutation->deletion = $deletion;
+ $packed_key = $column_family->pack_key($key);
+ $this->enqueue($packed_key, $column_family, array($mutation));
+
+ return $this;
+ }
+}
View
147 include/phpcassa/CHANGES
@@ -1,147 +0,0 @@
-Changelog
-=========
-
-Changes in 0.8.a.2
-------------------
-This release upgrades the bundled version of Thrift
-to 0.7.0, which fixes several issues with 32bit
-environments.
-
-Features
-^^^^^^^^
-- Add drop_index() to SystemManager
-- Order multiget_count() results by the order of the input
- keys
-- Allow for overriding the ConnectionPool error_log mechanism
- for custom error handling
-
-Bugfixes
-^^^^^^^^
-- Handle multiget() requests with responses that are
- larger than $buffer_size correctly
-- Don't ignore the $pool_size parameter in the ConnectionPool
- constructor
-- Pass data intended for UTF8Type values unaltered to Thrift.
- This fixes issues with corruption of some utf8 data, but the
- user is now responsible for ensuring the data is encoded
- correctly.
-- Fix corruption of timestamps in 32bit environments by
- upgrading to Thrift 0.7.0
-
-Changes in 0.8.a.1
-------------------
-This release adds support for Cassandra 0.8. This release is
-backwards compatible with Cassandra 0.7, and supports a cluster
-with a mixture of nodes running 0.7 and 0.8.
-
-Features
-^^^^^^^^
-- Added ColumnFamily.add() and remove_counter() to work with 0.8
- counters.
-
-- Support for the 0.8 column family attribute key_validation_class.
- Keys may now be automatically packed and upacked, similar to column
- names and values.
-
-- Addition of sysmanager.php and the SystemManager class. This class
- makes it much easier to dynamically create, alter, and drop keyspaces,
- column families, and secondary indexes.
-
-- New ConnectionPools are no longer automatically filled upon creation.
- The method ConnectionPool.fill() was added as an alternative way to
- supply this functionality.
-
-Bugfixes
-^^^^^^^^
-- Handle NotFoundException and other Exceptions cleanly in ConnectionPool.
- Previously, these could result in a slow drain of connections from the
- pool.
-
-- The default ColumnFamily buffer_size has been lowered from 8096 to 1024.
-
-Deprecated
-^^^^^^^^^^
-- The ColumnFamily constructor arguments $autopack_names and $autopack_values
- are deprecated. Use set_autopack_names() and
- set_autopack_values() after creating the ColumnFamily instead.
-
-- The ColumnFamily constructor argument $buffer_size has been deprecated.
- The public attribute $buffer_size should be set instead.
-
-- The ColumnFamily constructor arguments $read_consistency_level
- and $write_consistency_level have been deprecated.
- The public attributes of the same names should be set instead. Both
- attributes still default to ConsistencyLevel ONE.
-
-- The ConnectionPool constructor argument $framed_transport is deprecated;
- framed transport will be assumed in later versions.
-
-- The ConnectionPool constructor argument $max_retries is deprecated;
- adjust the public attribue of the same name instead.
-
-- The ConnectionPool constructor argument $recycle is deprecated;
- adjust the public attribue of the same name instead.
-
-Changes in 0.7.a.4
-------------------
-
-The bundled Thrift library has been updated to a post-0.6 trunk
-version. An important bugfix was made in Thrift which greatly
-improves performance.
-
-Bugfixes
-^^^^^^^^
-- Credentials were not properly passed through Thrift, causing
- any authorization attempts to fail.
-
-Features
-^^^^^^^^
-- Added the ConnectionPool class to connection.php. This allows
- for better failover and loadbalancing of operations. See the
- documentation for the ConnectionPool class when upgrading from
- 0.7.a.3 or earlier.
-
-Deprecated
-^^^^^^^^^^
-- The Connection class in connection.php has been replaced by
- ConnectionPool and is now deprecated.
-
-Changes in 0.7.a.3
-------------------
-
-Bugfixes
-^^^^^^^^
-- Typo in throwing IncompatibleAPIException
-- remove() on super column families did not pack names correctly
-- CassandraUtil::uuid3() param name should be $node not $null
-
-Features
-^^^^^^^^
-- Use remove() Thrift API call instead of batch_mutate() when possible
-- Allow a microsecond timestamp to be passed in for v1 UUID creation
-- Log connection errors with error_log()
-
-Deprecated
-^^^^^^^^^^
-None
-
-Changes in 0.7.a.2
-------------------
-
-Bugfixes
-^^^^^^^^
-- Fix server revival bug
-- Remove print statement from Connection on connection failure
-
-Features
-^^^^^^^^
-- Add an import() method for UUIDs to CassandraUtil to convert binary UUID
- representations back into UUID objects
-
-Deprecated
-^^^^^^^^^^^^
-None
-
-Changes in 0.7.a1
------------------
-Initial release
View
1,099 include/phpcassa/ColumnFamily.php
@@ -0,0 +1,1099 @@
+<?php
+namespace phpcassa;
+
+use phpcassa\Schema\DataType;
+use phpcassa\Schema\DataType\BytesType;
+use phpcassa\Schema\DataType\CompositeType;
+use phpcassa\Schema\DataType\Serialized;
+
+use phpcassa\Iterator\IndexedColumnFamilyIterator;
+use phpcassa\Iterator\RangeColumnFamilyIterator;
+
+use phpcassa\Batch\CfMutator;
+
+use phpcassa\Util\Clock;
+
+use cassandra\InvalidRequestException;
+use cassandra\NotFoundException;
+
+use cassandra\Mutation;
+use cassandra\Deletion;
+use cassandra\ConsistencyLevel;
+use cassandra\Column;
+use cassandra\ColumnParent;
+use cassandra\ColumnPath;
+use cassandra\ColumnOrSuperColumn;
+use cassandra\CounterColumn;
+use cassandra\IndexClause;
+use cassandra\IndexExpression;
+use cassandra\SlicePredicate;
+use cassandra\SliceRange;
+
+/**
+ * Representation of a column family in Cassandra.
+ *
+ * All data insertions, deletions, or retrievals will go through a ColumnFamily.
+ * This may only be used for standard column families; you must use
+ * \phpcassa\SuperColumnFamily for super column families.
+ *
+ * @package phpcassa
+ */
+class ColumnFamily {
+
+ /** The default limit to the number of rows retrieved in queries. */
+ const DEFAULT_ROW_COUNT = 100;
+
+ const DEFAULT_BUFFER_SIZE = 100;
+
+ /**
+ * Data that is returned will be stored in a "dictionary" format,
+ * where array keys correspond to row keys, super column names,
+ * or column names. Data that is inserted should match this format.
+ *
+ * When using non-scalar types or floats with this format, array keys
+ * must be serialized and unserialized. This is typically a good reason
+ * to use one of the other formats.
+ *
+ * This format is what phpcassa has historically used. This may be used
+ * for both ColumnFamily::insert_format and ColumnFamily::return_format.
+ */
+ const DICTIONARY_FORMAT = 1;
+
+ /**
+ * Data that is returned will be stored in normal, non-mapping arrays.
+ * For example, a column will be represented as array($name, $value),
+ * and a row returned with multiget() will be represented as
+ * array($rowkey, array(array($colname1, $colval1), array($colname2, $colval2))).
+ *
+ * Data that is inserted should match this format. Serialization is not needed with
+ * this format.
+ *
+ * This may be used for both ColumnFamily::insert_format and
+ * ColumnFamily::return_format.
+ */
+ const ARRAY_FORMAT = 2;
+
+ /**
+ * Data will be returned in a object-based format, roughly matching
+ * what Thrift returns directly. This means that results will contain:
+ * Column objects, which have $name, $value, $timestamp, and $ttl attributes;
+ * CounterColumn objects, which have $name and $value attributes;
+ * SuperColumn objects, which have $name and $columns attributes, where
+ * $columns is an array of Column or CounterColumn objects.
+ *
+ * This format can currently only be used for ColumnFamily::return_format,
+ * not ColumnFamily::insert_format.
+ *
+ * Unserialization is not required for this format.
+ */
+ const OBJECT_FORMAT = 3;
+
+ /** @internal */
+ public $column_family;
+
+ /** @internal */
+ public $is_super;
+
+ protected $cf_data_type;
+ protected $col_name_type;
+ protected $supercol_name_type;
+ protected $col_type_dict;
+
+
+ /**
+ * Whether column names should be packed and unpacked automatically.
+ * Default is true.
+ */
+ public $autopack_names;
+
+ /**
+ * Whether column values should be packed and unpacked automatically.
+ * Default is true.
+ */
+ public $autopack_values;
+
+ /**
+ * Whether keys should be packed and unpacked automatically.
+ * Default is true.
+ */
+ public $autopack_keys;
+
+ /** @var ConsistencyLevel the default read consistency level */
+ public $read_consistency_level = ConsistencyLevel::ONE;
+ /** @var ConsistencyLevel the default write consistency level */
+ public $write_consistency_level = ConsistencyLevel::ONE;
+
+ /**
+ * The format that data will be returned in.
+ *
+ * Valid values include DICTIONARY_FORMAT, ARRAY_FORMAT,
+ * and OBJECT_FORMAT.
+ */
+ public $return_format = self::DICTIONARY_FORMAT;
+
+ /**
+ * The format that data should be inserted in.
+ *
+ * Valid values include DICTIONARY_FORMAT and
+ * ARRAY_FORMAT.
+ */
+ public $insert_format = self::DICTIONARY_FORMAT;
+
+ /**
+ * @var int When calling `get_range`, the intermediate results need
+ * to be buffered if we are fetching many rows, otherwise the Cassandra
+ * server will overallocate memory and fail. This is the size of
+ * that buffer in number of rows. The default is 100.
+ */
+ public $buffer_size = 100;
+
+ /**
+ * Constructs a ColumnFamily.
+ *
+ * @param phpcassa\Connection\ConnectionPool $pool the pool to use when
+ * querying Cassandra
+ * @param string $column_family the name of the column family in Cassandra
+ * @param bool $autopack_names whether or not to automatically convert column names
+ * to and from their binary representation in Cassandra
+ * based on their comparator type
+ * @param bool $autopack_values whether or not to automatically convert column values
+ * to and from their binary representation in Cassandra
+ * based on their validator type
+ * @param ConsistencyLevel $read_consistency_level the default consistency
+ * level for read operations on this column family
+ * @param ConsistencyLevel $write_consistency_level the default consistency
+ * level for write operations on this column family
+ * @param int $buffer_size When calling `get_range`, the intermediate results need
+ * to be buffered if we are fetching many rows, otherwise the Cassandra
+ * server will overallocate memory and fail. This is the size of
+ * that buffer in number of rows.
+ */
+ public function __construct($pool,
+ $column_family,
+ $autopack_names=true,
+ $autopack_values=true,
+ $read_consistency_level=ConsistencyLevel::ONE,
+ $write_consistency_level=ConsistencyLevel::ONE,
+ $buffer_size=self::DEFAULT_BUFFER_SIZE) {
+
+ $this->pool = $pool;
+ $this->column_family = $column_family;
+ $this->read_consistency_level = $read_consistency_level;
+ $this->write_consistency_level = $write_consistency_level;
+ $this->buffer_size = $buffer_size;
+
+ $ks = $this->pool->describe_keyspace();
+
+ $cf_def = null;
+ foreach($ks->cf_defs as $cfdef) {
+ if ($cfdef->name == $this->column_family) {
+ $cf_def = $cfdef;
+ break;
+ }
+ }
+ if ($cf_def == null)
+ throw new NotFoundException();
+ else
+ $this->cfdef = $cf_def;
+
+ $this->cf_data_type = new BytesType();
+ $this->col_name_type = new BytesType();
+ $this->supercol_name_type = new BytesType();
+ $this->key_type = new BytesType();
+ $this->col_type_dict = array();
+
+ $this->is_super = $this->cfdef->column_type === 'Super';
+ $this->has_counters = self::endswith(
+ $this->cfdef->default_validation_class,
+ "CounterColumnType");
+
+ $this->set_autopack_names($autopack_names);
+ $this->set_autopack_values($autopack_values);
+ $this->set_autopack_keys(true);
+ }
+
+ protected static function endswith($str, $suffix) {
+ $suffix_len = strlen($suffix);
+ return substr_compare($str, $suffix, strlen($str)-$suffix_len, $suffix_len) === 0;
+ }
+
+ /**
+ * @param bool $pack_names whether or not column names are automatically packed/unpacked
+ */
+ public function set_autopack_names($pack_names) {
+ if ($pack_names) {
+ if ($this->autopack_names)
+ return;
+ $this->autopack_names = true;
+ if (!$this->is_super) {
+ $this->col_name_type = DataType::get_type_for($this->cfdef->comparator_type);
+ } else {
+ $this->col_name_type = DataType::get_type_for($this->cfdef->subcomparator_type);
+ $this->supercol_name_type = DataType::get_type_for($this->cfdef->comparator_type);
+ }
+ } else {
+ $this->autopack_names = false;
+ }
+ }
+
+ /**
+ * @param bool $pack_values whether or not column values are automatically packed/unpacked
+ */
+ public function set_autopack_values($pack_values) {
+ if ($pack_values) {
+ $this->autopack_values = true;
+ $this->cf_data_type = DataType::get_type_for($this->cfdef->default_validation_class);
+ foreach($this->cfdef->column_metadata as $coldef) {
+ $this->col_type_dict[$coldef->name] =
+ DataType::get_type_for($coldef->validation_class);
+ }
+ } else {
+ $this->autopack_values = false;
+ }
+ }
+
+ /**
+ * @param bool $pack_keys whether or not keys are automatically packed/unpacked
+ *
+ * Available since Cassandra 0.8.0.
+ */
+ public function set_autopack_keys($pack_keys) {
+ if ($pack_keys) {
+ $this->autopack_keys = true;
+ if (property_exists('\cassandra\CfDef', "key_validation_class")) {
+ $this->key_type = DataType::get_type_for($this->cfdef->key_validation_class);
+ } else {
+ $this->key_type = new BytesType();
+ }
+ } else {
+ $this->autopack_keys = false;
+ }
+ }
+
+ /**
+ * Fetch a row from this column family.
+ *
+ * @param string $key row key to fetch
+ * @param \phpcassa\ColumnSlice a slice of columns to fetch, or null
+ * @param mixed[] $column_names limit the columns or super columns fetched to this list
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ *
+ * @return mixed array(column_name => column_value)
+ */
+ public function get($key,
+ $column_slice=null,
+ $column_names=null,
+ $consistency_level=null) {
+
+ $column_parent = $this->create_column_parent();
+ $predicate = $this->create_slice_predicate($column_names, $column_slice);
+ return $this->_get($key, $column_parent, $predicate, $consistency_level);
+ }
+
+ protected function _get($key, $cp, $slice, $cl) {
+ $resp = $this->pool->call("get_slice",
+ $this->pack_key($key),
+ $cp, $slice, $this->rcl($cl));
+
+ if (count($resp) == 0)
+ throw new NotFoundException();
+
+ return $this->unpack_coscs($resp);
+ }
+
+ /**
+ * Fetch a set of rows from this column family.
+ *
+ * @param string[] $keys row keys to fetch
+ * @param \phpcassa\ColumnSlice a slice of columns to fetch, or null
+ * @param mixed[] $column_names limit the columns or super columns fetched to this list
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ * @param int $buffer_size the number of keys to multiget at a single time. If your
+ * rows are large, having a high buffer size gives poor performance; if your
+ * rows are small, consider increasing this value.
+ *
+ * @return mixed array(key => array(column_name => column_value))
+ */
+ public function multiget($keys,
+ $column_slice=null,
+ $column_names=null,
+ $consistency_level=null,
+ $buffer_size=16) {
+
+ $cp = $this->create_column_parent();
+ $slice = $this->create_slice_predicate($column_names, $column_slice);
+
+ return $this->_multiget($keys, $cp, $slice, $consistency_level, $buffer_size);
+ }
+
+ protected function _multiget($keys, $cp, $slice, $cl, $buffsz) {
+ $ret = array();
+
+ $have_dict = ($this->return_format == self::DICTIONARY_FORMAT);
+ $should_serialize = ($this->key_type instanceof Serialized);
+ if ($have_dict) {
+ if ($should_serialize) {
+ foreach($keys as $key) {
+ $ret[serialize($key)] = null;
+ }
+ } else {
+ foreach($keys as $key) {
+ $ret[$key] = null;
+ }
+ }
+ }
+
+ $cl = $this->rcl($cl);
+
+ $resp = array();
+ if(count($keys) <= $buffsz) {
+ $resp = $this->pool->call("multiget_slice",
+ array_map(array($this, "pack_key"), $keys),
+ $cp, $slice, $cl);
+ } else {
+ $subset_keys = array();
+ $i = 0;
+ foreach($keys as $key) {
+ $i += 1;
+ $subset_keys[] = $key;
+ if ($i == $buffsz) {
+ $sub_resp = $this->pool->call("multiget_slice",
+ array_map(array($this, "pack_key"), $subset_keys),
+ $cp, $slice, $cl);
+ $subset_keys = array();
+ $i = 0;
+ $resp = $resp + $sub_resp;
+ }
+ }
+ if (count($subset_keys) != 0) {
+ $sub_resp = $this->pool->call("multiget_slice",
+ array_map(array($this, "pack_key"), $subset_keys),
+ $cp, $slice, $cl);
+ $resp = $resp + $sub_resp;
+ }
+ }
+
+ $non_empty_keys = array();
+ foreach($resp as $key => $val) {
+ if (count($val) > 0) {
+ $unpacked_key = $this->unpack_key($key, $have_dict);
+
+ if ($have_dict) {
+ $non_empty_keys[$unpacked_key] = 1;
+ $ret[$unpacked_key] = $this->unpack_coscs($val);
+ } else {
+ $ret[] = array($unpacked_key, $this->unpack_coscs($val));
+ }
+ }
+ }
+
+ if ($have_dict) {
+ if ($should_serialize) {
+ foreach($keys as $key) {
+ $skey = serialize($key);
+ if (!isset($non_empty_keys[$skey]))
+ unset($ret[$skey]);
+ }
+ } else {
+ foreach($keys as $key) {
+ if (!isset($non_empty_keys[$key]))
+ unset($ret[$key]);
+ }
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Count the number of columns in a row.
+ *
+ * @param string $key row to be counted
+ * @param \phpcassa\ColumnSlice a slice of columns to count, or null
+ * @param mixed[] $column_names limit the possible columns or super columns counted to this list
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ *
+ * @return int
+ */
+ public function get_count($key,
+ $column_slice=null,
+ $column_names=null,
+ $consistency_level=null) {
+
+ $cp = $this->create_column_parent();
+ $slice = $this->create_slice_predicate($column_names, $column_slice);
+ return $this->_get_count($key, $cp, $slice, $consistency_level);
+ }
+
+ protected function _get_count($key, $cp, $slice, $cl) {
+ $packed_key = $this->pack_key($key);
+ return $this->pool->call("get_count", $packed_key, $cp, $slice, $this->rcl($cl));
+ }
+
+ /**
+ * Count the number of columns in a set of rows.
+ *
+ * @param string[] $keys rows to be counted
+ * @param \phpcassa\ColumnSlice a slice of columns to count, or null
+ * @param mixed[] $column_names limit the possible columns or super columns counted to this list
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ *
+ * @return mixed array(row_key => row_count)
+ */
+ public function multiget_count($keys,
+ $column_slice=null,
+ $column_names=null,
+ $consistency_level=null) {
+
+ $cp = $this->create_column_parent();
+ $slice = $this->create_slice_predicate($column_names, $column_slice);
+
+ return $this->_multiget_count($keys, $cp, $slice, $consistency_level);
+ }
+
+ protected function _multiget_count($keys, $cp, $slice, $cl) {
+
+ $ret = array();
+ $have_dict = ($this->return_format == self::DICTIONARY_FORMAT);
+ if ($have_dict) {
+ foreach($keys as $key) {
+ $ret[$key] = null;
+ }
+ }
+
+ $packed_keys = array_map(array($this, "pack_key"), $keys);
+ $results = $this->pool->call("multiget_count", $packed_keys, $cp, $slice,
+ $this->rcl($cl));
+
+ $non_empty_keys = array();
+ foreach ($results as $key => $count) {
+ $unpacked_key = $this->unpack_key($key, $have_dict);
+
+ if ($have_dict) {
+ $non_empty_keys[$unpacked_key] = 1;
+ $ret[$unpacked_key] = $count;
+ } else {
+ $ret[] = array($unpacked_key, $count);
+ }
+ }
+
+ if ($have_dict) {
+ foreach($keys as $key) {
+ if (!isset($non_empty_keys[$key]))
+ unset($ret[$key]);
+ }
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Get an iterator over a range of rows.
+ *
+ * @param string $key_start fetch rows with a key >= this
+ * @param string $key_finish fetch rows with a key <= this
+ * @param int $row_count limit the number of rows returned to this amount
+ * @param \phpcassa\ColumnSlice a slice of columns to fetch, or null
+ * @param mixed[] $column_names limit the columns or super columns fetched to this list
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ * @param int $buffer_size When calling `get_range`, the intermediate results need
+ * to be buffered if we are fetching many rows, otherwise the Cassandra
+ * server will overallocate memory and fail. This is the size of
+ * that buffer in number of rows.
+ *
+ * @return phpcassa\Iterator\RangeColumnFamilyIterator
+ */
+ public function get_range($key_start="",
+ $key_finish="",
+ $row_count=self::DEFAULT_ROW_COUNT,
+ $column_slice=null,
+ $column_names=null,
+ $consistency_level=null,
+ $buffer_size=null) {
+
+ $cp = $this->create_column_parent();
+ $slice = $this->create_slice_predicate($column_names, $column_slice);
+
+ return $this->_get_range($key_start, $key_finish, $row_count,
+ $cp, $slice, $consistency_level, $buffer_size);
+ }
+
+ protected function _get_range($start, $finish, $count, $cp, $slice, $cl, $buffsz) {
+
+ if ($buffsz == null)
+ $buffsz = $this->buffer_size;
+ if ($buffsz < 2) {
+ $ire = new InvalidRequestException();
+ $ire->message = 'buffer_size cannot be less than 2';
+ throw $ire;
+ }
+
+ $packed_key_start = $this->pack_key($start);
+ $packed_key_finish = $this->pack_key($finish);
+
+ return new RangeColumnFamilyIterator($this, $buffsz,
+ $packed_key_start, $packed_key_finish,
+ $count, $cp, $slice, $this->rcl($cl));
+ }
+
+ /**
+ * Fetch a set of rows from this column family based on an index clause.
+ *
+ * @param phpcassa\Index\IndexClause $index_clause limits the keys that are returned based
+ * on expressions that compare the value of a column to a given value. At least
+ * one of the expressions in the IndexClause must be on an indexed column.
+ * @param phpcassa\ColumnSlice a slice of columns to fetch, or null
+ * @param mixed[] $column_names limit the columns or super columns fetched to this list
+ * number of nodes that must respond before the operation returns
+ *
+ * @return phpcassa\Iterator\IndexedColumnFamilyIterator
+ */
+ public function get_indexed_slices($index_clause,
+ $column_slice=null,
+ $column_names=null,
+ $consistency_level=null,
+ $buffer_size=null) {
+
+ if ($buffer_size == null)
+ $buffer_size = $this->buffer_size;
+ if ($buffer_size < 2) {
+ $ire = new InvalidRequestException();
+ $ire->message = 'buffer_size cannot be less than 2';
+ throw $ire;
+ }
+
+ $new_clause = new IndexClause();
+ foreach($index_clause->expressions as $expr) {
+ $new_expr = new IndexExpression();
+ $new_expr->value = $this->pack_value($expr->value, $expr->column_name);
+ $new_expr->column_name = $this->pack_name($expr->column_name);
+ $new_expr->op = $expr->op;
+ $new_clause->expressions[] = $new_expr;
+ }
+ $new_clause->start_key = $this->pack_key($index_clause->start_key);
+ $new_clause->count = $index_clause->count;
+
+ $column_parent = $this->create_column_parent();
+ $predicate = $this->create_slice_predicate($column_names, $column_slice);
+
+ return new IndexedColumnFamilyIterator($this, $new_clause, $buffer_size,
+ $column_parent, $predicate,
+ $this->rcl($consistency_level));
+ }
+
+ /**
+ * Insert or update columns in a row.
+ *
+ * @param string $key the row to insert or update the columns in
+ * @param mixed[] $columns array(column_name => column_value) the columns to insert or update
+ * @param int $timestamp the timestamp to use for this insertion. Leaving this as null will
+ * result in a timestamp being generated for you
+ * @param int $ttl time to live for the columns; after ttl seconds they will be deleted
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ *
+ * @return int the timestamp for the operation
+ */
+ public function insert($key,
+ $columns,
+ $timestamp=null,
+ $ttl=null,
+ $consistency_level=null) {
+
+ if ($timestamp === null)
+ $timestamp = Clock::get_time();
+
+ $cfmap = array();
+ $packed_key = $this->pack_key($key);
+ $cfmap[$packed_key][$this->column_family] =
+ $this->make_mutation($columns, $timestamp, $ttl);
+
+ return $this->pool->call("batch_mutate", $cfmap, $this->wcl($consistency_level));
+ }
+
+ /**
+ * Increment or decrement a counter.
+ *
+ * `value` should be an integer, either positive or negative, to be added
+ * to a counter column. By default, `value` is 1.
+ *
+ * This method is not idempotent. Retrying a failed add may result
+ * in a double count. You should consider using a separate
+ * ConnectionPool with retries disabled for column families
+ * with counters.
+ *
+ * Only available in Cassandra 0.8.0 and later.
+ *
+ * @param string $key the row to insert or update the columns in
+ * @param mixed $column the column name of the counter
+ * @param int $value the amount to adjust the counter by
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ */
+ public function add($key, $column, $value=1, $consistency_level=null) {
+ $packed_key = $this->pack_key($key);
+ $cp = $this->create_column_parent();
+ $counter = new CounterColumn();
+ $counter->name = $this->pack_name($column);
+ $counter->value = $value;
+ return $this->pool->call("add", $packed_key, $cp, $counter,
+ $this->wcl($consistency_level));
+ }
+
+ /**
+ * Insert or update columns in multiple rows. Note that this operation is only atomic
+ * per row.
+ *
+ * @param array $rows an array of keys, each of which maps to an array of columns. This
+ * looks like array(key => array(column_name => column_value))
+ * @param int $timestamp the timestamp to use for these insertions. Leaving this as null will
+ * result in a timestamp being generated for you
+ * @param int $ttl time to live for the columns; after ttl seconds they will be deleted
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ *
+ * @return int the timestamp for the operation
+ */
+ public function batch_insert($rows, $timestamp=null, $ttl=null, $consistency_level=null) {
+ if ($timestamp === null)
+ $timestamp = Clock::get_time();
+
+ $cfmap = array();
+ if ($this->insert_format == self::DICTIONARY_FORMAT) {
+ foreach($rows as $key => $columns) {
+ $packed_key = $this->pack_key($key);
+ $cfmap[$packed_key][$this->column_family] =
+ $this->make_mutation($columns, $timestamp, $ttl);
+ }
+ } else if ($this->insert_format == self::ARRAY_FORMAT) {
+ foreach($rows as $row) {
+ list($key, $columns) = $row;
+ $packed_key = $this->pack_key($key);
+ $cfmap[$packed_key][$this->column_family] =
+ $this->make_mutation($columns, $timestamp, $ttl);
+ }
+ } else {
+ throw new UnexpectedValueException("Bad insert_format selected");
+ }
+
+ return $this->pool->call("batch_mutate", $cfmap, $this->wcl($consistency_level));
+ }
+
+ public function batch($consistency_level=null) {
+ return new CfMutator($this, $consistency_level);
+ }
+
+ /**
+ * Delete a row or a set of columns or supercolumns from a row.
+ *
+ * @param string $key the row to remove columns from
+ * @param mixed[] $column_names the columns or supercolumns to remove.
+ * If null, the entire row will be removed.
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ *
+ * @return int the timestamp for the operation
+ */
+ public function remove($key, $column_names=null, $consistency_level=null) {
+
+ if ($column_names === null || count($column_names) == 1)
+ {
+ $cp = new ColumnPath();
+ $cp->column_family = $this->column_family;
+
+ if ($column_names !== null) {
+ if ($this->is_super)
+ $cp->super_column = $this->pack_name($column_names[0], true);
+ else
+ $cp->column = $this->pack_name($column_names[0], false);
+ }
+ return $this->_remove_single($key, $cp, $consistency_level);
+ } else {
+ $deletion = new Deletion();
+ if ($column_names !== null)
+ $deletion->predicate = $this->create_slice_predicate($column_names, null);
+
+ return $this->_remove_multi($key, $deletion, $consistency_level);
+ }
+ }
+
+ protected function _remove_single($key, $cp, $cl) {
+ $timestamp = Clock::get_time();
+ $packed_key = $this->pack_key($key);
+ return $this->pool->call("remove", $packed_key, $cp, $timestamp,
+ $this->wcl($cl));
+ }
+
+ protected function _remove_multi($key, $deletion, $cl) {
+ $timestamp = Clock::get_time();
+ $deletion->timestamp = $timestamp;
+ $mutation = new Mutation();
+ $mutation->deletion = $deletion;
+
+ $packed_key = $this->pack_key($key);
+ $mut_map = array($packed_key => array($this->column_family => array($mutation)));
+
+ return $this->pool->call("batch_mutate", $mut_map, $this->wcl($cl));
+ }
+
+ /**
+ * Remove a counter at the specified location.
+ *
+ * Note that counters have limited support for deletes: if you remove a
+ * counter, you must wait to issue any following update until the delete
+ * has reached all the nodes and all of them have been fully compacted.
+ *
+ * Available in Cassandra 0.8.0 and later.
+ *
+ * @param string $key the key for the row
+ * @param mixed $column the column name of the counter
+ * @param ConsistencyLevel $consistency_level affects the guaranteed
+ * number of nodes that must respond before the operation returns
+ */
+ public function remove_counter($key, $column, $consistency_level=null) {
+ $cp = new ColumnPath();
+ $packed_key = $this->pack_key($key);
+ $cp->column_family = $this->column_family;
+ $cp->column = $this->pack_name($column);
+ $this->pool->call("remove_counter", $packed_key, $cp,
+ $this->wcl($consistency_level));
+ }
+
+ /**
+ * Mark the entire column family as deleted.
+ *
+ * From the user's perspective a successful call to truncate will result
+ * complete data deletion from cfname. Internally, however, disk space
+ * will not be immediatily released, as with all deletes in cassandra,
+ * this one only marks the data as deleted.
+ *
+ * The operation succeeds only if all hosts in the cluster at available
+ * and will throw an UnavailableException if some hosts are down.
+ */
+ public function truncate() {
+ return $this->pool->call("truncate", $this->column_family);
+ }
+
+
+ /********************* Helper functions *************************/
+
+ protected function rcl($read_consistency_level) {
+ if ($read_consistency_level === null)
+ return $this->read_consistency_level;
+ else
+ return $read_consistency_level;
+ }
+
+ protected function wcl($write_consistency_level) {
+ if ($write_consistency_level === null)
+ return $this->write_consistency_level;
+ else
+ return $write_consistency_level;
+ }
+
+ protected function create_slice_predicate($column_names, $column_slice) {
+
+ $predicate = new SlicePredicate();
+ if ($column_names !== null) {
+ $packed_cols = array();
+ foreach($column_names as $col)
+ $packed_cols[] = $this->pack_name($col, $this->is_super);
+ $predicate->column_names = $packed_cols;
+ } else {
+ if ($column_slice !== null) {
+ $slice_range = new SliceRange();
+
+ $column_start = $column_slice->start;
+ if ($column_start !== null and $column_start != '') {
+ if ($column_slice->reversed)
+ $slice_end = self::SLICE_FINISH;
+ else
+ $slice_end = self::SLICE_START;
+
+ $slice_range->start = $this->pack_name(
+ $column_start, $this->is_super, $slice_end);
+ } else {
+ $slice_range->start = '';
+ }
+
+ $column_finish = $column_slice->finish;
+ if ($column_finish !== null and $column_finish != '') {
+ if ($column_slice->reversed)
+ $slice_end = self::SLICE_START;
+ else
+ $slice_end = self::SLICE_FINISH;
+
+ $slice_range->finish = $this->pack_name(
+ $column_finish, $this->is_super, $slice_end);
+ } else {
+ $slice_range->finish = '';
+ }
+
+ $slice_range->reversed = $column_slice->reversed;
+ $slice_range->count = $column_slice->count;
+ } else {
+ $slice_range = new ColumnSlice();
+ }
+ $predicate->slice_range = $slice_range;
+ }
+ return $predicate;
+ }
+
+ protected function create_column_parent($super_column=null) {
+ $column_parent = new ColumnParent();
+ $column_parent->column_family = $this->column_family;
+ if ($super_column !== null) {
+ $column_parent->super_column = $this->pack_name($super_column, true);
+ } else {
+ $column_parent->super_column = null;
+ }
+ return $column_parent;
+ }
+
+ /** @internal */
+ const NON_SLICE = 0;
+ /** @internal */
+ const SLICE_START = 1;
+ /** @internal */
+ const SLICE_FINISH = 2;
+
+ public function pack_name($value,
+ $is_supercol_name=false,
+ $slice_end=self::NON_SLICE,
+ $handle_serialize=false) {
+ if (!$this->autopack_names)
+ return $value;
+ if ($slice_end === self::NON_SLICE && ($value === null || $value === "")) {
+ throw new \UnexpectedValueException("Column names may not be null");
+ }
+ if ($is_supercol_name)
+ return $this->supercol_name_type->pack($value, true, $slice_end, $handle_serialize);
+ else
+ return $this->col_name_type->pack($value, true, $slice_end, $handle_serialize);
+ }
+
+ protected function unpack_name($b, $is_supercol_name=false, $handle_serialize=true) {
+ if (!$this->autopack_names || $b === null)
+ return $b;
+
+ if ($is_supercol_name)
+ return $this->supercol_name_type->unpack($b, $handle_serialize);
+ else
+ return $this->col_name_type->unpack($b, $handle_serialize);
+ }
+
+ public function pack_key($key, $handle_serialize=false) {
+ if (!$this->autopack_keys || $key === "")
+ return $key;
+ return $this->key_type->pack($key, true, null, $handle_serialize);
+ }
+
+ public function unpack_key($b, $handle_serialize=true) {
+ if (!$this->autopack_keys)
+ return $b;
+ return $this->key_type->unpack($b, $handle_serialize);
+ }
+
+ protected function get_data_type_for_col($col_name) {
+ if (isset($this->col_type_dict[$col_name]))
+ return $this->col_type_dict[$col_name];
+ else
+ return $this->cf_data_type;
+ }
+
+ protected function pack_value($value, $col_name) {
+ if (!$this->autopack_values)
+ return $value;
+
+ if (!is_scalar($col_name) || is_float($col_name))
+ $col_name = serialize($col_name);
+
+ if (isset($this->col_type_dict[$col_name])) {
+ $dtype = $this->col_type_dict[$col_name];
+ return $dtype->pack($value, false);
+ } else {
+ return $this->cf_data_type->pack($value, false);
+ }
+ }
+
+ protected function unpack_value($value, $col_name) {
+ if (!$this->autopack_values)
+ return $value;
+
+ if (!is_scalar($col_name) || is_float($col_name))
+ $col_name = serialize($col_name);
+
+ if (isset($this->col_type_dict[$col_name])) {
+ $dtype = $this->col_type_dict[$col_name];
+ return $dtype->unpack($value, false);
+ } else {
+ return $this->cf_data_type->unpack($value, false);
+ }
+ }
+
+ public function keyslices_to_array($keyslices) {
+ $ret = array();
+ if ($this->return_format == self::DICTIONARY_FORMAT) {
+ foreach($keyslices as $keyslice) {
+ $key = $this->unpack_key($keyslice->key);
+ $columns = $keyslice->columns;
+ $ret[$key] = $this->unpack_coscs($columns);
+ }
+ } else {
+ foreach($keyslices as $keyslice) {
+ $key = $this->unpack_key($keyslice->key, false);
+ $columns = $keyslice->columns;
+ $ret[] = array($key, $this->unpack_coscs($columns));
+ }
+ }
+ return $ret;
+ }
+
+ protected function unpack_coscs($array_of_coscs) {
+ if(count($array_of_coscs) == 0)
+ return $array_of_coscs;
+
+ $format = $this->return_format;
+ if ($format == self::DICTIONARY_FORMAT) {
+ return $this->coscs_to_dict($array_of_coscs);
+ } else if ($format == self::ARRAY_FORMAT) {
+ return $this->coscs_to_array($array_of_coscs);
+ } else { // self::OBJECT_FORMAT
+ return $this->unpack_coscs_attrs($array_of_coscs);
+ }
+ }
+
+ protected function coscs_to_dict($array_of_coscs) {
+ $ret = array();
+ $first = $array_of_coscs[0];
+ if($first->column) { // normal columns
+ foreach($array_of_coscs as $cosc) {
+ $name = $this->unpack_name($cosc->column->name, false);
+ $value = $this->unpack_value($cosc->column->value, $cosc->column->name);
+ $ret[$name] = $value;
+ }
+ } else if ($first->counter_column) {
+ foreach($array_of_coscs as $cosc) {
+ $name = $this->unpack_name($cosc->counter_column->name, false);
+ $ret[$name] = $cosc->counter_column->value;
+ }
+ }
+ return $ret;
+ }
+
+ protected function coscs_to_array($array_of_coscs) {
+ $ret = array();
+ $first = $array_of_coscs[0];
+ if($first->column) { // normal columns
+ foreach($array_of_coscs as $cosc) {
+ $name = $this->unpack_name(
+ $cosc->column->name, false, $handle_serialize=false);
+ $value = $this->unpack_value($cosc->column->value, $cosc->column->name);
+ $ret[] = array($name, $value);
+ }
+ } else if ($first->counter_column) {
+ foreach($array_of_coscs as $cosc) {
+ $name = $this->unpack_name(
+ $cosc->counter_column->name, false, $handle_serialize=false);
+ $ret[] = array($name, $cosc->counter_column->value);
+ }
+ }
+ return $ret;
+ }
+
+ protected function unpack_coscs_attrs($array_of_coscs) {
+ $ret = array();
+ $first = $array_of_coscs[0];
+ if($first->column) { // normal columns
+ foreach($array_of_coscs as $cosc) {
+ $col = $cosc->column;
+ $col->name = $this->unpack_name(
+ $col->name, false, $handle_serialize=false);
+ $col->value = $this->unpack_value($col->value, $col->name);
+ $ret[] = $col;
+ }
+ } else { // counter columns
+ foreach($array_of_coscs as $cosc) {
+ $col = $cosc->counter_column;
+ $col->name = $this->unpack_name(
+ $col->name, false, $handle_serialize=false);
+ $ret[] = $col;
+ }
+ }
+ return $ret;
+ }
+
+ public function make_mutation($array, $timestamp=null, $ttl=null) {
+ $coscs = $this->pack_data($array, $timestamp, $ttl);
+ $ret = array();
+ foreach($coscs as $cosc) {
+ $mutation = new Mutation();
+ $mutation->column_or_supercolumn = $cosc;
+ $ret[] = $mutation;
+ }
+ return $ret;
+ }
+
+ protected function pack_data($data, $timestamp=null, $ttl=null) {
+ if($timestamp === null)
+ $timestamp = Clock::get_time();
+
+ if ($this->insert_format == self::DICTIONARY_FORMAT) {
+ return $this->dict_to_coscs($data, $timestamp, $ttl);
+ } else if ($this->insert_format == self::ARRAY_FORMAT) {
+ return $this->array_to_coscs($data, $timestamp, $ttl);
+ } else {
+ throw new UnexpectedValueException("Bad insert_format selected");
+ }
+ }
+
+ protected function dict_to_coscs($data, $timestamp, $ttl) {
+ $have_counters = $this->has_counters;
+ $ret = array();
+ foreach ($data as $name => $value) {
+ $c_or_sc = new ColumnOrSuperColumn();
+ if($have_counters) {
+ $sub = new CounterColumn();
+ $c_or_sc->counter_column = $sub;
+ } else {
+ $sub = new Column();
+ $c_or_sc->column = $sub;
+ $sub->timestamp = $timestamp;
+ $sub->ttl = $ttl;
+ }
+ $sub->name = $this->pack_name(
+ $name, false, self::NON_SLICE, true);
+ $sub->value = $this->pack_value($value, $name);
+ $ret[] = $c_or_sc;
+ }
+ return $ret;
+ }
+
+ protected function array_to_coscs($data, $timestamp, $ttl) {
+ $have_counters = $this->has_counters;
+ $ret = array();
+ foreach ($data as $col) {
+ list($name, $value) = $col;
+ $c_or_sc = new ColumnOrSuperColumn();
+ if($have_counters) {
+ $sub = new CounterColumn();
+ $c_or_sc->counter_column = $sub;
+ } else {
+ $sub = new Column();
+ $c_or_sc->column = $sub;
+ $sub->timestamp = $timestamp;
+ $sub->ttl = $ttl;
+ }
+ $sub->name = $this->pack_name(
+ $name, false, self::NON_SLICE, false);
+ $sub->value = $this->pack_value($value, $name);
+ $ret[] = $c_or_sc;
+ }
+ return $ret;
+ }
+}
View
40 include/phpcassa/ColumnSlice.php
@@ -0,0 +1,40 @@
+<?php
+namespace phpcassa;
+
+use cassandra\SliceRange;
+
+/**
+ * Represents a range of columns to slice from a row, multiple rows,
+ * or a super column.
+ *
+ * @package phpcassa
+ */
+class ColumnSlice extends SliceRange {
+
+ /** The default limit to the number of columns retrieved in queries. */
+ const DEFAULT_COLUMN_COUNT = 100; // default max # of columns for get()
+
+ /** The maximum number number of columns that can be fetch at once. */
+ const MAX_COUNT = 2147483647; # 2^31 - 1
+
+ /**
+ * Defines a range of columns.
+ *
+ * @param mixed $start the column to start with, or '' for the
+ * beginning of the row
+ * @param mixed $finish the column to finish with, or '' for the
+ * end of the row
+ * @param int $count an upper bound on the number of columns to
+ * fetch. The default limit is 100 columns.
+ * @param bool $reversed whether or not to reverse the column
+ * slice, going backwards from $start to $finish.
+ */
+ function __construct($start="", $finish="",
+ $count=self::DEFAULT_COLUMN_COUNT, $reversed=False) {
+ parent::__construct();
+ $this->start = $start;
+ $this->finish = $finish;
+ $this->count = $count;
+ $this->reversed = $reversed;
+ }
+}
View
181 include/phpcassa/connection.php → include/phpcassa/Connection/ConnectionPool.php
@@ -1,114 +1,19 @@
<?php
-$GLOBALS['THRIFT_ROOT'] = (isset($GLOBALS['THRIFT_ROOT'])) ? $GLOBALS['THRIFT_ROOT'] : dirname(__FILE__) . '/thrift/';
-require_once $GLOBALS['THRIFT_ROOT'].'/packages/cassandra/Cassandra.php';
-require_once $GLOBALS['THRIFT_ROOT'].'/transport/TSocket.php';
-require_once $GLOBALS['THRIFT_ROOT'].'/protocol/TBinaryProtocol.php';
-require_once $GLOBALS['THRIFT_ROOT'].'/transport/TFramedTransport.php';
-require_once $GLOBALS['THRIFT_ROOT'].'/transport/TBufferedTransport.php';
+namespace phpcassa\Connection;
-/**
- * The ConnectionPool was unable to open a connection to any of the
- * servers in the provided list.
-